diff --git a/Directory.Build.props b/Directory.Build.props index b55d07820..5e69a2809 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -22,9 +22,11 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb $(AllowedReferenceRelatedFileExtensions);.pdb + + true + - - + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 607d9460f..86b35bc7a 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,12 +1,8 @@  - true $(BaseIntermediateOutputPath)\GeneratedFiles - - - diff --git a/benchmarks/Pipeline/Pipeline.csproj b/benchmarks/Pipeline/Pipeline.csproj index f9f41c6c0..15cca63e3 100644 --- a/benchmarks/Pipeline/Pipeline.csproj +++ b/benchmarks/Pipeline/Pipeline.csproj @@ -1,7 +1,7 @@ - net472;netcoreapp2.1;netcoreapp3.1 + net472;netcoreapp3.1 Exe false diff --git a/docs/lsp.md b/docs/lsp.md index 8a9cdda14..4d393cc98 100644 --- a/docs/lsp.md +++ b/docs/lsp.md @@ -4,7 +4,19 @@ The goal of this library is to implement [Language Server Protocol](https://micr Included in this library is a full-fidelity `LanguageServer` but also full `LanguageClient` implementation that could be implemented in an editor, but mainly it is used to help make Unit Testing easier, more consistent (and maybe even fun!). -# Creating a JsonRpcServer +# Concepts +The language server is built oin a few concepts. At it's core is the [MediatR](https://github.com/jbogard/MediatR) library that you will build language specific handlers around. Around that core is a bunch of knowledge of the LSP protocol +with the goal of making it more ".NET" like and less protocol centric. + +LSP revolves around features ( eg Completion, Hover, etc ) that define the inputs (request object) the outputs (response object) as well as Client Capabilities and Server Registration Options. + +## Client Capabilities +These determine what features are supported by the client, and each has a different set of capabilities. The [specification](https://microsoft.github.io/language-server-protocol/) explains each feature and the requirements of each. + +## Server Registration Options +The protocol defines two kinds of registration, static and dynamic. Dynamic registration, when it's supported, allows you to register features with the client on demand. Static registration is returned to the client during the initialization phase that explains what features the server supports. Dynamic and Static registration cannot be mixed. If you register something statically, you cannot register the same thing dynamically, otherwise the client will register both features twice. + +# Creating a Language Server or Client `LanguageServer` or `LanguageClient` can be created through two methods. ## Standalone diff --git a/docs/source-generation.md b/docs/source-generation.md new file mode 100644 index 000000000..717bc2480 --- /dev/null +++ b/docs/source-generation.md @@ -0,0 +1,824 @@ +# Source Generators +We have built a few source generators to help with aid with implementing the plumbing of all the things. The goals of using source generation this way is to ensure that errors and mistakes are avoided and don't cause issues. + +## Auto Implementation Properties +The following interfaces will automatically implement themselves so you don't have to worry about it. + +* `IWorkDoneProgressParams` +* `IPartialItemsRequest` +* `IPartialItemRequest` +* `ITextDocumentRegistrationOptions` +* `IWorkDoneProgressOptions` +* `IStaticRegistrationOptions` + +## JSON RPC Generation Attributes + +The general JSON RPC Attributes have logic for LSP and DAP but that logic only kicks in in the correct types and/or attributes is in place. + +### `[GenerateHandler([[[""], Name = ""], AllowDerivedRequests = true])]` +Generates an interface based on the given request object, within the optional namespace if provided. +You may also provide a specific name that will be used for the interface and base class names. The name format is `IHandler` and `HandlerBase`. + +There is special logic to handle request objects that use the `IPartialItemRequest<,>` or `IPartialItemsRequest<,>` interfaces. This emit another base class `PartialHandlerBase` that implements the right stuff for creating a handler that works with the partial spec. + +Certain MediatR request types will map to different matters. +* `IRequest` - Will map as a request +* `IRequest` - Will map as a notification +* `IJsonRpcRequest` - Will map as a `Task` returning request. + +Example Request Object: +```c# + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client", Name = "RegisterCapability"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) + ] + public class RegistrationParams : IJsonRpcRequest + { + public RegistrationContainer Registrations { get; set; } = null!; + } +``` + +Example Output +```c# +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ + [Parallel, Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public interface IRegisterCapabilityHandler : IJsonRpcRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public class RegisterCapabilityHandlerBase : AbstractHandlers.Request, IRegisterCapabilityHandler + { + } +#nullable restore +``` +Given `AllowDerivedRequests` an additional generic handler will be created. + +Example Request Object: +```c# + [Parallel] + [Method(RequestNames.Launch, Direction.ClientToServer)] + [ + GenerateHandler(Name = "Launch", AllowDerivedRequests = true), + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class LaunchRequestArguments : IRequest + { + /// + /// If noDebug is true the launch request should launch the program without enabling debugging. + /// + [Optional] + public bool NoDebug { get; set; } + + /// + /// Optional data from the previous, restarted session. + /// The data is sent as the 'restart' attribute of the 'terminated' event. + /// The client should leave the data intact. + /// + [Optional] + [JsonProperty(PropertyName = "__restart")] + public JToken? Restart { get; set; } + + [JsonExtensionData] public IDictionary ExtensionData { get; set; } = new Dictionary(); + } + + public class LaunchResponse + { + } +``` + +Example Output: +```c# + [Parallel, Method(RequestNames.Launch, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public interface ILaunchHandler : IJsonRpcRequestHandler where T : LaunchRequestArguments + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public class LaunchHandlerBase : AbstractHandlers.Request, ILaunchHandler where T : LaunchRequestArguments + { + } + + public interface ILaunchHandler : ILaunchHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public class LaunchHandlerBase : LaunchHandlerBase, ILaunchHandler + { + } +``` + + +### `[GenerateHandlerMethods([params Type[] registryTypes])]` +Generates helper methods for registering this as a delegate. This is useful in more functional scenarios and more importantly in unit testing scenarios. + +You can provide a list of registry types, these are the `this` item in a given extension method. If not provided it will attempt to infer the usage. + +Common registries are: +* `IJsonRpcServerRegistry` +* `ILanguageClientRegistry` +* `ILanguageServerRegistry` +* `IDebugAdapterClientRegistry` +* `IDebugAdapterServerRegistry` + +Example request: + +```c# + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client", Name = "RegisterCapability"), + GenerateHandlerMethods + ] + public class RegistrationParams : IJsonRpcRequest + { + public RegistrationContainer Registrations { get; set; } = null!; + } +``` + +Example output: + +```c# +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class RegisterCapabilityExtensions + { + public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(handler)); + public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(handler)); + } +} +``` + + +### `[GenerateRequestMethods([params Type[] proxyTypes])]` +Generates helper methods for calling the notification or the delegate. This is useful for hinting to the user what methods there are to call on a given class. + +You can provide a list of proxy types, these are the `this` item in a given extension method. If not provided it will attempt to infer the usage. + +Common proxy types are anything that implements `IResponseRouter`: + * `ILanguageProtocolProxy` + * `ILanguageClientProxy` + * `IClientLanguageClient` + * `IGeneralLanguageClient` + * `ITextDocumentLanguageClient` + * `IWindowLanguageClient` + * `IWorkspaceLanguageClient` + * `ILanguageServerProxy` + * `IClientLanguageServer` + * `IGeneralLanguageServer` + * `ITextDocumentLanguageServer` + * `IWindowLanguageServer` + * `IWorkspaceLanguageServer` + * `IDebugAdapterProtocolProxy` + * `IDebugAdapterClientProxy` + * `IDebugAdapterServerProxy` + +Example request: + +```c# + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client", Name = "RegisterCapability"), + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) + ] + public class RegistrationParams : IJsonRpcRequest + { + public RegistrationContainer Registrations { get; set; } = null!; + } +``` + +Example output: + +```c# +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class RegisterCapabilityExtensions + { + public static Task RegisterCapability(this IClientLanguageServer mediator, RegistrationParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task RegisterCapability(this ILanguageServer mediator, RegistrationParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +} +``` + +## LSP Generation Attributes + +### `CapabilityAttribute` / `RegistrationOptionsAttribute` / `ResolverAttribute` +These attributes are used to generate the "correct" pieces. Some features do not have capabilities, some do not have registration, others both and some have none. + +* `CapabilityAttribute` - Defines the capability type to be used. +* `RegistrationOptionsAttribute` - Defines the registration type to be used. +* `ResolverAttribute` - Defines the type that this feature will use it's resolved item + * This is for the features that model around the resolve pattern, such as CodeLens or Completion. + * This only works with that specific pattern + +Example Request: +```c# + namespace Models + { + [Parallel] + [Method(TextDocumentNames.References, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "References"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(ReferenceRegistrationOptions)), Capability(typeof(ReferenceCapability))] + public partial class ReferenceParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + public ReferenceContext Context { get; set; } = null!; + } + public class ReferenceContext + { + /// + /// Include the declaration of the current symbol. + /// + public bool IncludeDeclaration { get; set; } + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.ReferencesProvider))] + public partial class ReferenceRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.References))] + public partial class ReferenceCapability : DynamicCapability, ConnectedCapability + { + } + } +``` + +Example Output: +```c# +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + public partial class ReferenceParams + { + [Optional] + public ProgressToken? WorkDoneToken + { + get; + set; + } + + [Optional] + public ProgressToken? PartialResultToken + { + get; + set; + } + } +} + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ + [Parallel, Method(TextDocumentNames.References, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IReferencesHandler : IJsonRpcRequestHandler, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class ReferencesHandlerBase : AbstractHandlers.Request, IReferencesHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class ReferencesPartialHandlerBase : AbstractHandlers.PartialResults, IReferencesHandler + { + protected ReferencesPartialHandlerBase(System.Guid id, IProgressManager progressManager): base(progressManager, LocationContainer.From) + { + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class ReferencesExtensions + { + public static ILanguageServerRegistry OnReferences(this ILanguageServerRegistry registry, Func> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnReferences(this ILanguageServerRegistry registry, Func> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnReferences(this ILanguageServerRegistry registry, Func> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveReferences(this ILanguageServerRegistry registry, Action>> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationContainer.From)); + } + + public static ILanguageServerRegistry ObserveReferences(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationContainer.From)); + } + + public static ILanguageServerRegistry ObserveReferences(this ILanguageServerRegistry registry, Action>, ReferenceCapability, CancellationToken> handler, Func registrationOptions) + { + return registry.AddHandler(TextDocumentNames.References, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationContainer.From)); + } + + public static IRequestProgressObservable, LocationContainer> RequestReferences(this ITextDocumentLanguageClient mediator, ReferenceParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationContainer(value), cancellationToken); + public static IRequestProgressObservable, LocationContainer> RequestReferences(this ILanguageClient mediator, ReferenceParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationContainer(value), cancellationToken); + } +} +``` + +### `GenerateTypedDataAttribute` + +This leverages two interfaces `ICanHaveData` and `ICanBeResolved` they are identical interfaces but just a slightly different in overall meaning. + +This attributes takes a class that implements that interface and creates a copy of the class with one generic type parameter. +Then implements all the required logic to make that type work and interact with it's non-strongly typed friend. This includes methods and implict operators for conversion. + +Example Object: +```c# + /// + /// A code lens represents a command that should be shown along with + /// source text, like the number of references, a way to run tests, etc. + /// + /// A code lens is _unresolved_ when no command is associated to it. For performance + /// reasons the creation of a code lens and resolving should be done in two stages. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CodeLensResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateTypedData, + GenerateContainer + ] + [RegistrationOptions(typeof(CodeLensRegistrationOptions)), Capability(typeof(CodeLensCapability))] + public partial class CodeLens : IRequest, ICanBeResolved + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; set; } = null!; + + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command { get; set; } + + /// + /// A data entry field that is preserved on a code lens item between + /// a code lens and a code lens resolve request. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"{Range}{( Command != null ? $" {Command}" : "" )}"; + + /// + public override string ToString() => DebuggerDisplay; + } +``` + +Example Response: +```c# +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + public partial class CodeLens + { + public CodeLens WithData(TData data) + where TData : HandlerIdentity? + { + return new CodeLens{Range = Range, Command = Command, Data = data}; + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static CodeLens? From(CodeLens? item) + where T : HandlerIdentity? => item switch + { + not null => item, _ => null + } + + ; + } + + /// + /// A code lens represents a command that should be shown along with + /// source text, like the number of references, a way to run tests, etc. + /// + /// A code lens is _unresolved_ when no command is associated to it. For performance + /// reasons the creation of a code lens and resolving should be done in two stages. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [RegistrationOptions(typeof(CodeLensRegistrationOptions)), Capability(typeof(CodeLensCapability))] + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class CodeLens : ICanBeResolved where T : HandlerIdentity? + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range + { + get; + set; + } + + = null !; + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command + { + get; + set; + } + + /// + /// A data entry field that is preserved on a code lens item between + /// a code lens and a code lens resolve request. + /// + [Optional] + public T Data + { + get => ((ICanBeResolved)this).Data?.ToObject()!; + set => ((ICanBeResolved)this).Data = JToken.FromObject(value); + } + + private string DebuggerDisplay => $"{Range}{(Command != null ? $" {Command}" : "")}"; + /// + public override string ToString() => DebuggerDisplay; + public CodeLens WithData(TData data) + where TData : HandlerIdentity? + { + return new CodeLens{Range = Range, Command = Command, Data = data}; + } + + JToken? ICanBeResolved.Data + { + get; + set; + } + + private JToken? JData + { + get => ((ICanBeResolved)this).Data; + set => ((ICanBeResolved)this).Data = value; + } + + public static implicit operator CodeLens(CodeLens value) => new CodeLens{Range = value.Range, Command = value.Command, JData = ((ICanBeResolved)value).Data}; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("value")] + public static implicit operator CodeLens? (CodeLens? value) => value switch + { + not null => new CodeLens{Range = value.Range, Command = value.Command, Data = ((ICanBeResolved)value).Data}, _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static CodeLens? From(CodeLens? item) => item switch + { + not null => item, _ => null + } + + ; + } + + public partial class CodeLensContainer : ContainerBase> where T : HandlerIdentity? + { + public CodeLensContainer(): this(Enumerable.Empty>()) + { + } + + public CodeLensContainer(IEnumerable> items): base(items) + { + } + + public CodeLensContainer(params CodeLens[] items): base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(IEnumerable>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeLensContainer? (CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(params CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeLensContainer? (Collection>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(Collection>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeLensContainer? (List>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(List>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeLensContainer? (in ImmutableArray>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(in ImmutableArray>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeLensContainer? (ImmutableList>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeLensContainer? From(ImmutableList>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("container")] + public static implicit operator CodeLensContainer? (CodeLensContainer? container) => container switch + { + not null => new CodeLensContainer(container.Select(value => (CodeLens)value)), _ => null + } + + ; + } +} +``` + +### `GenerateContainerAttribute` + +This is very simply it creates a class that derives from `ContainerBase` and implements conversion methods and operators. + +This leverages two interfaces `ICanHaveData` and `ICanBeResolved` they are identical interfaces but just a slightly different in overall meaning. + +This attributes takes a class that implements that interface and creates a copy of the class with one generic type parameter. +Then implements all the required logic to make that type work and interact with it's non-strongly typed friend. This includes methods and implict operators for conversion. + +Example Object: +```c# + /// + /// A code lens represents a command that should be shown along with + /// source text, like the number of references, a way to run tests, etc. + /// + /// A code lens is _unresolved_ when no command is associated to it. For performance + /// reasons the creation of a code lens and resolving should be done in two stages. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CodeLensResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateTypedData, + GenerateContainer + ] + [RegistrationOptions(typeof(CodeLensRegistrationOptions)), Capability(typeof(CodeLensCapability))] + public partial class CodeLens : IRequest, ICanBeResolved + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; set; } = null!; + + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command { get; set; } + + /// + /// A data entry field that is preserved on a code lens item between + /// a code lens and a code lens resolve request. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"{Range}{( Command != null ? $" {Command}" : "" )}"; + + /// + public override string ToString() => DebuggerDisplay; + } +``` + +Example Response: +```c# +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class CodeActionContainer : ContainerBase + { + public CodeActionContainer(): this(Enumerable.Empty()) + { + } + + public CodeActionContainer(IEnumerable items): base(items) + { + } + + public CodeActionContainer(params CodeAction[] items): base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(IEnumerable? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeActionContainer? (CodeAction[] items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(params CodeAction[] items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeActionContainer? (Collection? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(Collection? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeActionContainer? (List? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(List? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeActionContainer? (in ImmutableArray? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(in ImmutableArray? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator CodeActionContainer? (ImmutableList? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static CodeActionContainer? From(ImmutableList? items) => items switch + { + not null => new CodeActionContainer(items), _ => null + } + + ; + } +} +``` + +### `GenerateRegistrationOptionsAttribute` +This attribute is used to the static version of the registration options and generate a default converter if none is provided. + +Example Options +```c# + [GenerateRegistrationOptions(nameof(ServerCapabilities.ImplementationProvider))] + public partial class ImplementationRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions { } +``` + +Example Output: +```c# + [RegistrationOptionsConverterAttribute(typeof(ImplementationRegistrationOptionsConverter))] + public partial class ImplementationRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + public DocumentSelector? DocumentSelector + { + get; + set; + } + + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + + [Optional] + public string? Id + { + get; + set; + } + + class ImplementationRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public ImplementationRegistrationOptionsConverter(): base(nameof(ServerCapabilities.ImplementationProvider)) + { + } + + public override StaticOptions Convert(ImplementationRegistrationOptions source) + { + return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress, Id = source.Id}; + } + } + + public partial class StaticOptions : IWorkDoneProgressOptions, IStaticRegistrationOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + + [Optional] + public string? Id + { + get; + set; + } + } + } +``` diff --git a/sample/SampleServer/DidChangeWatchedFilesHandler.cs b/sample/SampleServer/DidChangeWatchedFilesHandler.cs index 320569019..eca65e2d8 100644 --- a/sample/SampleServer/DidChangeWatchedFilesHandler.cs +++ b/sample/SampleServer/DidChangeWatchedFilesHandler.cs @@ -13,8 +13,6 @@ internal class DidChangeWatchedFilesHandler : IDidChangeWatchedFilesHandler public Task Handle(DidChangeWatchedFilesParams request, CancellationToken cancellationToken) => Unit.Task; - public void SetCapability(DidChangeWatchedFilesCapability capability) - { - } + public DidChangeWatchedFilesRegistrationOptions GetRegistrationOptions(DidChangeWatchedFilesCapability capability, ClientCapabilities clientCapabilities) => new DidChangeWatchedFilesRegistrationOptions(); } } diff --git a/sample/SampleServer/FoldingRangeHandler.cs b/sample/SampleServer/FoldingRangeHandler.cs index 94423c29c..81d3f1362 100644 --- a/sample/SampleServer/FoldingRangeHandler.cs +++ b/sample/SampleServer/FoldingRangeHandler.cs @@ -29,8 +29,8 @@ CancellationToken cancellationToken ) ); - public void SetCapability(FoldingRangeCapability capability) - { - } + public FoldingRangeRegistrationOptions GetRegistrationOptions(FoldingRangeCapability capability, ClientCapabilities clientCapabilities) => new FoldingRangeRegistrationOptions { + DocumentSelector = DocumentSelector.ForLanguage("csharp") + }; } } diff --git a/sample/SampleServer/SemanticTokensHandler.cs b/sample/SampleServer/SemanticTokensHandler.cs index 0bbe5a848..01c54f241 100644 --- a/sample/SampleServer/SemanticTokensHandler.cs +++ b/sample/SampleServer/SemanticTokensHandler.cs @@ -18,16 +18,7 @@ public class SemanticTokensHandler : SemanticTokensHandlerBase { private readonly ILogger _logger; - public SemanticTokensHandler(ILogger logger) : base( - new SemanticTokensRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp"), - Legend = new SemanticTokensLegend(), - Full = new SemanticTokensCapabilityRequestFull { - Delta = true - }, - Range = true - } - ) => + public SemanticTokensHandler(ILogger logger) => _logger = logger; public override async Task Handle( @@ -83,7 +74,7 @@ CancellationToken cancellationToken protected override Task GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken) => - Task.FromResult(new SemanticTokensDocument(GetRegistrationOptions().Legend)); + Task.FromResult(new SemanticTokensDocument(RegistrationOptions.Legend)); private IEnumerable RotateEnum(IEnumerable values) @@ -94,6 +85,18 @@ private IEnumerable RotateEnum(IEnumerable values) yield return item; } } + + protected override SemanticTokensRegistrationOptions CreateRegistrationOptions(SemanticTokensCapability capability, ClientCapabilities clientCapabilities) => new SemanticTokensRegistrationOptions { + DocumentSelector = DocumentSelector.ForLanguage("csharp"), + Legend = new SemanticTokensLegend() { + TokenModifiers = capability.TokenModifiers, + TokenTypes = capability.TokenTypes + }, + Full = new SemanticTokensCapabilityRequestFull { + Delta = true + }, + Range = true + }; } #pragma warning restore 618 } diff --git a/sample/SampleServer/TextDocumentHandler.cs b/sample/SampleServer/TextDocumentHandler.cs index 937771370..94145e067 100644 --- a/sample/SampleServer/TextDocumentHandler.cs +++ b/sample/SampleServer/TextDocumentHandler.cs @@ -13,11 +13,12 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone; using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; + #pragma warning disable CS0618 namespace SampleServer { - internal class TextDocumentHandler : ITextDocumentSyncHandler + internal class TextDocumentHandler : TextDocumentSyncHandlerBase { private readonly ILogger _logger; private readonly ILanguageServerConfiguration _configuration; @@ -28,12 +29,7 @@ internal class TextDocumentHandler : ITextDocumentSyncHandler } ); - private SynchronizationCapability _capability; - - public TextDocumentHandler( - ILogger logger, Foo foo, - ILanguageServerConfiguration configuration - ) + public TextDocumentHandler(ILogger logger, Foo foo, ILanguageServerConfiguration configuration) { _logger = logger; _configuration = configuration; @@ -42,7 +38,7 @@ ILanguageServerConfiguration configuration public TextDocumentSyncKind Change { get; } = TextDocumentSyncKind.Full; - public Task Handle(DidChangeTextDocumentParams notification, CancellationToken token) + public override Task Handle(DidChangeTextDocumentParams notification, CancellationToken token) { _logger.LogCritical("Critical"); _logger.LogDebug("Debug"); @@ -51,16 +47,7 @@ public Task Handle(DidChangeTextDocumentParams notification, CancellationT return Unit.Task; } - TextDocumentChangeRegistrationOptions IRegistration. - GetRegistrationOptions() => - new TextDocumentChangeRegistrationOptions { - DocumentSelector = _documentSelector, - SyncKind = Change - }; - - public void SetCapability(SynchronizationCapability capability) => _capability = capability; - - public async Task Handle(DidOpenTextDocumentParams notification, CancellationToken token) + public override async Task Handle(DidOpenTextDocumentParams notification, CancellationToken token) { await Task.Yield(); _logger.LogInformation("Hello world!"); @@ -68,12 +55,7 @@ public async Task Handle(DidOpenTextDocumentParams notification, Cancellat return Unit.Value; } - TextDocumentRegistrationOptions IRegistration.GetRegistrationOptions() => - new TextDocumentRegistrationOptions { - DocumentSelector = _documentSelector, - }; - - public Task Handle(DidCloseTextDocumentParams notification, CancellationToken token) + public override Task Handle(DidCloseTextDocumentParams notification, CancellationToken token) { if (_configuration.TryGetScopedConfiguration(notification.TextDocument.Uri, out var disposable)) { @@ -83,28 +65,20 @@ public Task Handle(DidCloseTextDocumentParams notification, CancellationTo return Unit.Task; } - public Task Handle(DidSaveTextDocumentParams notification, CancellationToken token) => Unit.Task; + public override Task Handle(DidSaveTextDocumentParams notification, CancellationToken token) => Unit.Task; - TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions() => - new TextDocumentSaveRegistrationOptions { - DocumentSelector = _documentSelector, - IncludeText = true - }; + protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) => new TextDocumentSyncRegistrationOptions() { + DocumentSelector = _documentSelector, + SyncKind = Change, + IncludeText = true + }; - public TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri) => new TextDocumentAttributes(uri, "csharp"); + public override TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri) => new TextDocumentAttributes(uri, "csharp"); } - internal class MyDocumentSymbolHandler : DocumentSymbolHandler + internal class MyDocumentSymbolHandler : IDocumentSymbolHandler { - public MyDocumentSymbolHandler() : base( - new DocumentSymbolRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp") - } - ) - { - } - - public override async Task Handle( + public async Task Handle( DocumentSymbolParams request, CancellationToken cancellationToken ) @@ -151,23 +125,26 @@ CancellationToken cancellationToken // await Task.Delay(2000, cancellationToken); return symbols; } + + public DocumentSymbolRegistrationOptions GetRegistrationOptions(DocumentSymbolCapability capability, ClientCapabilities clientCapabilities) => new DocumentSymbolRegistrationOptions { + DocumentSelector = DocumentSelector.ForLanguage("csharp") + }; } - internal class MyWorkspaceSymbolsHandler : WorkspaceSymbolsHandler + internal class MyWorkspaceSymbolsHandler : IWorkspaceSymbolsHandler { private readonly IServerWorkDoneManager _serverWorkDoneManager; private readonly IProgressManager _progressManager; private readonly ILogger _logger; - public MyWorkspaceSymbolsHandler(IServerWorkDoneManager serverWorkDoneManager, IProgressManager progressManager, ILogger logger) : - base(new WorkspaceSymbolRegistrationOptions()) + public MyWorkspaceSymbolsHandler(IServerWorkDoneManager serverWorkDoneManager, IProgressManager progressManager, ILogger logger) { _serverWorkDoneManager = serverWorkDoneManager; _progressManager = progressManager; _logger = logger; } - public override async Task> Handle( + public async Task> Handle( WorkspaceSymbolParams request, CancellationToken cancellationToken ) @@ -272,5 +249,7 @@ CancellationToken cancellationToken ); } } + + public WorkspaceSymbolRegistrationOptions GetRegistrationOptions(WorkspaceSymbolCapability capability, ClientCapabilities clientCapabilities) => new WorkspaceSymbolRegistrationOptions(); } } diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index 1c7d12043..e59c5f956 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -28,6 +28,7 @@ namespace OmniSharp.Extensions.LanguageServer.Client { + [BuiltIn] public class LanguageClient : JsonRpcServerBase, ILanguageClient { private readonly Connection _connection; @@ -35,7 +36,7 @@ public class LanguageClient : JsonRpcServerBase, ILanguageClient private readonly ILspClientReceiver _receiver; private readonly TextDocumentIdentifiers _textDocumentIdentifiers; - private readonly IHandlerCollection _collection; + private readonly SharedHandlerCollection _collection; // private readonly IEnumerable _initializeDelegates; // private readonly IEnumerable _initializedDelegates; @@ -143,8 +144,10 @@ internal LanguageClient( IProgressManager progressManager, IClientWorkDoneManager clientWorkDoneManager, IRegistrationManager registrationManager, - ILanguageClientWorkspaceFoldersManager languageClientWorkspaceFoldersManager, IEnumerable initializeDelegates, - IEnumerable initializeHandlers, IEnumerable initializedDelegates, + ILanguageClientWorkspaceFoldersManager languageClientWorkspaceFoldersManager, + IEnumerable initializeDelegates, + IEnumerable initializeHandlers, + IEnumerable initializedDelegates, IEnumerable initializedHandlers, LspSerializer serializer, InstanceHasStarted instanceHasStarted @@ -250,12 +253,9 @@ public async Task Initialize(CancellationToken token) _serializer.JsonSerializer.Populate(reader, _clientCapabilities); } + _collection.Initialize(); RegisterCapabilities(_clientCapabilities); - WorkDoneManager.Initialize(@params.Capabilities.Window); - - ClientSettings = @params; - await LanguageProtocolEventingHelper.Run( _initializeDelegates, (handler, ct) => handler(this, @params, ct), @@ -265,6 +265,10 @@ await LanguageProtocolEventingHelper.Run( token ).ConfigureAwait(false); + WorkDoneManager.Initialize(@params.Capabilities.Window); + + ClientSettings = @params; + _connection.Open(); var serverParams = await SendRequest(ClientSettings, token).ConfigureAwait(false); diff --git a/src/Client/LanguageClientRegistrationManager.cs b/src/Client/LanguageClientRegistrationManager.cs index 1ef32e538..893025dea 100644 --- a/src/Client/LanguageClientRegistrationManager.cs +++ b/src/Client/LanguageClientRegistrationManager.cs @@ -19,13 +19,14 @@ namespace OmniSharp.Extensions.LanguageServer.Client { + [BuiltIn] internal class LanguageClientRegistrationManager : IRegisterCapabilityHandler, IUnregisterCapabilityHandler, IRegistrationManager, IDisposable { private readonly ISerializer _serializer; private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; private readonly ILogger _logger; private readonly ConcurrentDictionary _registrations; - private ReplaySubject> _registrationSubject = new ReplaySubject>(1); + private readonly ReplaySubject> _registrationSubject = new ReplaySubject>(1); public LanguageClientRegistrationManager( ISerializer serializer, diff --git a/src/Client/LanguageClientWorkspaceFoldersManager.cs b/src/Client/LanguageClientWorkspaceFoldersManager.cs index 050d6514d..c768335bc 100644 --- a/src/Client/LanguageClientWorkspaceFoldersManager.cs +++ b/src/Client/LanguageClientWorkspaceFoldersManager.cs @@ -14,6 +14,7 @@ namespace OmniSharp.Extensions.LanguageServer.Client { + [BuiltIn] internal class LanguageClientWorkspaceFoldersManager : ILanguageClientWorkspaceFoldersManager, IDisposable { private readonly IWorkspaceLanguageClient _client; diff --git a/src/Dap.Protocol/AbstractHandlers.cs b/src/Dap.Protocol/AbstractHandlers.cs new file mode 100644 index 000000000..ab80046e9 --- /dev/null +++ b/src/Dap.Protocol/AbstractHandlers.cs @@ -0,0 +1,23 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; + +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + public static class AbstractHandlers + { + public abstract class Request : + IJsonRpcRequestHandler + where TParams : IRequest + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class Notification : IJsonRpcRequestHandler + where TParams : IRequest + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + } +} diff --git a/src/Dap.Protocol/Dap.Protocol.csproj b/src/Dap.Protocol/Dap.Protocol.csproj index 40417c6b1..71f2b0ec2 100644 --- a/src/Dap.Protocol/Dap.Protocol.csproj +++ b/src/Dap.Protocol/Dap.Protocol.csproj @@ -27,24 +27,6 @@ - - - - - - - - - - - - - - - - - - MSBuild:GenerateCodeFromAttributes diff --git a/src/Dap.Protocol/DapReceiver.cs b/src/Dap.Protocol/DapReceiver.cs index 48c3a6d49..2d580b920 100644 --- a/src/Dap.Protocol/DapReceiver.cs +++ b/src/Dap.Protocol/DapReceiver.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using OmniSharp.Extensions.DebugAdapter.Protocol.Events; diff --git a/src/Dap.Protocol/Events/BreakpointEvent.cs b/src/Dap.Protocol/Events/BreakpointEvent.cs deleted file mode 100644 index f13a5d974..000000000 --- a/src/Dap.Protocol/Events/BreakpointEvent.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Breakpoint, Direction.ServerToClient)] - public class BreakpointEvent : IRequest - { - /// - /// The reason for the event. - /// Values: 'changed', 'new', 'removed', etc. - /// - public string Reason { get; set; } = null!; - - /// - /// The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values. - /// - public Breakpoint Breakpoint { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Events/BreakpointExtensions.cs b/src/Dap.Protocol/Events/BreakpointExtensions.cs deleted file mode 100644 index 3f19f24d6..000000000 --- a/src/Dap.Protocol/Events/BreakpointExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Breakpoint, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IBreakpointHandler : IJsonRpcNotificationHandler - { - } - - public abstract class BreakpointHandler : IBreakpointHandler - { - public abstract Task Handle(BreakpointEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/CapabilitiesEvent.cs b/src/Dap.Protocol/Events/CapabilitiesEvent.cs deleted file mode 100644 index 735d6ec48..000000000 --- a/src/Dap.Protocol/Events/CapabilitiesEvent.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Capabilities, Direction.ServerToClient)] - public class CapabilitiesEvent : IRequest - { - /// - /// The set of updated capabilities. - /// - public Capabilities Capabilities { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Events/CapabilitiesExtensions.cs b/src/Dap.Protocol/Events/CapabilitiesExtensions.cs deleted file mode 100644 index 3a4a3b5d0..000000000 --- a/src/Dap.Protocol/Events/CapabilitiesExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Capabilities, Direction.ServerToClient)] - [GenerateRequestMethods] - [GenerateHandlerMethods] - public interface ICapabilitiesHandler : IJsonRpcNotificationHandler - { - } - - public abstract class CapabilitiesHandler : ICapabilitiesHandler - { - public abstract Task Handle(CapabilitiesEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/ContinuedEvent.cs b/src/Dap.Protocol/Events/ContinuedEvent.cs deleted file mode 100644 index 23ff44751..000000000 --- a/src/Dap.Protocol/Events/ContinuedEvent.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Continued, Direction.ServerToClient)] - public class ContinuedEvent : IRequest - { - /// - /// The thread which was continued. - /// - public long ThreadId { get; set; } - - /// - /// If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued. - /// - [Optional] - public bool AllThreadsContinued { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ContinuedExtensions.cs b/src/Dap.Protocol/Events/ContinuedExtensions.cs deleted file mode 100644 index 80016a4a7..000000000 --- a/src/Dap.Protocol/Events/ContinuedExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Continued, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IContinuedHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ContinuedHandler : IContinuedHandler - { - public abstract Task Handle(ContinuedEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/ExitedEvent.cs b/src/Dap.Protocol/Events/ExitedEvent.cs deleted file mode 100644 index 76c7e8278..000000000 --- a/src/Dap.Protocol/Events/ExitedEvent.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Exited, Direction.ServerToClient)] - public class ExitedEvent : IRequest - { - /// - /// The exit code returned from the debuggee. - /// - public long ExitCode { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ExitedExtensions.cs b/src/Dap.Protocol/Events/ExitedExtensions.cs deleted file mode 100644 index 8a1f43481..000000000 --- a/src/Dap.Protocol/Events/ExitedExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Exited, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IExitedHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ExitedHandler : IExitedHandler - { - public abstract Task Handle(ExitedEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/IProgressEndHandler.cs b/src/Dap.Protocol/Events/IProgressEndHandler.cs deleted file mode 100644 index a63e4fc2f..000000000 --- a/src/Dap.Protocol/Events/IProgressEndHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.ProgressEnd, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IProgressEndHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ProgressEndHandlerBase : IProgressEndHandler - { - public abstract Task Handle(ProgressEndEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/IProgressStartHandler.cs b/src/Dap.Protocol/Events/IProgressStartHandler.cs deleted file mode 100644 index 29143b6dd..000000000 --- a/src/Dap.Protocol/Events/IProgressStartHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.ProgressStart, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IProgressStartHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ProgressStartHandlerBase : IProgressStartHandler - { - public abstract Task Handle(ProgressStartEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/IProgressUpdateHandler.cs b/src/Dap.Protocol/Events/IProgressUpdateHandler.cs deleted file mode 100644 index 1776fde5f..000000000 --- a/src/Dap.Protocol/Events/IProgressUpdateHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.ProgressUpdate, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IProgressUpdateHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ProgressUpdateHandlerBase : IProgressUpdateHandler - { - public abstract Task Handle(ProgressUpdateEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/InitializedEvent.cs b/src/Dap.Protocol/Events/InitializedEvent.cs deleted file mode 100644 index 818b69e49..000000000 --- a/src/Dap.Protocol/Events/InitializedEvent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Initialized, Direction.ServerToClient)] - public class InitializedEvent : IRequest - { - } -} diff --git a/src/Dap.Protocol/Events/InitializedExtensions.cs b/src/Dap.Protocol/Events/InitializedExtensions.cs deleted file mode 100644 index 0b0eceff0..000000000 --- a/src/Dap.Protocol/Events/InitializedExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Initialized, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IDebugAdapterInitializedHandler : IJsonRpcNotificationHandler - { - } - - public abstract class DebugAdapterInitializedHandler : IDebugAdapterInitializedHandler - { - public abstract Task Handle(InitializedEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/LoadedSourceEvent.cs b/src/Dap.Protocol/Events/LoadedSourceEvent.cs deleted file mode 100644 index a8b1fc27e..000000000 --- a/src/Dap.Protocol/Events/LoadedSourceEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.LoadedSource, Direction.ServerToClient)] - public class LoadedSourceEvent : IRequest - { - /// - /// The reason for the event. - /// - public LoadedSourceReason Reason { get; set; } - - /// - /// The new, changed, or removed source. - /// - public Source Source { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Events/LoadedSourceExtensions.cs b/src/Dap.Protocol/Events/LoadedSourceExtensions.cs deleted file mode 100644 index 1d539ff3a..000000000 --- a/src/Dap.Protocol/Events/LoadedSourceExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.LoadedSource, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ILoadedSourceHandler : IJsonRpcNotificationHandler - { - } - - public abstract class LoadedSourceHandler : ILoadedSourceHandler - { - public abstract Task Handle(LoadedSourceEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/LoadedSourceReason.cs b/src/Dap.Protocol/Events/LoadedSourceReason.cs deleted file mode 100644 index e0eafb3a9..000000000 --- a/src/Dap.Protocol/Events/LoadedSourceReason.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum LoadedSourceReason - { - New, Changed, Removed - } -} diff --git a/src/Dap.Protocol/Events/ModuleEvent.cs b/src/Dap.Protocol/Events/ModuleEvent.cs deleted file mode 100644 index cda325036..000000000 --- a/src/Dap.Protocol/Events/ModuleEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Module, Direction.ServerToClient)] - public class ModuleEvent : IRequest - { - /// - /// The reason for the event. - /// - public ModuleEventReason Reason { get; set; } - - /// - /// The new, changed, or removed module. In case of 'removed' only the module id is used. - /// - public Module Module { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Events/ModuleEventReason.cs b/src/Dap.Protocol/Events/ModuleEventReason.cs deleted file mode 100644 index 89c5cbbbc..000000000 --- a/src/Dap.Protocol/Events/ModuleEventReason.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum ModuleEventReason - { - New, Changed, Removed - } -} diff --git a/src/Dap.Protocol/Events/ModuleExtensions.cs b/src/Dap.Protocol/Events/ModuleExtensions.cs deleted file mode 100644 index c4dd61dee..000000000 --- a/src/Dap.Protocol/Events/ModuleExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Module, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IModuleHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ModuleHandler : IModuleHandler - { - public abstract Task Handle(ModuleEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/OutputEvent.cs b/src/Dap.Protocol/Events/OutputEvent.cs deleted file mode 100644 index 511e7cfb5..000000000 --- a/src/Dap.Protocol/Events/OutputEvent.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Output, Direction.ServerToClient)] - public class OutputEvent : IRequest - { - /// - /// The output category. If not specified, 'console' is assumed. - /// Values: 'console', 'stdout', 'stderr', 'telemetry', etc. - /// - [Optional] - public string? Category { get; set; } - - /// - /// The output to report. - /// - public string Output { get; set; } = null!; - - /// - /// If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. - /// - [Optional] - public long? VariablesReference { get; set; } - - /// - /// An optional source location where the output was produced. - /// - [Optional] - public Source? Source { get; set; } - - /// - /// An optional source location line where the output was produced. - /// - [Optional] - public long? Line { get; set; } - - /// - /// An optional source location column where the output was produced. - /// - [Optional] - public long? Column { get; set; } - - /// - /// Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format. - /// - [Optional] - public JToken? Data { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/OutputExtensions.cs b/src/Dap.Protocol/Events/OutputExtensions.cs deleted file mode 100644 index 355965f92..000000000 --- a/src/Dap.Protocol/Events/OutputExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Output, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IOutputHandler : IJsonRpcNotificationHandler - { - } - - public abstract class OutputHandler : IOutputHandler - { - public abstract Task Handle(OutputEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/ProcessEvent.cs b/src/Dap.Protocol/Events/ProcessEvent.cs deleted file mode 100644 index fa99cee52..000000000 --- a/src/Dap.Protocol/Events/ProcessEvent.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Process, Direction.ServerToClient)] - public class ProcessEvent : IRequest - { - /// - /// The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js. - /// - public string Name { get; set; } = null!; - - /// - /// The system process id of the debugged process. This property will be missing for non-system processes. - /// - [Optional] - public long? SystemProcessId { get; set; } - - /// - /// If true, the process is running on the same computer as the debug adapter. - /// - [Optional] - public bool IsLocalProcess { get; set; } - - /// - /// Describes how the debug engine started debugging this process. - /// 'launch': Process was launched under the debugger. - /// 'attach': Debugger attached to an existing process. - /// 'attachForSuspendedLaunch': A project launcher component has launched a new process in a suspended state and then asked the debugger to attach. - /// - [Optional] - public ProcessEventStartMethod? StartMethod { get; set; } - - /// - /// The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display. - /// - [Optional] - public long? PointerSize { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ProcessEventStartMethod.cs b/src/Dap.Protocol/Events/ProcessEventStartMethod.cs deleted file mode 100644 index c9685ea71..000000000 --- a/src/Dap.Protocol/Events/ProcessEventStartMethod.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum ProcessEventStartMethod - { - Launch, Attach, AttachForSuspendedLaunch - } -} diff --git a/src/Dap.Protocol/Events/ProcessExtensions.cs b/src/Dap.Protocol/Events/ProcessExtensions.cs deleted file mode 100644 index 482901dc4..000000000 --- a/src/Dap.Protocol/Events/ProcessExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Process, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IProcessHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ProcessHandler : IProcessHandler - { - public abstract Task Handle(ProcessEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/ProgressEndEvent.cs b/src/Dap.Protocol/Events/ProgressEndEvent.cs deleted file mode 100644 index 73202a906..000000000 --- a/src/Dap.Protocol/Events/ProgressEndEvent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.ProgressEnd, Direction.ServerToClient)] - public class ProgressEndEvent : ProgressEvent, IRequest - { - } -} diff --git a/src/Dap.Protocol/Events/ProgressEvent.cs b/src/Dap.Protocol/Events/ProgressEvent.cs deleted file mode 100644 index 8ef568601..000000000 --- a/src/Dap.Protocol/Events/ProgressEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - public abstract class ProgressEvent - { - /// - /// The ID that was introduced in the initial 'progressStart' event. - /// - public ProgressToken ProgressId { get; set; } - - /// - /// Optional, more detailed progress message. If omitted, the previous message (if any) is used. - /// - [Optional] - public string? Message { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ProgressStartEvent.cs b/src/Dap.Protocol/Events/ProgressStartEvent.cs deleted file mode 100644 index b1b21a54e..000000000 --- a/src/Dap.Protocol/Events/ProgressStartEvent.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.ProgressStart, Direction.ServerToClient)] - public class ProgressStartEvent : ProgressEvent, IRequest - { - /// - /// Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation. - /// - public string Title { get; set; } = null!; - - /// - /// The request ID that this progress report is related to. If specified a debug adapter is expected to emit - /// progress events for the long running request until the request has been either completed or cancelled. - /// If the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter. - /// - [Optional] - public int? RequestId { get; set; } - - /// - /// If true, the request that reports progress may be canceled with a 'cancel' request. - /// So this property basically controls whether the client should use UX that supports cancellation. - /// Clients that don't support cancellation are allowed to ignore the setting. - /// - [Optional] - public bool Cancellable { get; set; } - - /// - /// Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. - /// - [Optional] - public int? Percentage { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ProgressUpdateEvent.cs b/src/Dap.Protocol/Events/ProgressUpdateEvent.cs deleted file mode 100644 index 3bac1eee8..000000000 --- a/src/Dap.Protocol/Events/ProgressUpdateEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.ProgressUpdate, Direction.ServerToClient)] - public class ProgressUpdateEvent : ProgressEvent, IRequest - { - /// - /// Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. - /// - [Optional] - public double? Percentage { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/StoppedEvent.cs b/src/Dap.Protocol/Events/StoppedEvent.cs deleted file mode 100644 index c10dbd5f2..000000000 --- a/src/Dap.Protocol/Events/StoppedEvent.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Stopped, Direction.ServerToClient)] - public class StoppedEvent : IRequest - { - /// - /// The reason for the event. - /// For backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated). - /// Values: 'step', 'breakpoint', 'exception', 'pause', 'entry', 'goto', 'function breakpoint', 'data breakpoint', etc. - /// - public string Reason { get; set; } = null!; - - /// - /// The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated. - /// - [Optional] - public string? Description { get; set; } - - /// - /// The thread which was stopped. - /// - [Optional] - public long? ThreadId { get; set; } - - /// - /// A value of true hints to the frontend that this event should not change the focus. - /// - [Optional] - public bool PreserveFocusHint { get; set; } - - /// - /// Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI. - /// - [Optional] - public string? Text { get; set; } - - /// - /// If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped. - /// - The client should use this information to enable that all threads can be expanded to access their stacktraces. - /// - If the attribute is missing or false, only the thread with the given threadId can be expanded. - /// - [Optional] - public bool AllThreadsStopped { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/StoppedExtensions.cs b/src/Dap.Protocol/Events/StoppedExtensions.cs deleted file mode 100644 index 565491a86..000000000 --- a/src/Dap.Protocol/Events/StoppedExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Stopped, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStoppedHandler : IJsonRpcNotificationHandler - { - } - - public abstract class StoppedHandler : IStoppedHandler - { - public abstract Task Handle(StoppedEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/TerminatedEvent.cs b/src/Dap.Protocol/Events/TerminatedEvent.cs deleted file mode 100644 index fdb792d20..000000000 --- a/src/Dap.Protocol/Events/TerminatedEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Terminated, Direction.ServerToClient)] - public class TerminatedEvent : IRequest - { - /// - /// A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session. - /// The value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests. - /// - [Optional] - [JsonProperty(PropertyName = "__restart")] - public JToken? Restart { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/TerminatedExtensions.cs b/src/Dap.Protocol/Events/TerminatedExtensions.cs deleted file mode 100644 index b3a5bea30..000000000 --- a/src/Dap.Protocol/Events/TerminatedExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Terminated, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ITerminatedHandler : IJsonRpcNotificationHandler - { - } - - public abstract class TerminatedHandler : ITerminatedHandler - { - public abstract Task Handle(TerminatedEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Events/ThreadEvent.cs b/src/Dap.Protocol/Events/ThreadEvent.cs deleted file mode 100644 index d6ca4db28..000000000 --- a/src/Dap.Protocol/Events/ThreadEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Method(EventNames.Thread, Direction.ServerToClient)] - public class ThreadEvent : IRequest - { - /// - /// The reason for the event. - /// Values: 'started', 'exited', etc. - /// - public string Reason { get; set; } = null!; - - /// - /// The identifier of the thread. - /// - public long ThreadId { get; set; } - } -} diff --git a/src/Dap.Protocol/Events/ThreadExtensions.cs b/src/Dap.Protocol/Events/ThreadExtensions.cs deleted file mode 100644 index 3dd91c7ad..000000000 --- a/src/Dap.Protocol/Events/ThreadExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events -{ - [Parallel] - [Method(EventNames.Thread, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IThreadHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ThreadHandler : IThreadHandler - { - public abstract Task Handle(ThreadEvent request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Feature/Events/BreakpointFeature.cs b/src/Dap.Protocol/Feature/Events/BreakpointFeature.cs new file mode 100644 index 000000000..fe5bf491d --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/BreakpointFeature.cs @@ -0,0 +1,104 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Models + { + + /// + /// Information about a Breakpoint created in setBreakpoints or setFunctionBreakpoints. + /// + public class Breakpoint + { + /// + /// An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints. + /// + [Optional] + public long? Id { get; set; } + + /// + /// If true breakpoint could be set (but not necessarily at the desired location). + /// + public bool Verified { get; set; } + + /// + /// An optional message about the state of the breakpoint. This is shown to the user and can be used to explain why a breakpoint could not be verified. + /// + [Optional] + public string? Message { get; set; } + + /// + /// The source where the breakpoint is located. + /// + [Optional] + public Source? Source { get; set; } + + /// + /// The start line of the actual range covered by the breakpoint. + /// + [Optional] + public int? Line { get; set; } + + /// + /// An optional start column of the actual range covered by the breakpoint. + /// + [Optional] + public int? Column { get; set; } + + /// + /// An optional end line of the actual range covered by the breakpoint. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// An optional end column of the actual range covered by the breakpoint. If no end line is given, then the end column is assumed to be in the start line. + /// + [Optional] + public int? EndColumn { get; set; } + + /// + /// An optional memory reference to where the breakpoint is set. + /// + [Optional] + public string? InstructionReference { get; set; } + + /// + /// An optional offset from the instruction reference. + /// This can be negative. + /// + [Optional] + public int? Offset { get; set; } + } + } + namespace Events + { + [Parallel] + [Method(EventNames.Breakpoint, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class BreakpointEvent : IRequest + { + /// + /// The reason for the event. + /// Values: 'changed', 'new', 'removed', etc. + /// + public string Reason { get; set; } = null!; + + /// + /// The 'id' attribute is used to find the target breakpoint and the other attributes are used as the new values. + /// + public Breakpoint Breakpoint { get; set; } = null!; + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/CapabilitiesFeature.cs b/src/Dap.Protocol/Feature/Events/CapabilitiesFeature.cs new file mode 100644 index 000000000..04ca5c173 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/CapabilitiesFeature.cs @@ -0,0 +1,243 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Models + { + /// + /// Information about the capabilities of a debug adapter. + /// + public class Capabilities + { + /// + /// The debug adapter supports the 'configurationDone' request. + /// + [Optional] + public bool SupportsConfigurationDoneRequest { get; set; } + + /// + /// The debug adapter supports function breakpoints. + /// + [Optional] + public bool SupportsFunctionBreakpoints { get; set; } + + /// + /// The debug adapter supports conditional breakpoints. + /// + [Optional] + public bool SupportsConditionalBreakpoints { get; set; } + + /// + /// The debug adapter supports breakpoints that break execution after a specified long of hits. + /// + [Optional] + public bool SupportsHitConditionalBreakpoints { get; set; } + + /// + /// The debug adapter supports a (side effect free) evaluate request for data hovers. + /// + [Optional] + public bool SupportsEvaluateForHovers { get; set; } + + /// + /// Available filters or options for the setExceptionBreakpoints request. + /// + [Optional] + public Container? ExceptionBreakpointFilters { get; set; } + + /// + /// The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests. + /// + [Optional] + public bool SupportsStepBack { get; set; } + + /// + /// The debug adapter supports setting a variable to a value. + /// + [Optional] + public bool SupportsSetVariable { get; set; } + + /// + /// The debug adapter supports restarting a frame. + /// + [Optional] + public bool SupportsRestartFrame { get; set; } + + /// + /// The debug adapter supports the 'gotoTargets' request. + /// + [Optional] + public bool SupportsGotoTargetsRequest { get; set; } + + /// + /// The debug adapter supports the 'stepInTargets' request. + /// + [Optional] + public bool SupportsStepInTargetsRequest { get; set; } + + /// + /// The debug adapter supports the 'completions' request. + /// + [Optional] + public bool SupportsCompletionsRequest { get; set; } + + /// + /// The debug adapter supports the 'modules' request. + /// + [Optional] + public bool SupportsModulesRequest { get; set; } + + /// + /// The set of additional module information exposed by the debug adapter. + /// + [Optional] + public Container? AdditionalModuleColumns { get; set; } + + /// + /// Checksum algorithms supported by the debug adapter. + /// + [Optional] + public Container? SupportedChecksumAlgorithms { get; set; } + + /// + /// The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the + /// RestartRequest. + /// + [Optional] + public bool SupportsRestartRequest { get; set; } + + /// + /// The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request. + /// + [Optional] + public bool SupportsExceptionOptions { get; set; } + + /// + /// The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest. + /// + [Optional] + public bool SupportsValueFormattingOptions { get; set; } + + /// + /// The debug adapter supports the 'exceptionInfo' request. + /// + [Optional] + public bool SupportsExceptionInfoRequest { get; set; } + + /// + /// The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request. + /// + [Optional] + public bool SupportTerminateDebuggee { get; set; } + + /// + /// The debug adapter supports the delayed loading of parts of the stack, which requires that both the 'startFrame' and 'levels' arguments and the 'totalFrames' result of the + /// 'StackTrace' request are supported. + /// + [Optional] + public bool SupportsDelayedStackTraceLoading { get; set; } + + /// + /// The debug adapter supports the 'loadedSources' request. + /// + [Optional] + public bool SupportsLoadedSourcesRequest { get; set; } + + /// + /// The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint. + /// + [Optional] + public bool SupportsLogPoints { get; set; } + + /// + /// The debug adapter supports the 'terminateThreads' request. + /// + [Optional] + public bool SupportsTerminateThreadsRequest { get; set; } + + /// + /// The debug adapter supports the 'setExpression' request. + /// + [Optional] + public bool SupportsSetExpression { get; set; } + + /// + /// The debug adapter supports the 'terminate' request. + /// + [Optional] + public bool SupportsTerminateRequest { get; set; } + + /// + /// The debug adapter supports data breakpoints. + /// + [Optional] + public bool SupportsDataBreakpoints { get; set; } + + /// + /// The debug adapter supports the 'readMemory' request. + /// + [Optional] + public bool SupportsReadMemoryRequest { get; set; } + + /// + /// The debug adapter supports the 'disassemble' request. + /// + [Optional] + public bool SupportsDisassembleRequest { get; set; } + + /// + /// The debug adapter supports the 'cancel' request. + /// + [Optional] + public bool SupportsCancelRequest { get; set; } + + /// + /// The debug adapter supports the 'breakpointLocations' request. + /// + [Optional] + public bool SupportsBreakpointLocationsRequest { get; set; } + + /// + /// The debug adapter supports the 'clipboard' context value in the 'evaluate' request. + /// + [Optional] + public bool SupportsClipboardContext { get; set; } + + /// + /// The debug adapter supports stepping granularities (argument 'granularity') for the stepping requests. + /// + [Optional] + public bool SupportsSteppingGranularity { get; set; } + + /// + /// The debug adapter supports adding breakpoints based on instruction references. + /// + [Optional] + public bool SupportsInstructionBreakpoints { get; set; } + } + } + namespace Events + { + [Parallel] + [Method(EventNames.Capabilities, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class CapabilitiesEvent : IRequest + { + /// + /// The set of updated capabilities. + /// + public Capabilities Capabilities { get; set; } = null!; + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ContinuedFeature.cs b/src/Dap.Protocol/Feature/Events/ContinuedFeature.cs new file mode 100644 index 000000000..013da5a63 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ContinuedFeature.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Continued, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ContinuedEvent : IRequest + { + /// + /// The thread which was continued. + /// + public long ThreadId { get; set; } + + /// + /// If 'allThreadsContinued' is true, a debug adapter can announce that all threads have continued. + /// + [Optional] + public bool AllThreadsContinued { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ExitedFeature.cs b/src/Dap.Protocol/Feature/Events/ExitedFeature.cs new file mode 100644 index 000000000..8e02a25ff --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ExitedFeature.cs @@ -0,0 +1,27 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Exited, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ExitedEvent : IRequest + { + /// + /// The exit code returned from the debuggee. + /// + public long ExitCode { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/InitializedFeature.cs b/src/Dap.Protocol/Feature/Events/InitializedFeature.cs new file mode 100644 index 000000000..dd1237f2d --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/InitializedFeature.cs @@ -0,0 +1,23 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Initialized, Direction.ServerToClient)] + [ + GenerateHandler(Name = "DebugAdapterInitialized"), + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class InitializedEvent : IRequest + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/LoadedSourceFeature.cs b/src/Dap.Protocol/Feature/Events/LoadedSourceFeature.cs new file mode 100644 index 000000000..c4bd478d9 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/LoadedSourceFeature.cs @@ -0,0 +1,41 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.LoadedSource, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class LoadedSourceEvent : IRequest + { + /// + /// The reason for the event. + /// + public LoadedSourceReason Reason { get; set; } + + /// + /// The new, changed, or removed source. + /// + public Source Source { get; set; } = null!; + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum LoadedSourceReason + { + New, Changed, Removed + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ModuleFeature.cs b/src/Dap.Protocol/Feature/Events/ModuleFeature.cs new file mode 100644 index 000000000..ab7603334 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ModuleFeature.cs @@ -0,0 +1,41 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Module, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ModuleEvent : IRequest + { + /// + /// The reason for the event. + /// + public ModuleEventReason Reason { get; set; } + + /// + /// The new, changed, or removed module. In case of 'removed' only the module id is used. + /// + public Module Module { get; set; } = null!; + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum ModuleEventReason + { + New, Changed, Removed + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/OutputFeature.cs b/src/Dap.Protocol/Feature/Events/OutputFeature.cs new file mode 100644 index 000000000..ee10a71e3 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/OutputFeature.cs @@ -0,0 +1,67 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Output, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class OutputEvent : IRequest + { + /// + /// The output category. If not specified, 'console' is assumed. + /// Values: 'console', 'stdout', 'stderr', 'telemetry', etc. + /// + [Optional] + public string? Category { get; set; } + + /// + /// The output to report. + /// + public string Output { get; set; } = null!; + + /// + /// If an attribute 'variablesReference' exists and its value is > 0, the output contains objects which can be retrieved by passing 'variablesReference' to the 'variables' request. + /// + [Optional] + public long? VariablesReference { get; set; } + + /// + /// An optional source location where the output was produced. + /// + [Optional] + public Source? Source { get; set; } + + /// + /// An optional source location line where the output was produced. + /// + [Optional] + public long? Line { get; set; } + + /// + /// An optional source location column where the output was produced. + /// + [Optional] + public long? Column { get; set; } + + /// + /// Optional data to report. For the 'telemetry' category the data will be sent to telemetry, for the other categories the data is shown in JSON format. + /// + [Optional] + public JToken? Data { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ProcessFeature.cs b/src/Dap.Protocol/Feature/Events/ProcessFeature.cs new file mode 100644 index 000000000..076a7657c --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ProcessFeature.cs @@ -0,0 +1,63 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Process, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ProcessEvent : IRequest + { + /// + /// The logical name of the process. This is usually the full path to process's executable file. Example: /home/example/myproj/program.js. + /// + public string Name { get; set; } = null!; + + /// + /// The system process id of the debugged process. This property will be missing for non-system processes. + /// + [Optional] + public long? SystemProcessId { get; set; } + + /// + /// If true, the process is running on the same computer as the debug adapter. + /// + [Optional] + public bool IsLocalProcess { get; set; } + + /// + /// Describes how the debug engine started debugging this process. + /// 'launch': Process was launched under the debugger. + /// 'attach': Debugger attached to an existing process. + /// 'attachForSuspendedLaunch': A project launcher component has launched a new process in a suspended state and then asked the debugger to attach. + /// + [Optional] + public ProcessEventStartMethod? StartMethod { get; set; } + + /// + /// The size of a pointer or address for this process, in bits. This value may be used by clients when formatting addresses for display. + /// + [Optional] + public long? PointerSize { get; set; } + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum ProcessEventStartMethod + { + Launch, Attach, AttachForSuspendedLaunch + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ProgressFeature.cs b/src/Dap.Protocol/Feature/Events/ProgressFeature.cs new file mode 100644 index 000000000..3565dca07 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ProgressFeature.cs @@ -0,0 +1,93 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + public abstract class ProgressEvent + { + /// + /// The ID that was introduced in the initial 'progressStart' event. + /// + public ProgressToken ProgressId { get; set; } + + /// + /// Optional, more detailed progress message. If omitted, the previous message (if any) is used. + /// + [Optional] + public string? Message { get; set; } + } + + [Parallel] + [Method(EventNames.ProgressStart, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ProgressStartEvent : ProgressEvent, IRequest + { + /// + /// Mandatory (short) title of the progress reporting. Shown in the UI to describe the long running operation. + /// + public string Title { get; set; } = null!; + + /// + /// The request ID that this progress report is related to. If specified a debug adapter is expected to emit + /// progress events for the long running request until the request has been either completed or cancelled. + /// If the request ID is omitted, the progress report is assumed to be related to some general activity of the debug adapter. + /// + [Optional] + public int? RequestId { get; set; } + + /// + /// If true, the request that reports progress may be canceled with a 'cancel' request. + /// So this property basically controls whether the client should use UX that supports cancellation. + /// Clients that don't support cancellation are allowed to ignore the setting. + /// + [Optional] + public bool Cancellable { get; set; } + + /// + /// Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. + /// + [Optional] + public int? Percentage { get; set; } + } + + [Parallel] + [Method(EventNames.ProgressUpdate, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ProgressUpdateEvent : ProgressEvent, IRequest + { + /// + /// Optional progress percentage to display (value range: 0 to 100). If omitted no percentage will be shown. + /// + [Optional] + public double? Percentage { get; set; } + } + + [Parallel] + [Method(EventNames.ProgressEnd, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ProgressEndEvent : ProgressEvent, IRequest + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/StoppedFeature.cs b/src/Dap.Protocol/Feature/Events/StoppedFeature.cs new file mode 100644 index 000000000..8ddca9031 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/StoppedFeature.cs @@ -0,0 +1,62 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Stopped, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StoppedEvent : IRequest + { + /// + /// The reason for the event. + /// For backward compatibility this string is shown in the UI if the 'description' attribute is missing (but it must not be translated). + /// Values: 'step', 'breakpoint', 'exception', 'pause', 'entry', 'goto', 'function breakpoint', 'data breakpoint', etc. + /// + public string Reason { get; set; } = null!; + + /// + /// The full reason for the event, e.g. 'Paused on exception'. This string is shown in the UI as is and must be translated. + /// + [Optional] + public string? Description { get; set; } + + /// + /// The thread which was stopped. + /// + [Optional] + public long? ThreadId { get; set; } + + /// + /// A value of true hints to the frontend that this event should not change the focus. + /// + [Optional] + public bool PreserveFocusHint { get; set; } + + /// + /// Additional information. E.g. if reason is 'exception', text contains the exception name. This string is shown in the UI. + /// + [Optional] + public string? Text { get; set; } + + /// + /// If 'allThreadsStopped' is true, a debug adapter can announce that all threads have stopped. + /// - The client should use this information to enable that all threads can be expanded to access their stacktraces. + /// - If the attribute is missing or false, only the thread with the given threadId can be expanded. + /// + [Optional] + public bool AllThreadsStopped { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/TerminatedFeature.cs b/src/Dap.Protocol/Feature/Events/TerminatedFeature.cs new file mode 100644 index 000000000..29e18709d --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/TerminatedFeature.cs @@ -0,0 +1,33 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Terminated, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class TerminatedEvent : IRequest + { + /// + /// A debug adapter may set 'restart' to true (or to an arbitrary object) to request that the front end restarts the session. + /// The value is not interpreted by the client and passed unmodified as an attribute '__restart' to the 'launch' and 'attach' requests. + /// + [Optional] + [JsonProperty(PropertyName = "__restart")] + public JToken? Restart { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Events/ThreadFeature.cs b/src/Dap.Protocol/Feature/Events/ThreadFeature.cs new file mode 100644 index 000000000..7e39ebb03 --- /dev/null +++ b/src/Dap.Protocol/Feature/Events/ThreadFeature.cs @@ -0,0 +1,33 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Events + { + [Parallel] + [Method(EventNames.Thread, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ThreadEvent : IRequest + { + /// + /// The reason for the event. + /// Values: 'started', 'exited', etc. + /// + public string Reason { get; set; } = null!; + + /// + /// The identifier of the thread. + /// + public long ThreadId { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/AttachFeature.cs b/src/Dap.Protocol/Feature/Requests/AttachFeature.cs new file mode 100644 index 000000000..dbe392a09 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/AttachFeature.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Attach, Direction.ClientToServer)] + [ + GenerateHandler(Name = "Attach", AllowDerivedRequests = true), + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class AttachRequestArguments : IRequest + { + /// + /// Optional data from the previous, restarted session. + /// The data is sent as the 'restart' attribute of the 'terminated' event. + /// The client should leave the data intact. + /// + [Optional] + [JsonProperty(PropertyName = "__restart")] + public JToken? Restart { get; set; } + + [JsonExtensionData] public IDictionary ExtensionData { get; set; } = new Dictionary(); + } + + public class AttachResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/BreakpointLocationsFeature.cs b/src/Dap.Protocol/Feature/Requests/BreakpointLocationsFeature.cs new file mode 100644 index 000000000..a86700caf --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/BreakpointLocationsFeature.cs @@ -0,0 +1,89 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.BreakpointLocations, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class BreakpointLocationsArguments : IRequest + { + /// + /// The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. + /// + public Source Source { get; set; } = null!; + + /// + /// Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line. + /// + public int Line { get; set; } + + /// + /// Optional start column of range to search possible breakpoint locations in. If no start column is given, the first column in the start line is assumed. + /// + [Optional] + public int? Column { get; set; } + + /// + /// Optional end line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// Optional end column of range to search possible breakpoint locations in. If no end column is given, then it is assumed to be in the last column of the end line. + /// + [Optional] + public int? EndColumn { get; set; } + } + + public class BreakpointLocationsResponse + { + /// + /// Sorted set of possible breakpoint locations. + /// + public Container Breakpoints { get; set; } = null!; + } + } + + namespace Models + { + public class BreakpointLocation + { + /// + /// Start line of breakpoint location. + /// + public int Line { get; set; } + + /// + /// Optional start column of breakpoint location. + /// + [Optional] + public int? Column { get; set; } + + /// + /// Optional end line of breakpoint location if the location covers a range. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// Optional end column of breakpoint location if the location covers a range. + /// + [Optional] + public int? EndColumn { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/CancelFeature.cs b/src/Dap.Protocol/Feature/Requests/CancelFeature.cs new file mode 100644 index 000000000..95e9180b3 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/CancelFeature.cs @@ -0,0 +1,61 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + + /// + /// DAP is kind of silly.... + /// Cancellation is for requests and progress tokens... hopefully if isn't ever expanded any further... because that would be fun. + /// + [Parallel] + [Method(RequestNames.Cancel, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class CancelArguments : IRequest + { + // This is removed on purpose, as request cancellation is handled by the DapReciever + // /// + // /// The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. + // /// Both a 'requestId' and a 'progressId' can be specified in one request. + // /// + // [Optional] + // public int? RequestId { get; set; } + + /// + /// The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled. + /// Both a 'requestId' and a 'progressId' can be specified in one request. + /// + [Optional] + public ProgressToken? ProgressId { get; set; } + } + + public class CancelResponse + { + /// + /// The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. + /// Both a 'requestId' and a 'progressId' can be specified in one request. + /// + [Optional] + public int? RequestId { get; set; } + + /// + /// The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled. + /// Both a 'requestId' and a 'progressId' can be specified in one request. + /// + [Optional] + public ProgressToken? ProgressId { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/CompletionsFeature.cs b/src/Dap.Protocol/Feature/Requests/CompletionsFeature.cs new file mode 100644 index 000000000..90ced02c5 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/CompletionsFeature.cs @@ -0,0 +1,121 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Completions, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class CompletionsArguments : IRequest + { + /// + /// Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope. + /// + [Optional] + public long? FrameId { get; set; } + + /// + /// One or more source lines.Typically this is the text a user has typed into the debug console before he asked for completion. + /// + public string Text { get; set; } = null!; + + /// + /// The character position for which to determine the completion proposals. + /// + public long Column { get; set; } + + /// + /// An optional line for which to determine the completion proposals.If missing the first line of the text is assumed. + /// + [Optional] + public long? Line { get; set; } + } + + public class CompletionsResponse + { + /// + /// The possible completions for . + /// + public Container Targets { get; set; } = null!; + } + } + + namespace Models + { + /// + /// CompletionItems are the suggestions returned from the CompletionsRequest. + /// + public class CompletionItem + { + /// + /// The label of this completion item. By default this is also the text that is inserted when selecting this completion. + /// + public string Label { get; set; } = null!; + + /// + /// If text is not falsy then it is inserted instead of the label. + /// + [Optional] + public string? Text { get; set; } = null!; + + /// + /// The item's type. Typically the client uses this information to render the item in the UI with an icon. + /// + [Optional] + public CompletionItemType Type { get; set; } + + /// + /// This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added. + /// If missing the text is added at the location specified by the CompletionsRequest's 'column' attribute. + /// + [Optional] + public int? Start { get; set; } + + /// + /// This value determines how many characters are overwritten by the completion text. + /// If missing the value 0 is assumed which results in the completion text being inserted. + /// + [Optional] + public int? Length { get; set; } + + /// + /// Determines the start of the new selection after the text has been inserted (or replaced). + /// The start position must in the range 0 and length of the completion text. + /// If omitted the selection starts at the end of the completion text. + /// + [Optional] + public int? SelectionStart { get; set; } + + /// + /// Determines the length of the new selection after the text has been inserted (or replaced). + /// The selection can not extend beyond the bounds of the completion text. + /// If omitted the length is assumed to be 0. + /// + [Optional] + public int? SelectionLength { get; set; } + } + + /// + /// Some predefined types for the CompletionItem.Please note that not all clients have specific icons for all of them. + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum CompletionItemType + { + Method, Function, Constructor, Field, Variable, Class, Interface, Module, Property, Unit, Value, Enum, Keyword, Snippet, Text, Color, File, Reference, CustomColor + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ConfigurationDoneFeature.cs b/src/Dap.Protocol/Feature/Requests/ConfigurationDoneFeature.cs new file mode 100644 index 000000000..650f1a9bd --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ConfigurationDoneFeature.cs @@ -0,0 +1,27 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.ConfigurationDone, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ConfigurationDoneArguments : IRequest + { + } + + public class ConfigurationDoneResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ContinueFeature.cs b/src/Dap.Protocol/Feature/Requests/ContinueFeature.cs new file mode 100644 index 000000000..4e6c8f576 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ContinueFeature.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Continue, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ContinueArguments : IRequest + { + /// + /// Continue execution for the specified thread(if possible). If the backend cannot continue on a single thread but will continue on all threads, it should set the + /// 'allThreadsContinued' attribute in the response to true. + /// + public long ThreadId { get; set; } + } + + public class ContinueResponse + { + /// + /// If true, the 'continue' request has ignored the specified thread and continued all threads instead.If this attribute is missing a value of 'true' is assumed for backward + /// compatibility. + /// + [Optional] + public bool AllThreadsContinued { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/DataBreakpointInfoFeature.cs b/src/Dap.Protocol/Feature/Requests/DataBreakpointInfoFeature.cs new file mode 100644 index 000000000..368eb4d53 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/DataBreakpointInfoFeature.cs @@ -0,0 +1,62 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.DataBreakpointInfo, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class DataBreakpointInfoArguments : IRequest + { + /// + /// Reference to the Variable container if the data breakpoint is requested for a child of the container. + /// + [Optional] + public long? VariablesReference { get; set; } + + /// + /// The name of the Variable's child to obtain data breakpoint information for. If variableReference isn’t provided, this can be an expression. + /// + public string Name { get; set; } = null!; + } + + public class DataBreakpointInfoResponse + { + /// + /// An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available. + /// + public string DataId { get; set; } = null!; + + /// + /// UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available. + /// + public string Description { get; set; } = null!; + + /// + /// Optional attribute listing the available access types for a potential data breakpoint.A UI frontend could surface this information. + /// + [Optional] + public Container? AccessTypes { get; set; } + + /// + /// Optional attribute indicating that a potential data breakpoint could be persisted across sessions. + /// + [Optional] + public bool CanPersist { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/DisassembleFeature.cs b/src/Dap.Protocol/Feature/Requests/DisassembleFeature.cs new file mode 100644 index 000000000..0b012ae34 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/DisassembleFeature.cs @@ -0,0 +1,125 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Disassemble, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class DisassembleArguments : IRequest + { + /// + /// Memory reference to the base location containing the instructions to disassemble. + /// + public string MemoryReference { get; set; } = null!; + + /// + /// Optional offset(in bytes) to be applied to the reference location before disassembling.Can be negative. + /// + [Optional] + public long? Offset { get; set; } + + /// + /// Optional offset(in instructions) to be applied after the byte offset(if any) before disassembling.Can be negative. + /// + + [Optional] + public long? InstructionOffset { get; set; } + + /// + /// Number of instructions to disassemble starting at the specified location and offset.An adapter must return exactly this number of instructions - any unavailable instructions + /// should be replaced with an implementation-defined 'invalid instruction' value. + /// + public long InstructionCount { get; set; } + + /// + /// If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. + /// + [Optional] + public bool ResolveSymbols { get; set; } + } + + public class DisassembleResponse + { + /// + /// The list of disassembled instructions. + /// + public Container Instructions { get; set; } = null!; + } + } + + namespace Models + { + /// + /// DisassembledInstruction + /// Represents a single disassembled instruction. + /// + public class DisassembledInstruction + { + /// + /// The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. + /// + public string Address { get; set; } = null!; + + /// + /// Optional raw bytes representing the instruction and its operands, in an implementation-defined format. + /// + [Optional] + public string? InstructionBytes { get; set; } + + /// + /// Text representing the instruction and its operands, in an implementation-defined format. + /// + public string Instruction { get; set; } = null!; + + /// + /// Name of the symbol that correponds with the location of this instruction, if any. + /// + [Optional] + public string? Symbol { get; set; } + + /// + /// Source location that corresponds to this instruction, if any. Should always be set (if available) on the first instruction returned, but can be omitted afterwards if this + /// instruction maps to the same source file as the previous instruction. + /// + [Optional] + public Source? Location { get; set; } + + /// + /// The line within the source location that corresponds to this instruction, if any. + /// + [Optional] + public int? Line { get; set; } + + /// + /// The column within the line that corresponds to this instruction, if any. + /// + [Optional] + public int? Column { get; set; } + + /// + /// The end line of the range that corresponds to this instruction, if any. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// The end column of the range that corresponds to this instruction, if any. + /// + [Optional] + public int? EndColumn { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/DisconnectFeature.cs b/src/Dap.Protocol/Feature/Requests/DisconnectFeature.cs new file mode 100644 index 000000000..a5e2af7e7 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/DisconnectFeature.cs @@ -0,0 +1,41 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Disconnect, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class DisconnectArguments : IRequest + { + /// + /// A value of true indicates that this 'disconnect' request is part of a restart sequence. + /// + [Optional] + public bool Restart { get; set; } + + /// + /// Indicates whether the debuggee should be terminated when the debugger is disconnected. + /// If unspecified, the debug adapter is free to do whatever it thinks is best. + /// A client can only rely on this attribute being properly honored if a debug adapter returns true for the 'supportTerminateDebuggee' capability. + /// + [Optional] + public bool TerminateDebuggee { get; set; } + } + + public class DisconnectResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/EvaluateFeature.cs b/src/Dap.Protocol/Feature/Requests/EvaluateFeature.cs new file mode 100644 index 000000000..723fa92eb --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/EvaluateFeature.cs @@ -0,0 +1,97 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Evaluate, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class EvaluateArguments : IRequest + { + /// + /// The expression to evaluate. + /// + public string Expression { get; set; } = null!; + + /// + /// Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. + /// + [Optional] + public long? FrameId { get; set; } + + /// + /// The context in which the evaluate request is run. + /// Values: + /// 'watch': evaluate is run in a watch. + /// 'repl': evaluate is run from REPL console. + /// 'hover': evaluate is run from a data hover. + /// etc. + /// + [Optional] + public string? Context { get; set; } + + /// + /// Specifies details on how to format the Evaluate result. + /// + [Optional] + public ValueFormat? Format { get; set; } + } + + public class EvaluateResponse + { + /// + /// The result of the evaluate request. + /// + public string Result { get; set; } = null!; + + /// + /// The optional type of the evaluate result. + /// + [Optional] + public string? Type { get; set; } + + /// + /// Properties of a evaluate result that can be used to determine how to render the result in the UI. + /// + [Optional] + public VariablePresentationHint? PresentationHint { get; set; } + + /// + /// If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + /// + public long VariablesReference { get; set; } + + /// + /// The number of named child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? NamedVariables { get; set; } + + /// + /// The number of indexed child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? IndexedVariables { get; set; } + + /// + /// Memory reference to a location appropriate for this result.For pointer type eval results, this is generally a reference to the memory address contained in the pointer. + /// + [Optional] + public string? MemoryReference { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ExceptionInfoFeature.cs b/src/Dap.Protocol/Feature/Requests/ExceptionInfoFeature.cs new file mode 100644 index 000000000..cb9b8eaa1 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ExceptionInfoFeature.cs @@ -0,0 +1,54 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.ExceptionInfo, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ExceptionInfoArguments : IRequest + { + /// + /// Thread for which exception information should be retrieved. + /// + public long ThreadId { get; set; } + } + + public class ExceptionInfoResponse + { + /// + /// ID of the exception that was thrown. + /// + public string ExceptionId { get; set; } = null!; + + /// + /// Descriptive text for the exception provided by the debug adapter. + /// + [Optional] + public string? Description { get; set; } + + /// + /// Mode that caused the exception notification to be raised. + /// + public ExceptionBreakMode BreakMode { get; set; } + + /// + /// Detailed information about the exception. + /// + [Optional] + public ExceptionDetails? Details { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/GotoFeature.cs b/src/Dap.Protocol/Feature/Requests/GotoFeature.cs new file mode 100644 index 000000000..7831c2977 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/GotoFeature.cs @@ -0,0 +1,36 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Goto, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class GotoArguments : IRequest + { + /// + /// Set the goto target for this thread. + /// + public long ThreadId { get; set; } + + /// + /// The location where the debuggee will continue to run. + /// + public long TargetId { get; set; } + } + + public class GotoResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/GotoTargetsFeature.cs b/src/Dap.Protocol/Feature/Requests/GotoTargetsFeature.cs new file mode 100644 index 000000000..78fcf0b2a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/GotoTargetsFeature.cs @@ -0,0 +1,97 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.GotoTargets, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class GotoTargetsArguments : IRequest + { + /// + /// The source location for which the goto targets are determined. + /// + public Source Source { get; set; } = null!; + + /// + /// The line location for which the goto targets are determined. + /// + public long Line { get; set; } + + /// + /// An optional column location for which the goto targets are determined. + /// + [Optional] + public long? Column { get; set; } + } + + public class GotoTargetsResponse + { + /// + /// The possible goto targets of the specified location. + /// + public Container Targets { get; set; } = null!; + } + } + + namespace Models + { + /// + /// A GotoTarget describes a code location that can be used as a target in the ‘goto’ request. + /// The possible goto targets can be determined via the ‘gotoTargets’ request. + /// + public class GotoTarget + { + /// + /// Unique identifier for a goto target. This is used in the goto request. + /// + public long Id { get; set; } + + /// + /// The name of the goto target (shown in the UI). + /// + public string Label { get; set; } = null!; + + /// + /// The line of the goto target. + /// + public int Line { get; set; } + + /// + /// An optional column of the goto target. + /// + [Optional] + public int? Column { get; set; } + + /// + /// An optional end line of the range covered by the goto target. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// An optional end column of the range covered by the goto target. + /// + [Optional] + public int? EndColumn { get; set; } + + /// + /// Optional memory reference for the instruction pointer value represented by this target. + /// + [Optional] + public string? InstructionPointerReference { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/InitializeRequestFeature.cs b/src/Dap.Protocol/Feature/Requests/InitializeRequestFeature.cs new file mode 100644 index 000000000..18e0220e9 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/InitializeRequestFeature.cs @@ -0,0 +1,103 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Initialize, Direction.ClientToServer)] + [ + GenerateHandler(Name = "DebugAdapterInitialize"), + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class InitializeRequestArguments : IRequest, IInitializeRequestArguments + { + /// + /// The ID of the(frontend) client using this adapter. + /// + + [Optional] + public string? ClientId { get; set; } + + /// + /// The human readable name of the(frontend) client using this adapter. + /// + + [Optional] + public string? ClientName { get; set; } + + /// + /// The ID of the debug adapter. + /// + public string AdapterId { get; set; } = null!; + + /// + /// The ISO-639 locale of the(frontend) client using this adapter, e.g.en-US or de-CH. + /// + + [Optional] + public string? Locale { get; set; } + + /// + /// If true all line numbers are 1-based(default). + /// + [Optional] + public bool LinesStartAt1 { get; set; } + + /// + /// If true all column numbers are 1-based(default). + /// + [Optional] + public bool ColumnsStartAt1 { get; set; } + + /// + /// Determines in what format paths are specified.The default is 'path', which is the native format. + /// Values: 'path', 'uri', etc. + /// + [Optional] + public string? PathFormat { get; set; } + + /// + /// Client supports the optional type attribute for variables. + /// + [Optional] + public bool SupportsVariableType { get; set; } + + /// + /// Client supports the paging of variables. + /// + [Optional] + public bool SupportsVariablePaging { get; set; } + + /// + /// Client supports the runInTerminal request. + /// + [Optional] + public bool SupportsRunInTerminalRequest { get; set; } + + /// + /// Client supports memory references. + /// + [Optional] + public bool SupportsMemoryReferences { get; set; } + + /// + /// Client supports progress reporting. + /// + [Optional] + public bool SupportsProgressReporting { get; set; } + } + + public class InitializeResponse : Capabilities + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/LaunchFeature.cs b/src/Dap.Protocol/Feature/Requests/LaunchFeature.cs new file mode 100644 index 000000000..23869bf1b --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/LaunchFeature.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Launch, Direction.ClientToServer)] + [ + GenerateHandler(Name = "Launch", AllowDerivedRequests = true), + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class LaunchRequestArguments : IRequest + { + /// + /// If noDebug is true the launch request should launch the program without enabling debugging. + /// + [Optional] + public bool NoDebug { get; set; } + + /// + /// Optional data from the previous, restarted session. + /// The data is sent as the 'restart' attribute of the 'terminated' event. + /// The client should leave the data intact. + /// + [Optional] + [JsonProperty(PropertyName = "__restart")] + public JToken? Restart { get; set; } + + [JsonExtensionData] public IDictionary ExtensionData { get; set; } = new Dictionary(); + } + + public class LaunchResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/LoadedSourcesFeature.cs b/src/Dap.Protocol/Feature/Requests/LoadedSourcesFeature.cs new file mode 100644 index 000000000..b459d22b0 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/LoadedSourcesFeature.cs @@ -0,0 +1,36 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.LoadedSources, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class LoadedSourcesArguments : IRequest + { + } + + public class LoadedSourcesResponse + { + /// + /// Set of loaded sources. + /// + public Container Sources { get; set; } = null!; + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ModulesFeature.cs b/src/Dap.Protocol/Feature/Requests/ModulesFeature.cs new file mode 100644 index 000000000..b7f725fc8 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ModulesFeature.cs @@ -0,0 +1,54 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Modules, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ModulesArguments : IRequest + { + /// + /// The index of the first module to return; if omitted modules start at 0. + /// + [Optional] + public long? StartModule { get; set; } + + /// + /// The number of modules to return. If moduleCount is not specified or 0, all modules are returned. + /// + [Optional] + public long? ModuleCount { get; set; } + } + + public class ModulesResponse + { + /// + /// All modules or range of modules. + /// + public Container Modules { get; set; } = null!; + + /// + /// The total number of modules available. + /// + [Optional] + public long? TotalModules { get; set; } + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/NextFeature.cs b/src/Dap.Protocol/Feature/Requests/NextFeature.cs new file mode 100644 index 000000000..4e746e41a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/NextFeature.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Next, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class NextArguments : IRequest + { + /// + /// Execute 'next' for this thread. + /// + public long ThreadId { get; set; } + + /// + /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + /// + [Optional] + public SteppingGranularity Granularity { get; set; } + } + + public class NextResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/PauseFeature.cs b/src/Dap.Protocol/Feature/Requests/PauseFeature.cs new file mode 100644 index 000000000..191bd9ad0 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/PauseFeature.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Pause, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class PauseArguments : IRequest + { + /// + /// Pause execution for this thread. + /// + public long ThreadId { get; set; } + } + + public class PauseResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ReadMemoryFeature.cs b/src/Dap.Protocol/Feature/Requests/ReadMemoryFeature.cs new file mode 100644 index 000000000..63284a18d --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ReadMemoryFeature.cs @@ -0,0 +1,61 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.ReadMemory, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ReadMemoryArguments : IRequest + { + /// + /// Memory reference to the base location from which data should be read. + /// + public string MemoryReference { get; set; } = null!; + + /// + /// Optional offset(in bytes) to be applied to the reference location before reading data.Can be negative. + /// + + [Optional] + public long? Offset { get; set; } + + /// + /// Number of bytes to read at the specified location and offset. + /// + public long Count { get; set; } + } + + public class ReadMemoryResponse + { + /// + /// The address of the first byte of data returned.Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. + /// + public string Address { get; set; } = null!; + + /// + /// The number of unreadable bytes encountered after the last successfully read byte. This can be used to determine the number of bytes that must be skipped before a subsequent + /// 'readMemory' request will succeed. + /// + [Optional] + public long? UnreadableBytes { get; set; } + + /// + /// The bytes read from memory, encoded using base64. + /// + [Optional] + public string? Data { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/RestartFeature.cs b/src/Dap.Protocol/Feature/Requests/RestartFeature.cs new file mode 100644 index 000000000..585cb01d3 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/RestartFeature.cs @@ -0,0 +1,27 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Restart, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class RestartArguments : IRequest + { + } + + public class RestartResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/RestartFrameFeature.cs b/src/Dap.Protocol/Feature/Requests/RestartFrameFeature.cs new file mode 100644 index 000000000..16dbcb9cf --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/RestartFrameFeature.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.RestartFrame, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class RestartFrameArguments : IRequest + { + /// + /// Restart this stackframe. + /// + public long FrameId { get; set; } + } + + public class RestartFrameResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ReverseContinueFeature.cs b/src/Dap.Protocol/Feature/Requests/ReverseContinueFeature.cs new file mode 100644 index 000000000..5fb893cfe --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ReverseContinueFeature.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.ReverseContinue, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ReverseContinueArguments : IRequest + { + /// + /// Execute 'reverseContinue' for this thread. + /// + public long ThreadId { get; set; } + } + + public class ReverseContinueResponse + { + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/RunInTerminalFeature.cs b/src/Dap.Protocol/Feature/Requests/RunInTerminalFeature.cs new file mode 100644 index 000000000..efaefd237 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/RunInTerminalFeature.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.RunInTerminal, Direction.ServerToClient)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class RunInTerminalArguments : IRequest + { + /// + /// What kind of terminal to launch. + /// + [Optional] + public RunInTerminalArgumentsKind? Kind { get; set; } + + /// + /// Optional title of the terminal. + /// + [Optional] + public string? Title { get; set; } + + /// + /// Working directory of the command. + /// + public string Cwd { get; set; } = null!; + + /// + /// List of arguments.The first argument is the command to run. + /// + public Container Args { get; set; } = null!; + + /// + /// Environment key-value pairs that are added to or removed from the default environment. + /// + [Optional] + public IDictionary? Env { get; set; } + } + + public class RunInTerminalResponse + { + /// + /// The process ID. + /// + [Optional] + public long? ProcessId { get; set; } + + /// + /// The process ID of the terminal shell. + /// + [Optional] + public long? ShellProcessId { get; set; } + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum RunInTerminalArgumentsKind + { + Integrated, + External + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ScopesFeature.cs b/src/Dap.Protocol/Feature/Requests/ScopesFeature.cs new file mode 100644 index 000000000..1db8b2561 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ScopesFeature.cs @@ -0,0 +1,116 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Scopes, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ScopesArguments : IRequest + { + /// + /// Retrieve the scopes for this stackframe. + /// + public long FrameId { get; set; } + } + + public class ScopesResponse + { + /// + /// The scopes of the stackframe.If the array has length zero, there are no scopes available. + /// + public Container Scopes { get; set; } = null!; + } + } + + namespace Models + { + /// + /// A Scope is a named container for variables.Optionally a scope can map to a source or a range within a source. + /// + public class Scope + { + /// + /// Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. + /// + public string Name { get; set; } = null!; + + /// + /// An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI. + /// Values: + /// 'arguments': Scope contains method arguments. + /// 'locals': Scope contains local variables. + /// 'registers': Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request. + /// etc. + /// + [Optional] + public string? PresentationHint { get; set; } + + /// + /// The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest. + /// + public long VariablesReference { get; set; } + + /// + /// The long of named variables in this scope. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? NamedVariables { get; set; } + + /// + /// The long of indexed variables in this scope. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? IndexedVariables { get; set; } + + /// + /// If true, the long of variables in this scope is large or expensive to retrieve. + /// + public bool Expensive { get; set; } + + /// + /// Optional source for this scope. + /// + [Optional] + public Source? Source { get; set; } + + /// + /// Optional start line of the range covered by this scope. + /// + [Optional] + public int? Line { get; set; } + + /// + /// Optional start column of the range covered by this scope. + /// + [Optional] + public int? Column { get; set; } + + /// + /// Optional end line of the range covered by this scope. + /// + [Optional] + public int? EndLine { get; set; } + + /// + /// Optional end column of the range covered by this scope. + /// + [Optional] + public int? EndColumn { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetBreakpointsFeature.cs b/src/Dap.Protocol/Feature/Requests/SetBreakpointsFeature.cs new file mode 100644 index 000000000..1feb17c6f --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetBreakpointsFeature.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetBreakpoints, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetBreakpointsArguments : IRequest + { + /// + /// The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. + /// + public Source Source { get; set; } = null!; + + /// + /// The code locations of the breakpoints. + /// + [Optional] + public Container? Breakpoints { get; set; } + + /// + /// Deprecated: The code locations of the breakpoints. + /// + [Obsolete("Deprecated")] + [Optional] + public Container? Lines { get; set; } + + /// + /// A value of true indicates that the underlying source has been modified which results in new breakpoint locations. + /// + [Optional] + public bool SourceModified { get; set; } + } + + public class SetBreakpointsResponse + { + /// + /// Information about the breakpoints.The array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments. + /// + public Container Breakpoints { get; set; } = null!; + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetDataBreakpointsFeature.cs b/src/Dap.Protocol/Feature/Requests/SetDataBreakpointsFeature.cs new file mode 100644 index 000000000..47b7c681a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetDataBreakpointsFeature.cs @@ -0,0 +1,36 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetDataBreakpoints, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetDataBreakpointsArguments : IRequest + { + /// + /// The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. + /// + public Container Breakpoints { get; set; } = null!; + } + + public class SetDataBreakpointsResponse + { + /// + /// Information about the data breakpoints.The array elements correspond to the elements of the input argument 'breakpoints' array. + /// + public Container Breakpoints { get; set; } = null!; + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetExceptionBreakpointsFeature.cs b/src/Dap.Protocol/Feature/Requests/SetExceptionBreakpointsFeature.cs new file mode 100644 index 000000000..f9713300a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetExceptionBreakpointsFeature.cs @@ -0,0 +1,94 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetExceptionBreakpoints, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetExceptionBreakpointsArguments : IRequest + { + /// + /// IDs of checked exception options.The set of IDs is returned via the 'exceptionBreakpointFilters' capability. + /// + public Container Filters { get; set; } = null!; + + /// + /// Configuration options for selected exceptions. + /// + [Optional] + public Container? ExceptionOptions { get; set; } + } + + public class SetExceptionBreakpointsResponse + { + } + } + + namespace Models + { + /// + /// ExceptionOptions + /// An ExceptionOptions assigns configuration options to a set of exceptions. + /// + public class ExceptionOptions + { + /// + /// A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected. By convention the first segment of the path is a category that is + /// used to group exceptions in the UI. + /// + [Optional] + public Container? Path { get; set; } + + /// + /// Condition when a thrown exception should result in a break. + /// + public ExceptionBreakMode BreakMode { get; set; } + } + + /// + /// An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions.If a segment consists of more than one name, it matches the + /// names provided if ‘negate’ is false or missing or it matches anything except the names provided if ‘negate’ is true. + /// + public class ExceptionPathSegment + { + /// + /// If false or missing this segment matches the names provided, otherwise it matches anything except the names provided. + /// + [Optional] + public bool Negate { get; set; } + + /// + /// Depending on the value of 'negate' the names that should match or not match. + /// + public Container Names { get; set; } = null!; + } + + /// + /// This enumeration defines all possible conditions when a thrown exception should result in a break. + /// never: never breaks, + /// always: always breaks, + /// unhandled: breaks when exception unhandled, + /// userUnhandled: breaks if the exception is not handled by user code. + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum ExceptionBreakMode + { + Never, Always, Unhandled, UserUnhandled + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetExpressionFeature.cs b/src/Dap.Protocol/Feature/Requests/SetExpressionFeature.cs new file mode 100644 index 000000000..af16f904b --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetExpressionFeature.cs @@ -0,0 +1,86 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetExpression, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetExpressionArguments : IRequest + { + /// + /// The l-value expression to assign to. + /// + public string Expression { get; set; } = null!; + + /// + /// The value expression to assign to the l-value expression. + /// + public string Value { get; set; } = null!; + + /// + /// Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope. + /// + [Optional] + public long? FrameId { get; set; } + + /// + /// Specifies how the resulting value should be formatted. + /// + [Optional] + public ValueFormat? Format { get; set; } + } + + public class SetExpressionResponse + { + /// + /// The new value of the expression. + /// + public string Value { get; set; } = null!; + + /// + /// The optional type of the value. + /// + [Optional] + public string? Type { get; set; } + + /// + /// Properties of a value that can be used to determine how to render the result in the UI. + /// + [Optional] + public VariablePresentationHint? PresentationHint { get; set; } + + /// + /// If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + /// + [Optional] + public long? VariablesReference { get; set; } + + /// + /// The number of named child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? NamedVariables { get; set; } + + /// + /// The number of indexed child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? IndexedVariables { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetFunctionBreakpointsFeature.cs b/src/Dap.Protocol/Feature/Requests/SetFunctionBreakpointsFeature.cs new file mode 100644 index 000000000..7accc1718 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetFunctionBreakpointsFeature.cs @@ -0,0 +1,64 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetFunctionBreakpoints, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetFunctionBreakpointsArguments : IRequest + { + /// + /// The function names of the breakpoints. + /// + public Container Breakpoints { get; set; } = null!; + } + + public class SetFunctionBreakpointsResponse + { + /// + /// Information about the breakpoints.The array elements correspond to the elements of the 'breakpoints' array. + /// + public Container Breakpoints { get; set; } = null!; + } + } + + namespace Models + { + /// + /// FunctionBreakpoint + /// Properties of a breakpoint passed to the setFunctionBreakpoints request. + /// + public class FunctionBreakpoint + { + /// + /// The name of the function. + /// + public string Name { get; set; } = null!; + + /// + /// An optional expression for conditional breakpoints. + /// + [Optional] + public string? Condition { get; set; } + + /// + /// An optional expression that controls how many hits of the breakpoint are ignored. The backend is expected to interpret the expression as needed. + /// + [Optional] + public string? HitCondition { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetInstructionBreakpointsFeature.cs b/src/Dap.Protocol/Feature/Requests/SetInstructionBreakpointsFeature.cs new file mode 100644 index 000000000..e287143bd --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetInstructionBreakpointsFeature.cs @@ -0,0 +1,40 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetInstructionBreakpoints, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetInstructionBreakpointsArguments : IRequest + { + /// + /// The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. + /// + public Container Breakpoints { get; set; } = null!; + } + + public class SetInstructionBreakpointsResponse + { + /// + /// Information about the data breakpoints.The array elements correspond to the elements of the input argument 'breakpoints' array. + /// + public Container Breakpoints { get; set; } = null!; + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SetVariableFeature.cs b/src/Dap.Protocol/Feature/Requests/SetVariableFeature.cs new file mode 100644 index 000000000..50d66cbdc --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SetVariableFeature.cs @@ -0,0 +1,79 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.SetVariable, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SetVariableArguments : IRequest + { + /// + /// The reference of the variable container. + /// + public long VariablesReference { get; set; } + + /// + /// The name of the variable in the container. + /// + public string Name { get; set; } = null!; + + /// + /// The value of the variable. + /// + public string Value { get; set; } = null!; + + /// + /// Specifies details on how to format the response value. + /// + [Optional] + public ValueFormat? Format { get; set; } + } + + public class SetVariableResponse + { + /// + /// The new value of the variable. + /// + public string Value { get; set; } = null!; + + /// + /// The type of the new value.Typically shown in the UI when hovering over the value. + /// + [Optional] + public string? Type { get; set; } + + /// + /// If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. + /// + [Optional] + public long? VariablesReference { get; set; } + + /// + /// The number of named child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? NamedVariables { get; set; } + + /// + /// The number of indexed child variables. + /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. + /// + [Optional] + public long? IndexedVariables { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/SourceFeature.cs b/src/Dap.Protocol/Feature/Requests/SourceFeature.cs new file mode 100644 index 000000000..3a6c91723 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/SourceFeature.cs @@ -0,0 +1,53 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Source, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class SourceArguments : IRequest + { + /// + /// Specifies the source content to load.Either source.path or source.sourceReference must be specified. + /// + [Optional] + public Source? Source { get; set; } + + /// + /// The reference to the source.This is the same as source.sourceReference.This is provided for backward compatibility since old backends do not understand the 'source' attribute. + /// + public long SourceReference { get; set; } + } + + public class SourceResponse + { + /// + /// Content of the source reference. + /// + public string Content { get; set; } = null!; + + /// + /// Optional content type(mime type) of the source. + /// + [Optional] + public string? MimeType { get; set; } + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/StackTraceFeature.cs b/src/Dap.Protocol/Feature/Requests/StackTraceFeature.cs new file mode 100644 index 000000000..eb74f806a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/StackTraceFeature.cs @@ -0,0 +1,113 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.StackTrace, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StackTraceArguments : IRequest + { + /// + /// Retrieve the stacktrace for this thread. + /// + public long ThreadId { get; set; } + + /// + /// The index of the first frame to return; if omitted frames start at 0. + /// + [Optional] + public long? StartFrame { get; set; } + + /// + /// The maximum number of frames to return. If levels is not specified or 0, all frames are returned. + /// + [Optional] + public long? Levels { get; set; } + + /// + /// Specifies details on how to format the stack frames. + /// + [Optional] + public StackFrameFormat? Format { get; set; } + } + + public class StackTraceResponse + { + /// + /// The frames of the stackframe.If the array has length zero, there are no stackframes available. + /// This means that there is no location information available. + /// + public Container? StackFrames { get; set; } + + /// + /// The total number of frames available. + /// + [Optional] + public long? TotalFrames { get; set; } + } + } + + namespace Models + { + /// + /// Provides formatting information for a stack frame. + /// + public class StackFrameFormat : ValueFormat + { + /// + /// Displays parameters for the stack frame. + /// + [Optional] + public bool Parameters { get; set; } + + /// + /// Displays the types of parameters for the stack frame. + /// + [Optional] + public bool ParameterTypes { get; set; } + + /// + /// Displays the names of parameters for the stack frame. + /// + [Optional] + public bool ParameterNames { get; set; } + + /// + /// Displays the values of parameters for the stack frame. + /// + [Optional] + public bool ParameterValues { get; set; } + + /// + /// Displays the line long of the stack frame. + /// + [Optional] + public bool Line { get; set; } + + /// + /// Displays the module of the stack frame. + /// + [Optional] + public bool Module { get; set; } + + /// + /// Includes all stack frames, including those the debug adapter might otherwise hide. + /// + [Optional] + public bool IncludeAll { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/StepBackFeature.cs b/src/Dap.Protocol/Feature/Requests/StepBackFeature.cs new file mode 100644 index 000000000..0cfb45e01 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/StepBackFeature.cs @@ -0,0 +1,43 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.StepBack, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StepBackArguments : IRequest + { + /// + /// Execute 'stepBack' for this thread. + /// + public long ThreadId { get; set; } + + /// + /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + /// + [Optional] + public SteppingGranularity? Granularity { get; set; } + } + + public class StepBackResponse + { + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/StepInFeature.cs b/src/Dap.Protocol/Feature/Requests/StepInFeature.cs new file mode 100644 index 000000000..3fde7e64a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/StepInFeature.cs @@ -0,0 +1,49 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.StepIn, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StepInArguments : IRequest + { + /// + /// Execute 'stepIn' for this thread. + /// + public long ThreadId { get; set; } + + /// + /// Optional id of the target to step into. + /// + [Optional] + public long? TargetId { get; set; } + + /// + /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + /// + [Optional] + public SteppingGranularity? Granularity { get; set; } + } + + public class StepInResponse + { + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/StepInTargetsFeature.cs b/src/Dap.Protocol/Feature/Requests/StepInTargetsFeature.cs new file mode 100644 index 000000000..c355cc4f0 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/StepInTargetsFeature.cs @@ -0,0 +1,55 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.StepInTargets, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StepInTargetsArguments : IRequest + { + /// + /// The stack frame for which to retrieve the possible stepIn targets. + /// + public long FrameId { get; set; } + } + + public class StepInTargetsResponse + { + /// + /// The possible stepIn targets of the specified source location. + /// + public Container? Targets { get; set; } + } + } + + namespace Models + { + /// + /// A StepInTarget can be used in the ‘stepIn’ request and determines into which single target the stepIn request should step. + /// + public class StepInTarget + { + /// + /// Unique identifier for a stepIn target. + /// + public long Id { get; set; } + + /// + /// The name of the stepIn target (shown in the UI). + /// + public string Label { get; set; } = null!; + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/StepOutFeature.cs b/src/Dap.Protocol/Feature/Requests/StepOutFeature.cs new file mode 100644 index 000000000..1ee5f97a5 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/StepOutFeature.cs @@ -0,0 +1,43 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.StepOut, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class StepOutArguments : IRequest + { + /// + /// Execute 'stepOut' for this thread. + /// + public long ThreadId { get; set; } + + /// + /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. + /// + [Optional] + public SteppingGranularity? Granularity { get; set; } + } + + public class StepOutResponse + { + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/TerminateFeature.cs b/src/Dap.Protocol/Feature/Requests/TerminateFeature.cs new file mode 100644 index 000000000..f7cc7104f --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/TerminateFeature.cs @@ -0,0 +1,37 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Terminate, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class TerminateArguments : IRequest + { + /// + /// A value of true indicates that this 'terminate' request is part of a restart sequence. + /// + [Optional] + public bool Restart { get; set; } + } + + public class TerminateResponse + { + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/TerminateThreadsFeature.cs b/src/Dap.Protocol/Feature/Requests/TerminateThreadsFeature.cs new file mode 100644 index 000000000..0fd5ac93b --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/TerminateThreadsFeature.cs @@ -0,0 +1,38 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.TerminateThreads, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class TerminateThreadsArguments : IRequest + { + /// + /// Ids of threads to be terminated. + /// + [Optional] + public Container? ThreadIds { get; set; } + } + + public class TerminateThreadsResponse + { + } + } + + namespace Models + { + } +} diff --git a/src/Dap.Protocol/Feature/Requests/ThreadsFeature.cs b/src/Dap.Protocol/Feature/Requests/ThreadsFeature.cs new file mode 100644 index 000000000..5ae913f34 --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/ThreadsFeature.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using Thread = System.Threading.Thread; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Threads, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class ThreadsArguments : IRequest + { + } + + public class ThreadsResponse + { + /// + /// All threads. + /// + public Container? Threads { get; set; } + } + } +} diff --git a/src/Dap.Protocol/Feature/Requests/VariablesFeature.cs b/src/Dap.Protocol/Feature/Requests/VariablesFeature.cs new file mode 100644 index 000000000..baad55a7a --- /dev/null +++ b/src/Dap.Protocol/Feature/Requests/VariablesFeature.cs @@ -0,0 +1,69 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.DebugAdapter.Protocol +{ + namespace Requests + { + [Parallel] + [Method(RequestNames.Variables, Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods, + GenerateRequestMethods + ] + public class VariablesArguments : IRequest + { + /// + /// The Variable reference. + /// + public long VariablesReference { get; set; } + + /// + /// Optional filter to limit the child variables to either named or indexed.If ommited, both types are fetched. + /// + [Optional] + public VariablesArgumentsFilter? Filter { get; set; } + + /// + /// The index of the first variable to return; if omitted children start at 0. + /// + [Optional] + public long? Start { get; set; } + + /// + /// The number of variables to return. If count is missing or 0, all variables are returned. + /// + [Optional] + public long? Count { get; set; } + + /// + /// Specifies details on how to format the Variable values. + /// + [Optional] + public ValueFormat? Format { get; set; } + } + + public class VariablesResponse + { + /// + /// All(or a range) of variables for the given variable reference. + /// + public Container? Variables { get; set; } + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum VariablesArgumentsFilter + { + Indexed, Named + } + } +} diff --git a/src/Dap.Protocol/Models/Breakpoint.cs b/src/Dap.Protocol/Models/Breakpoint.cs deleted file mode 100644 index 04022e9bb..000000000 --- a/src/Dap.Protocol/Models/Breakpoint.cs +++ /dev/null @@ -1,70 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// Information about a Breakpoint created in setBreakpoints or setFunctionBreakpoints. - /// - public class Breakpoint - { - /// - /// An optional identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints. - /// - [Optional] - public long? Id { get; set; } - - /// - /// If true breakpoint could be set (but not necessarily at the desired location). - /// - public bool Verified { get; set; } - - /// - /// An optional message about the state of the breakpoint. This is shown to the user and can be used to explain why a breakpoint could not be verified. - /// - [Optional] - public string? Message { get; set; } - - /// - /// The source where the breakpoint is located. - /// - [Optional] - public Source? Source { get; set; } - - /// - /// The start line of the actual range covered by the breakpoint. - /// - [Optional] - public int? Line { get; set; } - - /// - /// An optional start column of the actual range covered by the breakpoint. - /// - [Optional] - public int? Column { get; set; } - - /// - /// An optional end line of the actual range covered by the breakpoint. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// An optional end column of the actual range covered by the breakpoint. If no end line is given, then the end column is assumed to be in the start line. - /// - [Optional] - public int? EndColumn { get; set; } - - /// - /// An optional memory reference to where the breakpoint is set. - /// - [Optional] - public string? InstructionReference { get; set; } - - /// - /// An optional offset from the instruction reference. - /// This can be negative. - /// - [Optional] - public int? Offset { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/BreakpointLocation.cs b/src/Dap.Protocol/Models/BreakpointLocation.cs deleted file mode 100644 index ef362e811..000000000 --- a/src/Dap.Protocol/Models/BreakpointLocation.cs +++ /dev/null @@ -1,30 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - public class BreakpointLocation - { - /// - /// Start line of breakpoint location. - /// - public int Line { get; set; } - - /// - /// Optional start column of breakpoint location. - /// - [Optional] - public int? Column { get; set; } - - /// - /// Optional end line of breakpoint location if the location covers a range. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// Optional end column of breakpoint location if the location covers a range. - /// - [Optional] - public int? EndColumn { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/Capabilities.cs b/src/Dap.Protocol/Models/Capabilities.cs deleted file mode 100644 index 5a35c1ce4..000000000 --- a/src/Dap.Protocol/Models/Capabilities.cs +++ /dev/null @@ -1,216 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// Information about the capabilities of a debug adapter. - /// - public class Capabilities - { - /// - /// The debug adapter supports the 'configurationDone' request. - /// - [Optional] - public bool SupportsConfigurationDoneRequest { get; set; } - - /// - /// The debug adapter supports function breakpoints. - /// - [Optional] - public bool SupportsFunctionBreakpoints { get; set; } - - /// - /// The debug adapter supports conditional breakpoints. - /// - [Optional] - public bool SupportsConditionalBreakpoints { get; set; } - - /// - /// The debug adapter supports breakpoints that break execution after a specified long of hits. - /// - [Optional] - public bool SupportsHitConditionalBreakpoints { get; set; } - - /// - /// The debug adapter supports a (side effect free) evaluate request for data hovers. - /// - [Optional] - public bool SupportsEvaluateForHovers { get; set; } - - /// - /// Available filters or options for the setExceptionBreakpoints request. - /// - [Optional] - public Container? ExceptionBreakpointFilters { get; set; } - - /// - /// The debug adapter supports stepping back via the 'stepBack' and 'reverseContinue' requests. - /// - [Optional] - public bool SupportsStepBack { get; set; } - - /// - /// The debug adapter supports setting a variable to a value. - /// - [Optional] - public bool SupportsSetVariable { get; set; } - - /// - /// The debug adapter supports restarting a frame. - /// - [Optional] - public bool SupportsRestartFrame { get; set; } - - /// - /// The debug adapter supports the 'gotoTargets' request. - /// - [Optional] - public bool SupportsGotoTargetsRequest { get; set; } - - /// - /// The debug adapter supports the 'stepInTargets' request. - /// - [Optional] - public bool SupportsStepInTargetsRequest { get; set; } - - /// - /// The debug adapter supports the 'completions' request. - /// - [Optional] - public bool SupportsCompletionsRequest { get; set; } - - /// - /// The debug adapter supports the 'modules' request. - /// - [Optional] - public bool SupportsModulesRequest { get; set; } - - /// - /// The set of additional module information exposed by the debug adapter. - /// - [Optional] - public Container? AdditionalModuleColumns { get; set; } - - /// - /// Checksum algorithms supported by the debug adapter. - /// - [Optional] - public Container? SupportedChecksumAlgorithms { get; set; } - - /// - /// The debug adapter supports the 'restart' request. In this case a client should not implement 'restart' by terminating and relaunching the adapter but by calling the - /// RestartRequest. - /// - [Optional] - public bool SupportsRestartRequest { get; set; } - - /// - /// The debug adapter supports 'exceptionOptions' on the setExceptionBreakpoints request. - /// - [Optional] - public bool SupportsExceptionOptions { get; set; } - - /// - /// The debug adapter supports a 'format' attribute on the stackTraceRequest, variablesRequest, and evaluateRequest. - /// - [Optional] - public bool SupportsValueFormattingOptions { get; set; } - - /// - /// The debug adapter supports the 'exceptionInfo' request. - /// - [Optional] - public bool SupportsExceptionInfoRequest { get; set; } - - /// - /// The debug adapter supports the 'terminateDebuggee' attribute on the 'disconnect' request. - /// - [Optional] - public bool SupportTerminateDebuggee { get; set; } - - /// - /// The debug adapter supports the delayed loading of parts of the stack, which requires that both the 'startFrame' and 'levels' arguments and the 'totalFrames' result of the - /// 'StackTrace' request are supported. - /// - [Optional] - public bool SupportsDelayedStackTraceLoading { get; set; } - - /// - /// The debug adapter supports the 'loadedSources' request. - /// - [Optional] - public bool SupportsLoadedSourcesRequest { get; set; } - - /// - /// The debug adapter supports logpoints by interpreting the 'logMessage' attribute of the SourceBreakpoint. - /// - [Optional] - public bool SupportsLogPoints { get; set; } - - /// - /// The debug adapter supports the 'terminateThreads' request. - /// - [Optional] - public bool SupportsTerminateThreadsRequest { get; set; } - - /// - /// The debug adapter supports the 'setExpression' request. - /// - [Optional] - public bool SupportsSetExpression { get; set; } - - /// - /// The debug adapter supports the 'terminate' request. - /// - [Optional] - public bool SupportsTerminateRequest { get; set; } - - /// - /// The debug adapter supports data breakpoints. - /// - [Optional] - public bool SupportsDataBreakpoints { get; set; } - - /// - /// The debug adapter supports the 'readMemory' request. - /// - [Optional] - public bool SupportsReadMemoryRequest { get; set; } - - /// - /// The debug adapter supports the 'disassemble' request. - /// - [Optional] - public bool SupportsDisassembleRequest { get; set; } - - /// - /// The debug adapter supports the 'cancel' request. - /// - [Optional] - public bool SupportsCancelRequest { get; set; } - - /// - /// The debug adapter supports the 'breakpointLocations' request. - /// - [Optional] - public bool SupportsBreakpointLocationsRequest { get; set; } - - /// - /// The debug adapter supports the 'clipboard' context value in the 'evaluate' request. - /// - [Optional] - public bool SupportsClipboardContext { get; set; } - - /// - /// The debug adapter supports stepping granularities (argument 'granularity') for the stepping requests. - /// - [Optional] - public bool SupportsSteppingGranularity { get; set; } - - /// - /// The debug adapter supports adding breakpoints based on instruction references. - /// - [Optional] - public bool SupportsInstructionBreakpoints { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/CompletionItem.cs b/src/Dap.Protocol/Models/CompletionItem.cs deleted file mode 100644 index 2133deb00..000000000 --- a/src/Dap.Protocol/Models/CompletionItem.cs +++ /dev/null @@ -1,57 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// CompletionItems are the suggestions returned from the CompletionsRequest. - /// - public class CompletionItem - { - /// - /// The label of this completion item. By default this is also the text that is inserted when selecting this completion. - /// - public string Label { get; set; } = null!; - - /// - /// If text is not falsy then it is inserted instead of the label. - /// - [Optional] - public string? Text { get; set; } = null!; - - /// - /// The item's type. Typically the client uses this information to render the item in the UI with an icon. - /// - [Optional] - public CompletionItemType Type { get; set; } - - /// - /// This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added. - /// If missing the text is added at the location specified by the CompletionsRequest's 'column' attribute. - /// - [Optional] - public int? Start { get; set; } - - /// - /// This value determines how many characters are overwritten by the completion text. - /// If missing the value 0 is assumed which results in the completion text being inserted. - /// - [Optional] - public int? Length { get; set; } - - /// - /// Determines the start of the new selection after the text has been inserted (or replaced). - /// The start position must in the range 0 and length of the completion text. - /// If omitted the selection starts at the end of the completion text. - /// - [Optional] - public int? SelectionStart { get; set; } - - /// - /// Determines the length of the new selection after the text has been inserted (or replaced). - /// The selection can not extend beyond the bounds of the completion text. - /// If omitted the length is assumed to be 0. - /// - [Optional] - public int? SelectionLength { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/CompletionItemType.cs b/src/Dap.Protocol/Models/CompletionItemType.cs deleted file mode 100644 index dd6412356..000000000 --- a/src/Dap.Protocol/Models/CompletionItemType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// Some predefined types for the CompletionItem.Please note that not all clients have specific icons for all of them. - /// - [JsonConverter(typeof(StringEnumConverter))] - public enum CompletionItemType - { - Method, Function, Constructor, Field, Variable, Class, Interface, Module, Property, Unit, Value, Enum, Keyword, Snippet, Text, Color, File, Reference, CustomColor - } -} diff --git a/src/Dap.Protocol/Models/DisassembledInstruction.cs b/src/Dap.Protocol/Models/DisassembledInstruction.cs deleted file mode 100644 index f19e08667..000000000 --- a/src/Dap.Protocol/Models/DisassembledInstruction.cs +++ /dev/null @@ -1,64 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// DisassembledInstruction - /// Represents a single disassembled instruction. - /// - public class DisassembledInstruction - { - /// - /// The address of the instruction. Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. - /// - public string Address { get; set; } = null!; - - /// - /// Optional raw bytes representing the instruction and its operands, in an implementation-defined format. - /// - [Optional] - public string? InstructionBytes { get; set; } - - /// - /// Text representing the instruction and its operands, in an implementation-defined format. - /// - public string Instruction { get; set; } = null!; - - /// - /// Name of the symbol that correponds with the location of this instruction, if any. - /// - [Optional] - public string? Symbol { get; set; } - - /// - /// Source location that corresponds to this instruction, if any. Should always be set (if available) on the first instruction returned, but can be omitted afterwards if this - /// instruction maps to the same source file as the previous instruction. - /// - [Optional] - public Source? Location { get; set; } - - /// - /// The line within the source location that corresponds to this instruction, if any. - /// - [Optional] - public int? Line { get; set; } - - /// - /// The column within the line that corresponds to this instruction, if any. - /// - [Optional] - public int? Column { get; set; } - - /// - /// The end line of the range that corresponds to this instruction, if any. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// The end column of the range that corresponds to this instruction, if any. - /// - [Optional] - public int? EndColumn { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/ExceptionBreakMode.cs b/src/Dap.Protocol/Models/ExceptionBreakMode.cs deleted file mode 100644 index b2138d2a8..000000000 --- a/src/Dap.Protocol/Models/ExceptionBreakMode.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// This enumeration defines all possible conditions when a thrown exception should result in a break. - /// never: never breaks, - /// always: always breaks, - /// unhandled: breaks when excpetion unhandled, - /// userUnhandled: breaks if the exception is not handled by user code. - /// - [JsonConverter(typeof(StringEnumConverter))] - public enum ExceptionBreakMode - { - Never, Always, Unhandled, UserUnhandled - } -} diff --git a/src/Dap.Protocol/Models/ExceptionOptions.cs b/src/Dap.Protocol/Models/ExceptionOptions.cs deleted file mode 100644 index 4a8b21247..000000000 --- a/src/Dap.Protocol/Models/ExceptionOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// ExceptionOptions - /// An ExceptionOptions assigns configuration options to a set of exceptions. - /// - public class ExceptionOptions - { - /// - /// A path that selects a single or multiple exceptions in a tree. If 'path' is missing, the whole tree is selected. By convention the first segment of the path is a category that is - /// used to group exceptions in the UI. - /// - [Optional] - public Container? Path { get; set; } - - /// - /// Condition when a thrown exception should result in a break. - /// - public ExceptionBreakMode BreakMode { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/ExceptionPathSegment.cs b/src/Dap.Protocol/Models/ExceptionPathSegment.cs deleted file mode 100644 index 545ae94dc..000000000 --- a/src/Dap.Protocol/Models/ExceptionPathSegment.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions.If a segment consists of more than one name, it matches the - /// names provided if ‘negate’ is false or missing or it matches anything except the names provided if ‘negate’ is true. - /// - public class ExceptionPathSegment - { - /// - /// If false or missing this segment matches the names provided, otherwise it matches anything except the names provided. - /// - [Optional] - public bool Negate { get; set; } - - /// - /// Depending on the value of 'negate' the names that should match or not match. - /// - public Container Names { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Models/FunctionBreakpoint.cs b/src/Dap.Protocol/Models/FunctionBreakpoint.cs deleted file mode 100644 index 9805bdb61..000000000 --- a/src/Dap.Protocol/Models/FunctionBreakpoint.cs +++ /dev/null @@ -1,28 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// FunctionBreakpoint - /// Properties of a breakpoint passed to the setFunctionBreakpoints request. - /// - public class FunctionBreakpoint - { - /// - /// The name of the function. - /// - public string Name { get; set; } = null!; - - /// - /// An optional expression for conditional breakpoints. - /// - [Optional] - public string? Condition { get; set; } - - /// - /// An optional expression that controls how many hits of the breakpoint are ignored. The backend is expected to interpret the expression as needed. - /// - [Optional] - public string? HitCondition { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/GotoTarget.cs b/src/Dap.Protocol/Models/GotoTarget.cs deleted file mode 100644 index 35ab6c0bf..000000000 --- a/src/Dap.Protocol/Models/GotoTarget.cs +++ /dev/null @@ -1,50 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// A GotoTarget describes a code location that can be used as a target in the ‘goto’ request. - /// The possible goto targets can be determined via the ‘gotoTargets’ request. - /// - public class GotoTarget - { - /// - /// Unique identifier for a goto target. This is used in the goto request. - /// - public long Id { get; set; } - - /// - /// The name of the goto target (shown in the UI). - /// - public string Label { get; set; } = null!; - - /// - /// The line of the goto target. - /// - public int Line { get; set; } - - /// - /// An optional column of the goto target. - /// - [Optional] - public int? Column { get; set; } - - /// - /// An optional end line of the range covered by the goto target. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// An optional end column of the range covered by the goto target. - /// - [Optional] - public int? EndColumn { get; set; } - - /// - /// Optional memory reference for the instruction pointer value represented by this target. - /// - [Optional] - public string? InstructionPointerReference { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/Scope.cs b/src/Dap.Protocol/Models/Scope.cs deleted file mode 100644 index d6f7af1ee..000000000 --- a/src/Dap.Protocol/Models/Scope.cs +++ /dev/null @@ -1,80 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// A Scope is a named container for variables.Optionally a scope can map to a source or a range within a source. - /// - public class Scope - { - /// - /// Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. - /// - public string Name { get; set; } = null!; - - /// - /// An optional hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI. - /// Values: - /// 'arguments': Scope contains method arguments. - /// 'locals': Scope contains local variables. - /// 'registers': Scope contains registers. Only a single 'registers' scope should be returned from a 'scopes' request. - /// etc. - /// - [Optional] - public string? PresentationHint { get; set; } - - /// - /// The variables of this scope can be retrieved by passing the value of variablesReference to the VariablesRequest. - /// - public long VariablesReference { get; set; } - - /// - /// The long of named variables in this scope. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? NamedVariables { get; set; } - - /// - /// The long of indexed variables in this scope. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? IndexedVariables { get; set; } - - /// - /// If true, the long of variables in this scope is large or expensive to retrieve. - /// - public bool Expensive { get; set; } - - /// - /// Optional source for this scope. - /// - [Optional] - public Source? Source { get; set; } - - /// - /// Optional start line of the range covered by this scope. - /// - [Optional] - public int? Line { get; set; } - - /// - /// Optional start column of the range covered by this scope. - /// - [Optional] - public int? Column { get; set; } - - /// - /// Optional end line of the range covered by this scope. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// Optional end column of the range covered by this scope. - /// - [Optional] - public int? EndColumn { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/StackFrameFormat.cs b/src/Dap.Protocol/Models/StackFrameFormat.cs deleted file mode 100644 index 7280a8363..000000000 --- a/src/Dap.Protocol/Models/StackFrameFormat.cs +++ /dev/null @@ -1,52 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// Provides formatting information for a stack frame. - /// - public class StackFrameFormat : ValueFormat - { - /// - /// Displays parameters for the stack frame. - /// - [Optional] - public bool Parameters { get; set; } - - /// - /// Displays the types of parameters for the stack frame. - /// - [Optional] - public bool ParameterTypes { get; set; } - - /// - /// Displays the names of parameters for the stack frame. - /// - [Optional] - public bool ParameterNames { get; set; } - - /// - /// Displays the values of parameters for the stack frame. - /// - [Optional] - public bool ParameterValues { get; set; } - - /// - /// Displays the line long of the stack frame. - /// - [Optional] - public bool Line { get; set; } - - /// - /// Displays the module of the stack frame. - /// - [Optional] - public bool Module { get; set; } - - /// - /// Includes all stack frames, including those the debug adapter might otherwise hide. - /// - [Optional] - public bool IncludeAll { get; set; } - } -} diff --git a/src/Dap.Protocol/Models/StepInTarget.cs b/src/Dap.Protocol/Models/StepInTarget.cs deleted file mode 100644 index 762d814df..000000000 --- a/src/Dap.Protocol/Models/StepInTarget.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Models -{ - /// - /// A StepInTarget can be used in the ‘stepIn’ request and determines into which single target the stepIn request should step. - /// - public class StepInTarget - { - /// - /// Unique identifier for a stepIn target. - /// - public long Id { get; set; } - - /// - /// The name of the stepIn target (shown in the UI). - /// - public string Label { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/AttachRequestArguments.cs b/src/Dap.Protocol/Requests/AttachRequestArguments.cs deleted file mode 100644 index 08e785e96..000000000 --- a/src/Dap.Protocol/Requests/AttachRequestArguments.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using MediatR; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Attach, Direction.ClientToServer)] - public class AttachRequestArguments : IRequest - { - /// - /// Optional data from the previous, restarted session. - /// The data is sent as the 'restart' attribute of the 'terminated' event. - /// The client should leave the data intact. - /// - [Optional] - [JsonProperty(PropertyName = "__restart")] - public JToken? Restart { get; set; } - - [JsonExtensionData] public IDictionary ExtensionData { get; set; } = new Dictionary(); - } -} diff --git a/src/Dap.Protocol/Requests/AttachResponse.cs b/src/Dap.Protocol/Requests/AttachResponse.cs deleted file mode 100644 index 06339ab55..000000000 --- a/src/Dap.Protocol/Requests/AttachResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class AttachResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/BreakpointLocationsArguments.cs b/src/Dap.Protocol/Requests/BreakpointLocationsArguments.cs deleted file mode 100644 index 585d90402..000000000 --- a/src/Dap.Protocol/Requests/BreakpointLocationsArguments.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.BreakpointLocations, Direction.ClientToServer)] - public class BreakpointLocationsArguments : IRequest - { - /// - /// The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. - /// - public Source Source { get; set; } = null!; - - /// - /// Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line. - /// - public int Line { get; set; } - - /// - /// Optional start column of range to search possible breakpoint locations in. If no start column is given, the first column in the start line is assumed. - /// - [Optional] - public int? Column { get; set; } - - /// - /// Optional end line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line. - /// - [Optional] - public int? EndLine { get; set; } - - /// - /// Optional end column of range to search possible breakpoint locations in. If no end column is given, then it is assumed to be in the last column of the end line. - /// - [Optional] - public int? EndColumn { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/BreakpointLocationsResponse.cs b/src/Dap.Protocol/Requests/BreakpointLocationsResponse.cs deleted file mode 100644 index 9e03d80fd..000000000 --- a/src/Dap.Protocol/Requests/BreakpointLocationsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class BreakpointLocationsResponse - { - /// - /// Sorted set of possible breakpoint locations. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/CancelArguments.cs b/src/Dap.Protocol/Requests/CancelArguments.cs deleted file mode 100644 index ba7bf2fe9..000000000 --- a/src/Dap.Protocol/Requests/CancelArguments.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - /// - /// DAP is kind of silly.... - /// Cancellation is for requests and progress tokens... hopefully if isn't ever expanded any further... because that would be fun. - /// - [Method(RequestNames.Cancel, Direction.ClientToServer)] - public class CancelArguments : IRequest - { - // This is removed on purpose, as request cancellation is handled by the DapReciever - // /// - // /// The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. - // /// Both a 'requestId' and a 'progressId' can be specified in one request. - // /// - // [Optional] - // public int? RequestId { get; set; } - - /// - /// The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled. - /// Both a 'requestId' and a 'progressId' can be specified in one request. - /// - [Optional] - public ProgressToken? ProgressId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/CancelResponse.cs b/src/Dap.Protocol/Requests/CancelResponse.cs deleted file mode 100644 index e6e2c40ae..000000000 --- a/src/Dap.Protocol/Requests/CancelResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class CancelResponse - { - /// - /// The ID (attribute 'seq') of the request to cancel. If missing no request is cancelled. - /// Both a 'requestId' and a 'progressId' can be specified in one request. - /// - [Optional] - public int? RequestId { get; set; } - - /// - /// The ID (attribute 'progressId') of the progress to cancel. If missing no progress is cancelled. - /// Both a 'requestId' and a 'progressId' can be specified in one request. - /// - [Optional] - public ProgressToken? ProgressId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/CompletionsArguments.cs b/src/Dap.Protocol/Requests/CompletionsArguments.cs deleted file mode 100644 index 9a589b895..000000000 --- a/src/Dap.Protocol/Requests/CompletionsArguments.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Completions, Direction.ClientToServer)] - public class CompletionsArguments : IRequest - { - /// - /// Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope. - /// - [Optional] - public long? FrameId { get; set; } - - /// - /// One or more source lines.Typically this is the text a user has typed into the debug console before he asked for completion. - /// - public string Text { get; set; } = null!; - - /// - /// The character position for which to determine the completion proposals. - /// - public long Column { get; set; } - - /// - /// An optional line for which to determine the completion proposals.If missing the first line of the text is assumed. - /// - [Optional] - public long? Line { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/CompletionsResponse.cs b/src/Dap.Protocol/Requests/CompletionsResponse.cs deleted file mode 100644 index 0c1594f7b..000000000 --- a/src/Dap.Protocol/Requests/CompletionsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class CompletionsResponse - { - /// - /// The possible completions for . - /// - public Container Targets { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/ConfigurationDoneArguments.cs b/src/Dap.Protocol/Requests/ConfigurationDoneArguments.cs deleted file mode 100644 index 2c367764d..000000000 --- a/src/Dap.Protocol/Requests/ConfigurationDoneArguments.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.ConfigurationDone, Direction.ClientToServer)] - public class ConfigurationDoneArguments : IRequest - { - } -} diff --git a/src/Dap.Protocol/Requests/ConfigurationDoneResponse.cs b/src/Dap.Protocol/Requests/ConfigurationDoneResponse.cs deleted file mode 100644 index 341cfa8a9..000000000 --- a/src/Dap.Protocol/Requests/ConfigurationDoneResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ConfigurationDoneResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/ContinueArguments.cs b/src/Dap.Protocol/Requests/ContinueArguments.cs deleted file mode 100644 index eaa283a7f..000000000 --- a/src/Dap.Protocol/Requests/ContinueArguments.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Continue, Direction.ClientToServer)] - public class ContinueArguments : IRequest - { - /// - /// Continue execution for the specified thread(if possible). If the backend cannot continue on a single thread but will continue on all threads, it should set the - /// 'allThreadsContinued' attribute in the response to true. - /// - public long ThreadId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ContinueResponse.cs b/src/Dap.Protocol/Requests/ContinueResponse.cs deleted file mode 100644 index 3334bfaf8..000000000 --- a/src/Dap.Protocol/Requests/ContinueResponse.cs +++ /dev/null @@ -1,14 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ContinueResponse - { - /// - /// If true, the 'continue' request has ignored the specified thread and continued all threads instead.If this attribute is missing a value of 'true' is assumed for backward - /// compatibility. - /// - [Optional] - public bool AllThreadsContinued { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/DataBreakpointInfoArguments.cs b/src/Dap.Protocol/Requests/DataBreakpointInfoArguments.cs deleted file mode 100644 index aabe515dc..000000000 --- a/src/Dap.Protocol/Requests/DataBreakpointInfoArguments.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.DataBreakpointInfo, Direction.ClientToServer)] - public class DataBreakpointInfoArguments : IRequest - { - /// - /// Reference to the Variable container if the data breakpoint is requested for a child of the container. - /// - [Optional] - public long? VariablesReference { get; set; } - - /// - /// The name of the Variable's child to obtain data breakpoint information for. If variableReference isn’t provided, this can be an expression. - /// - public string Name { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/DataBreakpointInfoResponse.cs b/src/Dap.Protocol/Requests/DataBreakpointInfoResponse.cs deleted file mode 100644 index 86eaa0283..000000000 --- a/src/Dap.Protocol/Requests/DataBreakpointInfoResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class DataBreakpointInfoResponse - { - /// - /// An identifier for the data on which a data breakpoint can be registered with the setDataBreakpoints request or null if no data breakpoint is available. - /// - public string DataId { get; set; } = null!; - - /// - /// UI string that describes on what data the breakpoint is set on or why a data breakpoint is not available. - /// - public string Description { get; set; } = null!; - - /// - /// Optional attribute listing the available access types for a potential data breakpoint.A UI frontend could surface this information. - /// - [Optional] - public Container? AccessTypes { get; set; } - - /// - /// Optional attribute indicating that a potential data breakpoint could be persisted across sessions. - /// - [Optional] - public bool CanPersist { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/DisassembleArguments.cs b/src/Dap.Protocol/Requests/DisassembleArguments.cs deleted file mode 100644 index 44a5ee484..000000000 --- a/src/Dap.Protocol/Requests/DisassembleArguments.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Disassemble, Direction.ClientToServer)] - public class DisassembleArguments : IRequest - { - /// - /// Memory reference to the base location containing the instructions to disassemble. - /// - public string MemoryReference { get; set; } = null!; - - /// - /// Optional offset(in bytes) to be applied to the reference location before disassembling.Can be negative. - /// - [Optional] - public long? Offset { get; set; } - - /// - /// Optional offset(in instructions) to be applied after the byte offset(if any) before disassembling.Can be negative. - /// - - [Optional] - public long? InstructionOffset { get; set; } - - /// - /// Number of instructions to disassemble starting at the specified location and offset.An adapter must return exactly this number of instructions - any unavailable instructions - /// should be replaced with an implementation-defined 'invalid instruction' value. - /// - public long InstructionCount { get; set; } - - /// - /// If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. - /// - [Optional] - public bool ResolveSymbols { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/DisassembleResponse.cs b/src/Dap.Protocol/Requests/DisassembleResponse.cs deleted file mode 100644 index f81cdd8f5..000000000 --- a/src/Dap.Protocol/Requests/DisassembleResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class DisassembleResponse - { - /// - /// The list of disassembled instructions. - /// - public Container Instructions { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/DisconnectArguments.cs b/src/Dap.Protocol/Requests/DisconnectArguments.cs deleted file mode 100644 index 98520e7d0..000000000 --- a/src/Dap.Protocol/Requests/DisconnectArguments.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Disconnect, Direction.ClientToServer)] - public class DisconnectArguments : IRequest - { - /// - /// A value of true indicates that this 'disconnect' request is part of a restart sequence. - /// - [Optional] - public bool Restart { get; set; } - - /// - /// Indicates whether the debuggee should be terminated when the debugger is disconnected. - /// If unspecified, the debug adapter is free to do whatever it thinks is best. - /// A client can only rely on this attribute being properly honored if a debug adapter returns true for the 'supportTerminateDebuggee' capability. - /// - [Optional] - public bool TerminateDebuggee { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/DisconnectResponse.cs b/src/Dap.Protocol/Requests/DisconnectResponse.cs deleted file mode 100644 index 2a58dee1d..000000000 --- a/src/Dap.Protocol/Requests/DisconnectResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class DisconnectResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/EvaluateArguments.cs b/src/Dap.Protocol/Requests/EvaluateArguments.cs deleted file mode 100644 index 5f7ef0ce3..000000000 --- a/src/Dap.Protocol/Requests/EvaluateArguments.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Evaluate, Direction.ClientToServer)] - public class EvaluateArguments : IRequest - { - /// - /// The expression to evaluate. - /// - public string Expression { get; set; } = null!; - - /// - /// Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. - /// - [Optional] - public long? FrameId { get; set; } - - /// - /// The context in which the evaluate request is run. - /// Values: - /// 'watch': evaluate is run in a watch. - /// 'repl': evaluate is run from REPL console. - /// 'hover': evaluate is run from a data hover. - /// etc. - /// - [Optional] - public string? Context { get; set; } - - /// - /// Specifies details on how to format the Evaluate result. - /// - [Optional] - public ValueFormat? Format { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/EvaluateResponse.cs b/src/Dap.Protocol/Requests/EvaluateResponse.cs deleted file mode 100644 index 30a3165a3..000000000 --- a/src/Dap.Protocol/Requests/EvaluateResponse.cs +++ /dev/null @@ -1,50 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class EvaluateResponse - { - /// - /// The result of the evaluate request. - /// - public string Result { get; set; } = null!; - - /// - /// The optional type of the evaluate result. - /// - [Optional] - public string? Type { get; set; } - - /// - /// Properties of a evaluate result that can be used to determine how to render the result in the UI. - /// - [Optional] - public VariablePresentationHint? PresentationHint { get; set; } - - /// - /// If variablesReference is > 0, the evaluate result is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - /// - public long VariablesReference { get; set; } - - /// - /// The number of named child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? NamedVariables { get; set; } - - /// - /// The number of indexed child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? IndexedVariables { get; set; } - - /// - /// Memory reference to a location appropriate for this result.For pointer type eval results, this is generally a reference to the memory address contained in the pointer. - /// - [Optional] - public string? MemoryReference { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ExceptionInfoArguments.cs b/src/Dap.Protocol/Requests/ExceptionInfoArguments.cs deleted file mode 100644 index 2b8c2818e..000000000 --- a/src/Dap.Protocol/Requests/ExceptionInfoArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.ExceptionInfo, Direction.ClientToServer)] - public class ExceptionInfoArguments : IRequest - { - /// - /// Thread for which exception information should be retrieved. - /// - public long ThreadId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ExceptionInfoResponse.cs b/src/Dap.Protocol/Requests/ExceptionInfoResponse.cs deleted file mode 100644 index 85c56baec..000000000 --- a/src/Dap.Protocol/Requests/ExceptionInfoResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ExceptionInfoResponse - { - /// - /// ID of the exception that was thrown. - /// - public string ExceptionId { get; set; } = null!; - - /// - /// Descriptive text for the exception provided by the debug adapter. - /// - [Optional] - public string? Description { get; set; } - - /// - /// Mode that caused the exception notification to be raised. - /// - public ExceptionBreakMode BreakMode { get; set; } - - /// - /// Detailed information about the exception. - /// - [Optional] - public ExceptionDetails? Details { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/GotoArguments.cs b/src/Dap.Protocol/Requests/GotoArguments.cs deleted file mode 100644 index 6475246de..000000000 --- a/src/Dap.Protocol/Requests/GotoArguments.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Goto, Direction.ClientToServer)] - public class GotoArguments : IRequest - { - /// - /// Set the goto target for this thread. - /// - public long ThreadId { get; set; } - - /// - /// The location where the debuggee will continue to run. - /// - public long TargetId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/GotoResponse.cs b/src/Dap.Protocol/Requests/GotoResponse.cs deleted file mode 100644 index 4faf9abf5..000000000 --- a/src/Dap.Protocol/Requests/GotoResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class GotoResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/GotoTargetsArguments.cs b/src/Dap.Protocol/Requests/GotoTargetsArguments.cs deleted file mode 100644 index 424fea94b..000000000 --- a/src/Dap.Protocol/Requests/GotoTargetsArguments.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.GotoTargets, Direction.ClientToServer)] - public class GotoTargetsArguments : IRequest - { - /// - /// The source location for which the goto targets are determined. - /// - public Source Source { get; set; } = null!; - - /// - /// The line location for which the goto targets are determined. - /// - public long Line { get; set; } - - /// - /// An optional column location for which the goto targets are determined. - /// - [Optional] - public long? Column { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/GotoTargetsResponse.cs b/src/Dap.Protocol/Requests/GotoTargetsResponse.cs deleted file mode 100644 index 0852d5842..000000000 --- a/src/Dap.Protocol/Requests/GotoTargetsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class GotoTargetsResponse - { - /// - /// The possible goto targets of the specified location. - /// - public Container Targets { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/IAttachHandler.cs b/src/Dap.Protocol/Requests/IAttachHandler.cs deleted file mode 100644 index 07df0dba2..000000000 --- a/src/Dap.Protocol/Requests/IAttachHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Attach, Direction.ClientToServer)] - [GenerateHandlerMethods(AllowDerivedRequests = true)] - [GenerateRequestMethods] - public interface IAttachHandler : IJsonRpcRequestHandler where T : AttachRequestArguments - { - } - - public interface IAttachHandler : IAttachHandler - { - } - - public abstract class AttachHandlerBase : IAttachHandler where T : AttachRequestArguments - { - public abstract Task Handle(T request, CancellationToken cancellationToken); - } - - public abstract class AttachHandler : AttachHandlerBase, IAttachHandler - { - } -} diff --git a/src/Dap.Protocol/Requests/IBreakpointLocationsHandler.cs b/src/Dap.Protocol/Requests/IBreakpointLocationsHandler.cs deleted file mode 100644 index ad2d83d8a..000000000 --- a/src/Dap.Protocol/Requests/IBreakpointLocationsHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.BreakpointLocations, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IBreakpointLocationsHandler : IJsonRpcRequestHandler - { - } - - public abstract class BreakpointLocationsHandlerBase : IBreakpointLocationsHandler - { - public abstract Task Handle(BreakpointLocationsArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ICancelHandler.cs b/src/Dap.Protocol/Requests/ICancelHandler.cs deleted file mode 100644 index a90cf7eb0..000000000 --- a/src/Dap.Protocol/Requests/ICancelHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - /// - /// DAP is kind of silly.... - /// Cancellation is for requests and progress tokens... hopefully if isn't ever expanded any further... because that would be fun. - /// - [Parallel] - [Method(RequestNames.Cancel, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ICancelHandler : IJsonRpcRequestHandler - { - } - - public abstract class CancelHandlerBase : ICancelHandler - { - public abstract Task Handle(CancelArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ICompletionsHandler.cs b/src/Dap.Protocol/Requests/ICompletionsHandler.cs deleted file mode 100644 index ed6b41611..000000000 --- a/src/Dap.Protocol/Requests/ICompletionsHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Completions, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ICompletionsHandler : IJsonRpcRequestHandler - { - } - - public abstract class CompletionsHandler : ICompletionsHandler - { - public abstract Task Handle(CompletionsArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IConfigurationDoneHandler.cs b/src/Dap.Protocol/Requests/IConfigurationDoneHandler.cs deleted file mode 100644 index e8c7cc1ee..000000000 --- a/src/Dap.Protocol/Requests/IConfigurationDoneHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.ConfigurationDone, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface - IConfigurationDoneHandler : IJsonRpcRequestHandler - { - } - - public abstract class ConfigurationDoneHandler : IConfigurationDoneHandler - { - public abstract Task Handle( - ConfigurationDoneArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IContinueHandler.cs b/src/Dap.Protocol/Requests/IContinueHandler.cs deleted file mode 100644 index d610bbd8d..000000000 --- a/src/Dap.Protocol/Requests/IContinueHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Continue, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IContinueHandler : IJsonRpcRequestHandler - { - } - - public abstract class ContinueHandler : IContinueHandler - { - public abstract Task Handle(ContinueArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IDataBreakpointInfoHandler.cs b/src/Dap.Protocol/Requests/IDataBreakpointInfoHandler.cs deleted file mode 100644 index dddf32999..000000000 --- a/src/Dap.Protocol/Requests/IDataBreakpointInfoHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.DataBreakpointInfo, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface - IDataBreakpointInfoHandler : IJsonRpcRequestHandler - { - } - - public abstract class DataBreakpointInfoHandler : IDataBreakpointInfoHandler - { - public abstract Task Handle( - DataBreakpointInfoArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IDebugAdapterInitializeHandler.cs b/src/Dap.Protocol/Requests/IDebugAdapterInitializeHandler.cs deleted file mode 100644 index eb5298540..000000000 --- a/src/Dap.Protocol/Requests/IDebugAdapterInitializeHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Initialize, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IDebugAdapterInitializeHandler : IJsonRpcRequestHandler - { - } - - public abstract class DebugAdapterInitializeHandler : IDebugAdapterInitializeHandler - { - public abstract Task Handle( - InitializeRequestArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IDisassembleHandler.cs b/src/Dap.Protocol/Requests/IDisassembleHandler.cs deleted file mode 100644 index 59bbbc0ed..000000000 --- a/src/Dap.Protocol/Requests/IDisassembleHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Disassemble, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IDisassembleHandler : IJsonRpcRequestHandler - { - } - - public abstract class DisassembleHandler : IDisassembleHandler - { - public abstract Task Handle( - DisassembleArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IDisconnectHandler.cs b/src/Dap.Protocol/Requests/IDisconnectHandler.cs deleted file mode 100644 index 3583e86df..000000000 --- a/src/Dap.Protocol/Requests/IDisconnectHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Disconnect, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IDisconnectHandler : IJsonRpcRequestHandler - { - } - - public abstract class DisconnectHandler : IDisconnectHandler - { - public abstract Task Handle( - DisconnectArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IEvaluateHandler.cs b/src/Dap.Protocol/Requests/IEvaluateHandler.cs deleted file mode 100644 index 3cb7a9a97..000000000 --- a/src/Dap.Protocol/Requests/IEvaluateHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Evaluate, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IEvaluateHandler : IJsonRpcRequestHandler - { - } - - public abstract class EvaluateHandler : IEvaluateHandler - { - public abstract Task Handle(EvaluateArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IExceptionInfoHandler.cs b/src/Dap.Protocol/Requests/IExceptionInfoHandler.cs deleted file mode 100644 index fcb2044ac..000000000 --- a/src/Dap.Protocol/Requests/IExceptionInfoHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.ExceptionInfo, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IExceptionInfoHandler : IJsonRpcRequestHandler - { - } - - public abstract class ExceptionInfoHandler : IExceptionInfoHandler - { - public abstract Task Handle( - ExceptionInfoArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IGotoHandler.cs b/src/Dap.Protocol/Requests/IGotoHandler.cs deleted file mode 100644 index e7b10f35f..000000000 --- a/src/Dap.Protocol/Requests/IGotoHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Goto, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IGotoHandler : IJsonRpcRequestHandler - { - } - - public abstract class GotoHandler : IGotoHandler - { - public abstract Task Handle(GotoArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IGotoTargetsHandler.cs b/src/Dap.Protocol/Requests/IGotoTargetsHandler.cs deleted file mode 100644 index 381429062..000000000 --- a/src/Dap.Protocol/Requests/IGotoTargetsHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.GotoTargets, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IGotoTargetsHandler : IJsonRpcRequestHandler - { - } - - - public abstract class GotoTargetsHandler : IGotoTargetsHandler - { - public abstract Task Handle( - GotoTargetsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ILaunchHandler.cs b/src/Dap.Protocol/Requests/ILaunchHandler.cs deleted file mode 100644 index 9d5dd861f..000000000 --- a/src/Dap.Protocol/Requests/ILaunchHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Launch, Direction.ClientToServer)] - [GenerateHandlerMethods(AllowDerivedRequests = true)] - [GenerateRequestMethods] - public interface ILaunchHandler : IJsonRpcRequestHandler where T : LaunchRequestArguments - { - } - - public interface ILaunchHandler : ILaunchHandler - { - } - - public abstract class LaunchHandlerBase : ILaunchHandler where T : LaunchRequestArguments - { - public abstract Task Handle(T request, CancellationToken cancellationToken); - } - - public abstract class LaunchHandler : LaunchHandlerBase, ILaunchHandler - { - } -} diff --git a/src/Dap.Protocol/Requests/ILoadedSourcesHandler.cs b/src/Dap.Protocol/Requests/ILoadedSourcesHandler.cs deleted file mode 100644 index 4810d3d29..000000000 --- a/src/Dap.Protocol/Requests/ILoadedSourcesHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.LoadedSources, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ILoadedSourcesHandler : IJsonRpcRequestHandler - { - } - - public abstract class LoadedSourcesHandler : ILoadedSourcesHandler - { - public abstract Task Handle( - LoadedSourcesArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IModulesHandler.cs b/src/Dap.Protocol/Requests/IModulesHandler.cs deleted file mode 100644 index a023f1325..000000000 --- a/src/Dap.Protocol/Requests/IModulesHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Modules, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IModulesHandler : IJsonRpcRequestHandler - { - } - - public abstract class ModulesHandler : IModulesHandler - { - public abstract Task Handle(ModulesArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/INextHandler.cs b/src/Dap.Protocol/Requests/INextHandler.cs deleted file mode 100644 index 2e85d22eb..000000000 --- a/src/Dap.Protocol/Requests/INextHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Next, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface INextHandler : IJsonRpcRequestHandler - { - } - - public abstract class NextHandler : INextHandler - { - public abstract Task Handle(NextArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IPauseHandler.cs b/src/Dap.Protocol/Requests/IPauseHandler.cs deleted file mode 100644 index e8625f2ba..000000000 --- a/src/Dap.Protocol/Requests/IPauseHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Pause, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IPauseHandler : IJsonRpcRequestHandler - { - } - - public abstract class PauseHandler : IPauseHandler - { - public abstract Task Handle(PauseArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IReadMemoryHandler.cs b/src/Dap.Protocol/Requests/IReadMemoryHandler.cs deleted file mode 100644 index 5b0839761..000000000 --- a/src/Dap.Protocol/Requests/IReadMemoryHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.ReadMemory, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IReadMemoryHandler : IJsonRpcRequestHandler - { - } - - public abstract class ReadMemoryHandler : IReadMemoryHandler - { - public abstract Task Handle( - ReadMemoryArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IRestartFrameHandler.cs b/src/Dap.Protocol/Requests/IRestartFrameHandler.cs deleted file mode 100644 index 474415ab7..000000000 --- a/src/Dap.Protocol/Requests/IRestartFrameHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.RestartFrame, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IRestartFrameHandler : IJsonRpcRequestHandler - { - } - - public abstract class RestartFrameHandler : IRestartFrameHandler - { - public abstract Task Handle( - RestartFrameArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IRestartHandler.cs b/src/Dap.Protocol/Requests/IRestartHandler.cs deleted file mode 100644 index 52e8d4d14..000000000 --- a/src/Dap.Protocol/Requests/IRestartHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Restart, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IRestartHandler : IJsonRpcRequestHandler - { - } - - public abstract class RestartHandler : IRestartHandler - { - public abstract Task Handle(RestartArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IReverseContinueHandler.cs b/src/Dap.Protocol/Requests/IReverseContinueHandler.cs deleted file mode 100644 index 379d9a876..000000000 --- a/src/Dap.Protocol/Requests/IReverseContinueHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.ReverseContinue, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IReverseContinueHandler : IJsonRpcRequestHandler - { - } - - public abstract class ReverseContinueHandler : IReverseContinueHandler - { - public abstract Task Handle( - ReverseContinueArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IRunInTerminalHandler.cs b/src/Dap.Protocol/Requests/IRunInTerminalHandler.cs deleted file mode 100644 index fed3be45d..000000000 --- a/src/Dap.Protocol/Requests/IRunInTerminalHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.RunInTerminal, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IRunInTerminalHandler : IJsonRpcRequestHandler - { - } - - public abstract class RunInTerminalHandler : IRunInTerminalHandler - { - public abstract Task Handle(RunInTerminalArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IScopesHandler.cs b/src/Dap.Protocol/Requests/IScopesHandler.cs deleted file mode 100644 index cb1eaf6da..000000000 --- a/src/Dap.Protocol/Requests/IScopesHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Scopes, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IScopesHandler : IJsonRpcRequestHandler - { - } - - public abstract class ScopesHandler : IScopesHandler - { - public abstract Task Handle(ScopesArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ISetBreakpointsHandler.cs b/src/Dap.Protocol/Requests/ISetBreakpointsHandler.cs deleted file mode 100644 index adecde255..000000000 --- a/src/Dap.Protocol/Requests/ISetBreakpointsHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetBreakpoints, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISetBreakpointsHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetBreakpointsHandler : ISetBreakpointsHandler - { - public abstract Task Handle( - SetBreakpointsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISetDataBreakpointsHandler.cs b/src/Dap.Protocol/Requests/ISetDataBreakpointsHandler.cs deleted file mode 100644 index f8d2e2f6d..000000000 --- a/src/Dap.Protocol/Requests/ISetDataBreakpointsHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetDataBreakpoints, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface - ISetDataBreakpointsHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetDataBreakpointsHandler : ISetDataBreakpointsHandler - { - public abstract Task Handle( - SetDataBreakpointsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISetExceptionBreakpointsHandler.cs b/src/Dap.Protocol/Requests/ISetExceptionBreakpointsHandler.cs deleted file mode 100644 index ccc486be5..000000000 --- a/src/Dap.Protocol/Requests/ISetExceptionBreakpointsHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetExceptionBreakpoints, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISetExceptionBreakpointsHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetExceptionBreakpointsHandler : ISetExceptionBreakpointsHandler - { - public abstract Task Handle( - SetExceptionBreakpointsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISetExpressionHandler.cs b/src/Dap.Protocol/Requests/ISetExpressionHandler.cs deleted file mode 100644 index 680eae018..000000000 --- a/src/Dap.Protocol/Requests/ISetExpressionHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetExpression, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISetExpressionHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetExpressionHandler : ISetExpressionHandler - { - public abstract Task Handle( - SetExpressionArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISetFunctionBreakpointsHandler.cs b/src/Dap.Protocol/Requests/ISetFunctionBreakpointsHandler.cs deleted file mode 100644 index f369ecd2f..000000000 --- a/src/Dap.Protocol/Requests/ISetFunctionBreakpointsHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetFunctionBreakpoints, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface - ISetFunctionBreakpointsHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetFunctionBreakpointsHandler : ISetFunctionBreakpointsHandler - { - public abstract Task Handle( - SetFunctionBreakpointsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISetInstructionBreakpointsHandler.cs b/src/Dap.Protocol/Requests/ISetInstructionBreakpointsHandler.cs deleted file mode 100644 index dcf6b8fdf..000000000 --- a/src/Dap.Protocol/Requests/ISetInstructionBreakpointsHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetInstructionBreakpoints, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISetInstructionBreakpointsHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetInstructionBreakpointsHandlerBase : ISetInstructionBreakpointsHandler - { - public abstract Task Handle(SetInstructionBreakpointsArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ISetVariableHandler.cs b/src/Dap.Protocol/Requests/ISetVariableHandler.cs deleted file mode 100644 index 6614f4292..000000000 --- a/src/Dap.Protocol/Requests/ISetVariableHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.SetVariable, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISetVariableHandler : IJsonRpcRequestHandler - { - } - - public abstract class SetVariableHandler : ISetVariableHandler - { - public abstract Task Handle( - SetVariableArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/ISourceHandler.cs b/src/Dap.Protocol/Requests/ISourceHandler.cs deleted file mode 100644 index fd657068a..000000000 --- a/src/Dap.Protocol/Requests/ISourceHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Source, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ISourceHandler : IJsonRpcRequestHandler - { - } - - public abstract class SourceHandler : ISourceHandler - { - public abstract Task Handle(SourceArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IStackTraceHandler.cs b/src/Dap.Protocol/Requests/IStackTraceHandler.cs deleted file mode 100644 index 28b0fb03f..000000000 --- a/src/Dap.Protocol/Requests/IStackTraceHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.StackTrace, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStackTraceHandler : IJsonRpcRequestHandler - { - } - - public abstract class StackTraceHandler : IStackTraceHandler - { - public abstract Task Handle( - StackTraceArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IStepBackHandler.cs b/src/Dap.Protocol/Requests/IStepBackHandler.cs deleted file mode 100644 index 0210d70ad..000000000 --- a/src/Dap.Protocol/Requests/IStepBackHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.StepBack, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStepBackHandler : IJsonRpcRequestHandler - { - } - - public abstract class StepBackHandler : IStepBackHandler - { - public abstract Task Handle(StepBackArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IStepInHandler.cs b/src/Dap.Protocol/Requests/IStepInHandler.cs deleted file mode 100644 index 6f4c1fe08..000000000 --- a/src/Dap.Protocol/Requests/IStepInHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.StepIn, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStepInHandler : IJsonRpcRequestHandler - { - } - - public abstract class StepInHandler : IStepInHandler - { - public abstract Task Handle(StepInArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IStepInTargetsHandler.cs b/src/Dap.Protocol/Requests/IStepInTargetsHandler.cs deleted file mode 100644 index bc0d67888..000000000 --- a/src/Dap.Protocol/Requests/IStepInTargetsHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.StepInTargets, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStepInTargetsHandler : IJsonRpcRequestHandler - { - } - - public abstract class StepInTargetsHandler : IStepInTargetsHandler - { - public abstract Task Handle( - StepInTargetsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IStepOutHandler.cs b/src/Dap.Protocol/Requests/IStepOutHandler.cs deleted file mode 100644 index 252c40a2a..000000000 --- a/src/Dap.Protocol/Requests/IStepOutHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.StepOut, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IStepOutHandler : IJsonRpcRequestHandler - { - } - - public abstract class StepOutHandler : IStepOutHandler - { - public abstract Task Handle(StepOutArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ITerminateHandler.cs b/src/Dap.Protocol/Requests/ITerminateHandler.cs deleted file mode 100644 index 100c5ad9e..000000000 --- a/src/Dap.Protocol/Requests/ITerminateHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Terminate, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ITerminateHandler : IJsonRpcRequestHandler - { - } - - public abstract class TerminateHandler : ITerminateHandler - { - public abstract Task Handle(TerminateArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/ITerminateThreadsHandler.cs b/src/Dap.Protocol/Requests/ITerminateThreadsHandler.cs deleted file mode 100644 index eb46155ef..000000000 --- a/src/Dap.Protocol/Requests/ITerminateThreadsHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.TerminateThreads, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface ITerminateThreadsHandler : IJsonRpcRequestHandler - { - } - - public abstract class TerminateThreadsHandler : ITerminateThreadsHandler - { - public abstract Task Handle( - TerminateThreadsArguments request, - CancellationToken cancellationToken - ); - } -} diff --git a/src/Dap.Protocol/Requests/IThreadsHandler.cs b/src/Dap.Protocol/Requests/IThreadsHandler.cs deleted file mode 100644 index 297a3be16..000000000 --- a/src/Dap.Protocol/Requests/IThreadsHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Threads, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IThreadsHandler : IJsonRpcRequestHandler - { - } - - public abstract class ThreadsHandler : IThreadsHandler - { - public abstract Task Handle(ThreadsArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/IVariablesHandler.cs b/src/Dap.Protocol/Requests/IVariablesHandler.cs deleted file mode 100644 index 98b1ae590..000000000 --- a/src/Dap.Protocol/Requests/IVariablesHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Parallel] - [Method(RequestNames.Variables, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods] - public interface IVariablesHandler : IJsonRpcRequestHandler - { - } - - public abstract class VariablesHandler : IVariablesHandler - { - public abstract Task Handle(VariablesArguments request, CancellationToken cancellationToken); - } -} diff --git a/src/Dap.Protocol/Requests/InitializeRequestArguments.cs b/src/Dap.Protocol/Requests/InitializeRequestArguments.cs deleted file mode 100644 index bd83f5bca..000000000 --- a/src/Dap.Protocol/Requests/InitializeRequestArguments.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Initialize, Direction.ClientToServer)] - public class InitializeRequestArguments : IRequest, IInitializeRequestArguments - { - /// - /// The ID of the(frontend) client using this adapter. - /// - - [Optional] - public string? ClientId { get; set; } - - /// - /// The human readable name of the(frontend) client using this adapter. - /// - - [Optional] - public string? ClientName { get; set; } - - /// - /// The ID of the debug adapter. - /// - public string AdapterId { get; set; } = null!; - - /// - /// The ISO-639 locale of the(frontend) client using this adapter, e.g.en-US or de-CH. - /// - - [Optional] - public string? Locale { get; set; } - - /// - /// If true all line numbers are 1-based(default). - /// - [Optional] - public bool LinesStartAt1 { get; set; } - - /// - /// If true all column numbers are 1-based(default). - /// - [Optional] - public bool ColumnsStartAt1 { get; set; } - - /// - /// Determines in what format paths are specified.The default is 'path', which is the native format. - /// Values: 'path', 'uri', etc. - /// - [Optional] - public string? PathFormat { get; set; } - - /// - /// Client supports the optional type attribute for variables. - /// - [Optional] - public bool SupportsVariableType { get; set; } - - /// - /// Client supports the paging of variables. - /// - [Optional] - public bool SupportsVariablePaging { get; set; } - - /// - /// Client supports the runInTerminal request. - /// - [Optional] - public bool SupportsRunInTerminalRequest { get; set; } - - /// - /// Client supports memory references. - /// - [Optional] - public bool SupportsMemoryReferences { get; set; } - - /// - /// Client supports progress reporting. - /// - [Optional] - public bool SupportsProgressReporting { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/InitializeResponse.cs b/src/Dap.Protocol/Requests/InitializeResponse.cs deleted file mode 100644 index 0606368e8..000000000 --- a/src/Dap.Protocol/Requests/InitializeResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class InitializeResponse : Capabilities - { - } -} diff --git a/src/Dap.Protocol/Requests/LaunchRequestArguments.cs b/src/Dap.Protocol/Requests/LaunchRequestArguments.cs deleted file mode 100644 index 67f3831a2..000000000 --- a/src/Dap.Protocol/Requests/LaunchRequestArguments.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using MediatR; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Launch, Direction.ClientToServer)] - public class LaunchRequestArguments : IRequest - { - /// - /// If noDebug is true the launch request should launch the program without enabling debugging. - /// - [Optional] - public bool NoDebug { get; set; } - - /// - /// Optional data from the previous, restarted session. - /// The data is sent as the 'restart' attribute of the 'terminated' event. - /// The client should leave the data intact. - /// - [Optional] - [JsonProperty(PropertyName = "__restart")] - public JToken? Restart { get; set; } - - [JsonExtensionData] public IDictionary ExtensionData { get; set; } = new Dictionary(); - } -} diff --git a/src/Dap.Protocol/Requests/LaunchResponse.cs b/src/Dap.Protocol/Requests/LaunchResponse.cs deleted file mode 100644 index d9440bc23..000000000 --- a/src/Dap.Protocol/Requests/LaunchResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class LaunchResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/LoadedSourcesArguments.cs b/src/Dap.Protocol/Requests/LoadedSourcesArguments.cs deleted file mode 100644 index bdbde448a..000000000 --- a/src/Dap.Protocol/Requests/LoadedSourcesArguments.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.LoadedSources, Direction.ClientToServer)] - public class LoadedSourcesArguments : IRequest - { - } -} diff --git a/src/Dap.Protocol/Requests/LoadedSourcesResponse.cs b/src/Dap.Protocol/Requests/LoadedSourcesResponse.cs deleted file mode 100644 index a047ee61c..000000000 --- a/src/Dap.Protocol/Requests/LoadedSourcesResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class LoadedSourcesResponse - { - /// - /// Set of loaded sources. - /// - public Container Sources { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/ModulesArguments.cs b/src/Dap.Protocol/Requests/ModulesArguments.cs deleted file mode 100644 index f33bd9eda..000000000 --- a/src/Dap.Protocol/Requests/ModulesArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Modules, Direction.ClientToServer)] - public class ModulesArguments : IRequest - { - /// - /// The index of the first module to return; if omitted modules start at 0. - /// - [Optional] - public long? StartModule { get; set; } - - /// - /// The number of modules to return. If moduleCount is not specified or 0, all modules are returned. - /// - [Optional] - public long? ModuleCount { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ModulesResponse.cs b/src/Dap.Protocol/Requests/ModulesResponse.cs deleted file mode 100644 index d20cfb3ed..000000000 --- a/src/Dap.Protocol/Requests/ModulesResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ModulesResponse - { - /// - /// All modules or range of modules. - /// - public Container Modules { get; set; } = null!; - - /// - /// The total number of modules available. - /// - [Optional] - public long? TotalModules { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/NextArguments.cs b/src/Dap.Protocol/Requests/NextArguments.cs deleted file mode 100644 index a3945fbff..000000000 --- a/src/Dap.Protocol/Requests/NextArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Next, Direction.ClientToServer)] - public class NextArguments : IRequest - { - /// - /// Execute 'next' for this thread. - /// - public long ThreadId { get; set; } - - /// - /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. - /// - [Optional] - public SteppingGranularity Granularity { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/NextResponse.cs b/src/Dap.Protocol/Requests/NextResponse.cs deleted file mode 100644 index 7596c3f22..000000000 --- a/src/Dap.Protocol/Requests/NextResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class NextResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/PauseArguments.cs b/src/Dap.Protocol/Requests/PauseArguments.cs deleted file mode 100644 index 2501fbebd..000000000 --- a/src/Dap.Protocol/Requests/PauseArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Pause, Direction.ClientToServer)] - public class PauseArguments : IRequest - { - /// - /// Pause execution for this thread. - /// - public long ThreadId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/PauseResponse.cs b/src/Dap.Protocol/Requests/PauseResponse.cs deleted file mode 100644 index 8a270ea42..000000000 --- a/src/Dap.Protocol/Requests/PauseResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class PauseResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/ReadMemoryArguments.cs b/src/Dap.Protocol/Requests/ReadMemoryArguments.cs deleted file mode 100644 index fbef64d34..000000000 --- a/src/Dap.Protocol/Requests/ReadMemoryArguments.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.ReadMemory, Direction.ClientToServer)] - public class ReadMemoryArguments : IRequest - { - /// - /// Memory reference to the base location from which data should be read. - /// - public string MemoryReference { get; set; } = null!; - - /// - /// Optional offset(in bytes) to be applied to the reference location before reading data.Can be negative. - /// - - [Optional] - public long? Offset { get; set; } - - /// - /// Number of bytes to read at the specified location and offset. - /// - public long Count { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ReadMemoryResponse.cs b/src/Dap.Protocol/Requests/ReadMemoryResponse.cs deleted file mode 100644 index 1d3198073..000000000 --- a/src/Dap.Protocol/Requests/ReadMemoryResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ReadMemoryResponse - { - /// - /// The address of the first byte of data returned.Treated as a hex value if prefixed with '0x', or as a decimal value otherwise. - /// - public string Address { get; set; } = null!; - - /// - /// The number of unreadable bytes encountered after the last successfully read byte. This can be used to determine the number of bytes that must be skipped before a subsequent - /// 'readMemory' request will succeed. - /// - [Optional] - public long? UnreadableBytes { get; set; } - - /// - /// The bytes read from memory, encoded using base64. - /// - [Optional] - public string? Data { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/RestartArguments.cs b/src/Dap.Protocol/Requests/RestartArguments.cs deleted file mode 100644 index bb5f67042..000000000 --- a/src/Dap.Protocol/Requests/RestartArguments.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Restart, Direction.ClientToServer)] - public class RestartArguments : IRequest - { - } -} diff --git a/src/Dap.Protocol/Requests/RestartFrameArguments.cs b/src/Dap.Protocol/Requests/RestartFrameArguments.cs deleted file mode 100644 index 58c181677..000000000 --- a/src/Dap.Protocol/Requests/RestartFrameArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.RestartFrame, Direction.ClientToServer)] - public class RestartFrameArguments : IRequest - { - /// - /// Restart this stackframe. - /// - public long FrameId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/RestartFrameResponse.cs b/src/Dap.Protocol/Requests/RestartFrameResponse.cs deleted file mode 100644 index 45bbe22b8..000000000 --- a/src/Dap.Protocol/Requests/RestartFrameResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class RestartFrameResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/RestartResponse.cs b/src/Dap.Protocol/Requests/RestartResponse.cs deleted file mode 100644 index 5ff989df7..000000000 --- a/src/Dap.Protocol/Requests/RestartResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class RestartResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/ReverseContinueArguments.cs b/src/Dap.Protocol/Requests/ReverseContinueArguments.cs deleted file mode 100644 index 5b08987ea..000000000 --- a/src/Dap.Protocol/Requests/ReverseContinueArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.ReverseContinue, Direction.ClientToServer)] - public class ReverseContinueArguments : IRequest - { - /// - /// Execute 'reverseContinue' for this thread. - /// - public long ThreadId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ReverseContinueResponse.cs b/src/Dap.Protocol/Requests/ReverseContinueResponse.cs deleted file mode 100644 index 575b7df83..000000000 --- a/src/Dap.Protocol/Requests/ReverseContinueResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ReverseContinueResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/RunInTerminalArguments.cs b/src/Dap.Protocol/Requests/RunInTerminalArguments.cs deleted file mode 100644 index a85a5ad0b..000000000 --- a/src/Dap.Protocol/Requests/RunInTerminalArguments.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.RunInTerminal, Direction.ServerToClient)] - public class RunInTerminalArguments : IRequest - { - /// - /// What kind of terminal to launch. - /// - [Optional] - public RunInTerminalArgumentsKind? Kind { get; set; } - - /// - /// Optional title of the terminal. - /// - [Optional] - public string? Title { get; set; } - - /// - /// Working directory of the command. - /// - public string Cwd { get; set; } = null!; - - /// - /// List of arguments.The first argument is the command to run. - /// - public Container Args { get; set; } = null!; - - /// - /// Environment key-value pairs that are added to or removed from the default environment. - /// - [Optional] - public IDictionary? Env { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/RunInTerminalArgumentsKind.cs b/src/Dap.Protocol/Requests/RunInTerminalArgumentsKind.cs deleted file mode 100644 index 0c9261d14..000000000 --- a/src/Dap.Protocol/Requests/RunInTerminalArgumentsKind.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum RunInTerminalArgumentsKind - { - Integrated, - External - } -} diff --git a/src/Dap.Protocol/Requests/RunInTerminalResponse.cs b/src/Dap.Protocol/Requests/RunInTerminalResponse.cs deleted file mode 100644 index 1abad903b..000000000 --- a/src/Dap.Protocol/Requests/RunInTerminalResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class RunInTerminalResponse - { - /// - /// The process ID. - /// - [Optional] - public long? ProcessId { get; set; } - - /// - /// The process ID of the terminal shell. - /// - [Optional] - public long? ShellProcessId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ScopesArguments.cs b/src/Dap.Protocol/Requests/ScopesArguments.cs deleted file mode 100644 index 4a619febc..000000000 --- a/src/Dap.Protocol/Requests/ScopesArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Scopes, Direction.ClientToServer)] - public class ScopesArguments : IRequest - { - /// - /// Retrieve the scopes for this stackframe. - /// - public long FrameId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/ScopesResponse.cs b/src/Dap.Protocol/Requests/ScopesResponse.cs deleted file mode 100644 index d1e534742..000000000 --- a/src/Dap.Protocol/Requests/ScopesResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ScopesResponse - { - /// - /// The scopes of the stackframe.If the array has length zero, there are no scopes available. - /// - public Container Scopes { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetBreakpointsArguments.cs b/src/Dap.Protocol/Requests/SetBreakpointsArguments.cs deleted file mode 100644 index 1a0fca177..000000000 --- a/src/Dap.Protocol/Requests/SetBreakpointsArguments.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetBreakpoints, Direction.ClientToServer)] - public class SetBreakpointsArguments : IRequest - { - /// - /// The source location of the breakpoints; either 'source.path' or 'source.reference' must be specified. - /// - public Source Source { get; set; } = null!; - - /// - /// The code locations of the breakpoints. - /// - [Optional] - public Container? Breakpoints { get; set; } - - /// - /// Deprecated: The code locations of the breakpoints. - /// - [Obsolete("Deprecated")] - [Optional] - public Container? Lines { get; set; } - - /// - /// A value of true indicates that the underlying source has been modified which results in new breakpoint locations. - /// - [Optional] - public bool SourceModified { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SetBreakpointsResponse.cs b/src/Dap.Protocol/Requests/SetBreakpointsResponse.cs deleted file mode 100644 index f3179a696..000000000 --- a/src/Dap.Protocol/Requests/SetBreakpointsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetBreakpointsResponse - { - /// - /// Information about the breakpoints.The array elements are in the same order as the elements of the 'breakpoints' (or the deprecated 'lines') array in the arguments. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetDataBreakpointsArguments.cs b/src/Dap.Protocol/Requests/SetDataBreakpointsArguments.cs deleted file mode 100644 index 5eb3e4c45..000000000 --- a/src/Dap.Protocol/Requests/SetDataBreakpointsArguments.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetDataBreakpoints, Direction.ClientToServer)] - public class SetDataBreakpointsArguments : IRequest - { - /// - /// The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetDataBreakpointsResponse.cs b/src/Dap.Protocol/Requests/SetDataBreakpointsResponse.cs deleted file mode 100644 index cbeb97da8..000000000 --- a/src/Dap.Protocol/Requests/SetDataBreakpointsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetDataBreakpointsResponse - { - /// - /// Information about the data breakpoints.The array elements correspond to the elements of the input argument 'breakpoints' array. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetExceptionBreakpointsArguments.cs b/src/Dap.Protocol/Requests/SetExceptionBreakpointsArguments.cs deleted file mode 100644 index 5c03cc29b..000000000 --- a/src/Dap.Protocol/Requests/SetExceptionBreakpointsArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetExceptionBreakpoints, Direction.ClientToServer)] - public class SetExceptionBreakpointsArguments : IRequest - { - /// - /// IDs of checked exception options.The set of IDs is returned via the 'exceptionBreakpointFilters' capability. - /// - public Container Filters { get; set; } = null!; - - /// - /// Configuration options for selected exceptions. - /// - [Optional] - public Container? ExceptionOptions { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SetExceptionBreakpointsResponse.cs b/src/Dap.Protocol/Requests/SetExceptionBreakpointsResponse.cs deleted file mode 100644 index 8aa1b870e..000000000 --- a/src/Dap.Protocol/Requests/SetExceptionBreakpointsResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetExceptionBreakpointsResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/SetExpressionArguments.cs b/src/Dap.Protocol/Requests/SetExpressionArguments.cs deleted file mode 100644 index 70547c20f..000000000 --- a/src/Dap.Protocol/Requests/SetExpressionArguments.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetExpression, Direction.ClientToServer)] - public class SetExpressionArguments : IRequest - { - /// - /// The l-value expression to assign to. - /// - public string Expression { get; set; } = null!; - - /// - /// The value expression to assign to the l-value expression. - /// - public string Value { get; set; } = null!; - - /// - /// Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope. - /// - [Optional] - public long? FrameId { get; set; } - - /// - /// Specifies how the resulting value should be formatted. - /// - [Optional] - public ValueFormat? Format { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SetExpressionResponse.cs b/src/Dap.Protocol/Requests/SetExpressionResponse.cs deleted file mode 100644 index 1d0b7856e..000000000 --- a/src/Dap.Protocol/Requests/SetExpressionResponse.cs +++ /dev/null @@ -1,45 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetExpressionResponse - { - /// - /// The new value of the expression. - /// - public string Value { get; set; } = null!; - - /// - /// The optional type of the value. - /// - [Optional] - public string? Type { get; set; } - - /// - /// Properties of a value that can be used to determine how to render the result in the UI. - /// - [Optional] - public VariablePresentationHint? PresentationHint { get; set; } - - /// - /// If variablesReference is > 0, the value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - /// - [Optional] - public long? VariablesReference { get; set; } - - /// - /// The number of named child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? NamedVariables { get; set; } - - /// - /// The number of indexed child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? IndexedVariables { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SetFunctionBreakpointsArguments.cs b/src/Dap.Protocol/Requests/SetFunctionBreakpointsArguments.cs deleted file mode 100644 index 9ab70db28..000000000 --- a/src/Dap.Protocol/Requests/SetFunctionBreakpointsArguments.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetFunctionBreakpoints, Direction.ClientToServer)] - public class SetFunctionBreakpointsArguments : IRequest - { - /// - /// The function names of the breakpoints. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetFunctionBreakpointsResponse.cs b/src/Dap.Protocol/Requests/SetFunctionBreakpointsResponse.cs deleted file mode 100644 index 45359f57d..000000000 --- a/src/Dap.Protocol/Requests/SetFunctionBreakpointsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetFunctionBreakpointsResponse - { - /// - /// Information about the breakpoints.The array elements correspond to the elements of the 'breakpoints' array. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetInstructionBreakpointsArguments.cs b/src/Dap.Protocol/Requests/SetInstructionBreakpointsArguments.cs deleted file mode 100644 index 4cf711e47..000000000 --- a/src/Dap.Protocol/Requests/SetInstructionBreakpointsArguments.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetInstructionBreakpoints, Direction.ClientToServer)] - public class SetInstructionBreakpointsArguments : IRequest - { - /// - /// The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetInstructionBreakpointsResponse.cs b/src/Dap.Protocol/Requests/SetInstructionBreakpointsResponse.cs deleted file mode 100644 index a04bcd4ac..000000000 --- a/src/Dap.Protocol/Requests/SetInstructionBreakpointsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetInstructionBreakpointsResponse - { - /// - /// Information about the data breakpoints.The array elements correspond to the elements of the input argument 'breakpoints' array. - /// - public Container Breakpoints { get; set; } = null!; - } -} diff --git a/src/Dap.Protocol/Requests/SetVariableArguments.cs b/src/Dap.Protocol/Requests/SetVariableArguments.cs deleted file mode 100644 index 85903f22a..000000000 --- a/src/Dap.Protocol/Requests/SetVariableArguments.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.SetVariable, Direction.ClientToServer)] - public class SetVariableArguments : IRequest - { - /// - /// The reference of the variable container. - /// - public long VariablesReference { get; set; } - - /// - /// The name of the variable in the container. - /// - public string Name { get; set; } = null!; - - /// - /// The value of the variable. - /// - public string Value { get; set; } = null!; - - /// - /// Specifies details on how to format the response value. - /// - [Optional] - public ValueFormat? Format { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SetVariableResponse.cs b/src/Dap.Protocol/Requests/SetVariableResponse.cs deleted file mode 100644 index da8847977..000000000 --- a/src/Dap.Protocol/Requests/SetVariableResponse.cs +++ /dev/null @@ -1,38 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SetVariableResponse - { - /// - /// The new value of the variable. - /// - public string Value { get; set; } = null!; - - /// - /// The type of the new value.Typically shown in the UI when hovering over the value. - /// - [Optional] - public string? Type { get; set; } - - /// - /// If variablesReference is > 0, the new value is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. - /// - [Optional] - public long? VariablesReference { get; set; } - - /// - /// The number of named child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? NamedVariables { get; set; } - - /// - /// The number of indexed child variables. - /// The client can use this optional information to present the variables in a paged UI and fetch them in chunks. - /// - [Optional] - public long? IndexedVariables { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SourceArguments.cs b/src/Dap.Protocol/Requests/SourceArguments.cs deleted file mode 100644 index ddce74c44..000000000 --- a/src/Dap.Protocol/Requests/SourceArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Source, Direction.ClientToServer)] - public class SourceArguments : IRequest - { - /// - /// Specifies the source content to load.Either source.path or source.sourceReference must be specified. - /// - [Optional] - public Source? Source { get; set; } - - /// - /// The reference to the source.This is the same as source.sourceReference.This is provided for backward compatibility since old backends do not understand the 'source' attribute. - /// - public long SourceReference { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/SourceResponse.cs b/src/Dap.Protocol/Requests/SourceResponse.cs deleted file mode 100644 index 3149938e2..000000000 --- a/src/Dap.Protocol/Requests/SourceResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class SourceResponse - { - /// - /// Content of the source reference. - /// - public string Content { get; set; } = null!; - - /// - /// Optional content type(mime type) of the source. - /// - [Optional] - public string? MimeType { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StackTraceArguments.cs b/src/Dap.Protocol/Requests/StackTraceArguments.cs deleted file mode 100644 index e5fabf4ba..000000000 --- a/src/Dap.Protocol/Requests/StackTraceArguments.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.StackTrace, Direction.ClientToServer)] - public class StackTraceArguments : IRequest - { - /// - /// Retrieve the stacktrace for this thread. - /// - public long ThreadId { get; set; } - - /// - /// The index of the first frame to return; if omitted frames start at 0. - /// - [Optional] - public long? StartFrame { get; set; } - - /// - /// The maximum number of frames to return. If levels is not specified or 0, all frames are returned. - /// - [Optional] - public long? Levels { get; set; } - - /// - /// Specifies details on how to format the stack frames. - /// - [Optional] - public StackFrameFormat? Format { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StackTraceResponse.cs b/src/Dap.Protocol/Requests/StackTraceResponse.cs deleted file mode 100644 index 78e45e046..000000000 --- a/src/Dap.Protocol/Requests/StackTraceResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class StackTraceResponse - { - /// - /// The frames of the stackframe.If the array has length zero, there are no stackframes available. - /// This means that there is no location information available. - /// - public Container? StackFrames { get; set; } - - /// - /// The total number of frames available. - /// - [Optional] - public long? TotalFrames { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepBackArguments.cs b/src/Dap.Protocol/Requests/StepBackArguments.cs deleted file mode 100644 index 9172affde..000000000 --- a/src/Dap.Protocol/Requests/StepBackArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.StepBack, Direction.ClientToServer)] - public class StepBackArguments : IRequest - { - /// - /// Execute 'stepBack' for this thread. - /// - public long ThreadId { get; set; } - - /// - /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. - /// - [Optional] - public SteppingGranularity? Granularity { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepBackResponse.cs b/src/Dap.Protocol/Requests/StepBackResponse.cs deleted file mode 100644 index d41731d19..000000000 --- a/src/Dap.Protocol/Requests/StepBackResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class StepBackResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/StepInArguments.cs b/src/Dap.Protocol/Requests/StepInArguments.cs deleted file mode 100644 index 30223f3f3..000000000 --- a/src/Dap.Protocol/Requests/StepInArguments.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.StepIn, Direction.ClientToServer)] - public class StepInArguments : IRequest - { - /// - /// Execute 'stepIn' for this thread. - /// - public long ThreadId { get; set; } - - /// - /// Optional id of the target to step into. - /// - [Optional] - public long? TargetId { get; set; } - - /// - /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. - /// - [Optional] - public SteppingGranularity? Granularity { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepInResponse.cs b/src/Dap.Protocol/Requests/StepInResponse.cs deleted file mode 100644 index d062eb23b..000000000 --- a/src/Dap.Protocol/Requests/StepInResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class StepInResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/StepInTargetsArguments.cs b/src/Dap.Protocol/Requests/StepInTargetsArguments.cs deleted file mode 100644 index 85f9d46cc..000000000 --- a/src/Dap.Protocol/Requests/StepInTargetsArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.StepInTargets, Direction.ClientToServer)] - public class StepInTargetsArguments : IRequest - { - /// - /// The stack frame for which to retrieve the possible stepIn targets. - /// - public long FrameId { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepInTargetsResponse.cs b/src/Dap.Protocol/Requests/StepInTargetsResponse.cs deleted file mode 100644 index dbcc0da2a..000000000 --- a/src/Dap.Protocol/Requests/StepInTargetsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class StepInTargetsResponse - { - /// - /// The possible stepIn targets of the specified source location. - /// - public Container? Targets { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepOutArguments.cs b/src/Dap.Protocol/Requests/StepOutArguments.cs deleted file mode 100644 index f88ead520..000000000 --- a/src/Dap.Protocol/Requests/StepOutArguments.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.StepOut, Direction.ClientToServer)] - public class StepOutArguments : IRequest - { - /// - /// Execute 'stepOut' for this thread. - /// - public long ThreadId { get; set; } - - /// - /// Optional granularity to step. If no granularity is specified, a granularity of 'statement' is assumed. - /// - [Optional] - public SteppingGranularity? Granularity { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/StepOutResponse.cs b/src/Dap.Protocol/Requests/StepOutResponse.cs deleted file mode 100644 index a1b96f2e4..000000000 --- a/src/Dap.Protocol/Requests/StepOutResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class StepOutResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/TerminateArguments.cs b/src/Dap.Protocol/Requests/TerminateArguments.cs deleted file mode 100644 index f6fba14dc..000000000 --- a/src/Dap.Protocol/Requests/TerminateArguments.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Terminate, Direction.ClientToServer)] - public class TerminateArguments : IRequest - { - /// - /// A value of true indicates that this 'terminate' request is part of a restart sequence. - /// - [Optional] - public bool Restart { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/TerminateResponse.cs b/src/Dap.Protocol/Requests/TerminateResponse.cs deleted file mode 100644 index b93134a25..000000000 --- a/src/Dap.Protocol/Requests/TerminateResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class TerminateResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/TerminateThreadsArguments.cs b/src/Dap.Protocol/Requests/TerminateThreadsArguments.cs deleted file mode 100644 index 7056c3f21..000000000 --- a/src/Dap.Protocol/Requests/TerminateThreadsArguments.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.TerminateThreads, Direction.ClientToServer)] - public class TerminateThreadsArguments : IRequest - { - /// - /// Ids of threads to be terminated. - /// - [Optional] - public Container? ThreadIds { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/TerminateThreadsResponse.cs b/src/Dap.Protocol/Requests/TerminateThreadsResponse.cs deleted file mode 100644 index b764253a8..000000000 --- a/src/Dap.Protocol/Requests/TerminateThreadsResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class TerminateThreadsResponse - { - } -} diff --git a/src/Dap.Protocol/Requests/ThreadsArguments.cs b/src/Dap.Protocol/Requests/ThreadsArguments.cs deleted file mode 100644 index 573a369df..000000000 --- a/src/Dap.Protocol/Requests/ThreadsArguments.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Threads, Direction.ClientToServer)] - public class ThreadsArguments : IRequest - { - } -} diff --git a/src/Dap.Protocol/Requests/ThreadsResponse.cs b/src/Dap.Protocol/Requests/ThreadsResponse.cs deleted file mode 100644 index 75683bf23..000000000 --- a/src/Dap.Protocol/Requests/ThreadsResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class ThreadsResponse - { - /// - /// All threads. - /// - public Container? Threads { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/VariablesArguments.cs b/src/Dap.Protocol/Requests/VariablesArguments.cs deleted file mode 100644 index 35c9cb349..000000000 --- a/src/Dap.Protocol/Requests/VariablesArguments.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [Method(RequestNames.Variables, Direction.ClientToServer)] - public class VariablesArguments : IRequest - { - /// - /// The Variable reference. - /// - public long VariablesReference { get; set; } - - /// - /// Optional filter to limit the child variables to either named or indexed.If ommited, both types are fetched. - /// - [Optional] - public VariablesArgumentsFilter? Filter { get; set; } - - /// - /// The index of the first variable to return; if omitted children start at 0. - /// - [Optional] - public long? Start { get; set; } - - /// - /// The number of variables to return. If count is missing or 0, all variables are returned. - /// - [Optional] - public long? Count { get; set; } - - /// - /// Specifies details on how to format the Variable values. - /// - [Optional] - public ValueFormat? Format { get; set; } - } -} diff --git a/src/Dap.Protocol/Requests/VariablesArgumentsFilter.cs b/src/Dap.Protocol/Requests/VariablesArgumentsFilter.cs deleted file mode 100644 index bd96ab3cd..000000000 --- a/src/Dap.Protocol/Requests/VariablesArgumentsFilter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum VariablesArgumentsFilter - { - Indexed, Named - } -} diff --git a/src/Dap.Protocol/Requests/VariablesResponse.cs b/src/Dap.Protocol/Requests/VariablesResponse.cs deleted file mode 100644 index 73a1cbcb0..000000000 --- a/src/Dap.Protocol/Requests/VariablesResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests -{ - public class VariablesResponse - { - /// - /// All(or a range) of variables for the given variable reference. - /// - public Container? Variables { get; set; } - } -} diff --git a/src/JsonRpc.Generators/ActionContextExtensions.cs b/src/JsonRpc.Generators/ActionContextExtensions.cs new file mode 100644 index 000000000..c4e3c7359 --- /dev/null +++ b/src/JsonRpc.Generators/ActionContextExtensions.cs @@ -0,0 +1,23 @@ +using System.Linq; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + static class ActionContextExtensions + { + public static ParameterListSyntax GetRegistryParameterList(this ExtensionMethodContext extensionMethodContext) + { + return SyntaxFactory.ParameterList( + SyntaxFactory.SeparatedList( + new[] { + SyntaxFactory.Parameter(SyntaxFactory.Identifier("registry")) + .WithType(extensionMethodContext.Item) + .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ThisKeyword))) + } + ) + ); + } + } +} diff --git a/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs b/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs new file mode 100644 index 000000000..152ee67c7 --- /dev/null +++ b/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.CommonElements; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + [Generator] + public class AutoImplementParamsGenerator : CachedSourceGenerator + { + protected override void Execute(GeneratorExecutionContext context, SyntaxReceiver syntaxReceiver, AddCacheSource addCacheSource, ReportCacheDiagnostic cacheDiagnostic) + { + foreach (var candidate in syntaxReceiver.Candidates) + { + var members = new List(); + var model = context.Compilation.GetSemanticModel(candidate.SyntaxTree); + var symbol = model.GetDeclaredSymbol(candidate); + if (symbol is null) continue; + + var autoImplementProperties = AutoImplementInterfaces(candidate, symbol).ToArray(); + if (autoImplementProperties is { Length: > 0 }) + { + var extendedParams = candidate + .WithAttributeLists(List()) + .WithMembers(List(autoImplementProperties)) + .WithConstraintClauses(List()) + .WithBaseList(null); + members.Add(extendedParams); + } + + if (members.Count == 0) continue; + + if (!candidate.Modifiers.Any(z => z.IsKind(SyntaxKind.PartialKeyword))) + { + cacheDiagnostic(candidate, static c => Diagnostic.Create(GeneratorDiagnostics.MustBePartial, c.Identifier.GetLocation(), c.Identifier.Text)); + } + + var cu = CompilationUnit( + List(), + List(candidate.SyntaxTree.GetCompilationUnitRoot().Usings), + List(), + SingletonList( + NamespaceDeclaration(ParseName(symbol.ContainingNamespace.ToDisplayString())) + .WithMembers(List(members)) + ) + ) + .AddUsings(UsingDirective(ParseName("OmniSharp.Extensions.LanguageServer.Protocol.Serialization"))) + .WithLeadingTrivia() + .WithTrailingTrivia() + .WithLeadingTrivia(Comment(Preamble.GeneratedByATool), Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true))) + .WithTrailingTrivia(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)), CarriageReturnLineFeed); + + addCacheSource( + $"{candidate.Identifier.Text}{( candidate.Arity > 0 ? candidate.Arity.ToString() : "" )}.cs", + candidate, + cu.NormalizeWhitespace().GetText(Encoding.UTF8) + ); + } + } + + private static IEnumerable AutoImplementInterfaces(ClassDeclarationSyntax syntax, INamedTypeSymbol symbol) + { + if (syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName() is "IWorkDoneProgressParams") == true + && symbol.GetMembers("WorkDoneToken").IsEmpty) + { + yield return PropertyDeclaration(NullableType(IdentifierName("ProgressToken")), Identifier("WorkDoneToken")) + .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("Optional")))))) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithAccessorList(GetSetAccessor); + } + + if (syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName() is "IPartialItemsRequest" or "IPartialItemRequest") == true + && symbol.GetMembers("PartialResultToken").IsEmpty) + { + yield return PropertyDeclaration(NullableType(IdentifierName("ProgressToken")), Identifier("PartialResultToken")) + .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("Optional")))))) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithAccessorList(GetSetAccessor); + } + } + + public AutoImplementParamsGenerator() : base(() => new SyntaxReceiver(Cache)) { } + + public static CacheContainer Cache = new(); + + public class SyntaxReceiver : SyntaxReceiverCache + { + private string _attributes; + public List Candidates { get; } = new(); + + public SyntaxReceiver(CacheContainer cacheContainer) : base(cacheContainer) + { + _attributes = "Method,RegistrationOptions"; + } + + public override string? GetKey(ClassDeclarationSyntax syntax) + { + var hasher = new CacheKeyHasher(); + hasher.Append(syntax.SyntaxTree.FilePath); + hasher.Append(syntax.Identifier.Text); + hasher.Append(syntax.TypeParameterList); + hasher.Append(syntax.AttributeLists); + hasher.Append(syntax.BaseList); + foreach (var item in syntax.Members.OfType().Select(z => z.Identifier.Text)) + { + hasher.Append(item); + } + return hasher; + } + + /// + /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation + /// + public override void OnVisitNode(ClassDeclarationSyntax syntaxNode) + { + // any field with at least one attribute is a candidate for property generation + if (syntaxNode.AttributeLists.ContainsAttribute(_attributes)) + { + Candidates.Add(syntaxNode); + } + } + } + } +} diff --git a/src/JsonRpc.Generators/Cache/AddCacheSource.cs b/src/JsonRpc.Generators/Cache/AddCacheSource.cs new file mode 100644 index 000000000..1d7535413 --- /dev/null +++ b/src/JsonRpc.Generators/Cache/AddCacheSource.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + public delegate void AddCacheSource(string hintName, T syntaxNode, SourceText sourceText) where T : SyntaxNode; + + public delegate void ReportCacheDiagnostic(T syntaxNode, CacheDiagnosticFactory diagnostic) where T : SyntaxNode; + + public delegate Diagnostic CacheDiagnosticFactory(T syntaxNode) where T : SyntaxNode; + + public delegate Location LocationFactory(T syntaxNode) where T : SyntaxNode; +} diff --git a/src/JsonRpc.Generators/Cache/CacheContainer.cs b/src/JsonRpc.Generators/Cache/CacheContainer.cs new file mode 100644 index 000000000..29c0d2ae1 --- /dev/null +++ b/src/JsonRpc.Generators/Cache/CacheContainer.cs @@ -0,0 +1,37 @@ +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using Microsoft.CodeAnalysis; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + public class CacheContainer where T : SyntaxNode + { + private ImmutableDictionary> _sourceTexts; + private ImmutableDictionary>> _cacheDiagnostics; + + public CacheContainer() + { + _sourceTexts = ImmutableDictionary>.Empty; + _cacheDiagnostics = ImmutableDictionary>>.Empty; + } + + public ImmutableDictionary> SourceTexts => _sourceTexts; + public ImmutableDictionary>> Diagnostics => _cacheDiagnostics; + + public void Swap( + ImmutableDictionary.Builder sources)>.Builder foundCache, + ImmutableDictionary>.Builder>.Builder diagnosticFactories + ) + { + Interlocked.Exchange( + ref _sourceTexts, + foundCache.ToImmutableDictionary(z => z.Key, z => z.Value.sources.ToImmutable()) + ); + Interlocked.Exchange( + ref _cacheDiagnostics, + diagnosticFactories.ToImmutableDictionary(z => z.Key, z => z.Value.ToImmutable()) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Cache/CacheKeyHasher.cs b/src/JsonRpc.Generators/Cache/CacheKeyHasher.cs new file mode 100644 index 000000000..c54f5d234 --- /dev/null +++ b/src/JsonRpc.Generators/Cache/CacheKeyHasher.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + class CacheKeyHasher : IDisposable + { + public static bool Cache = true; + private readonly SHA1 _hasher; + + public CacheKeyHasher() + { + _hasher = SHA1.Create(); + } + + public void Append(string textToHash) + { + var inputBuffer = Encoding.UTF8.GetBytes(textToHash); + _hasher.TransformBlock(inputBuffer, 0, inputBuffer.Length, inputBuffer, 0); + } + + public void Append(TypeSyntax? typeSyntax) + { + if (typeSyntax?.GetSyntaxName() is { } a) + { + Append(a); + } + } + + public void Append(TypeParameterListSyntax? typeParameterListSyntax) + { + if (typeParameterListSyntax is null or { Parameters: { Count: 0 } }) return; + foreach (var item in typeParameterListSyntax.Parameters) + { + Append(item.Identifier.Text); + Append(item.AttributeLists); + } + } + + public void Append(BaseListSyntax? baseListSyntax) + { + if (baseListSyntax is null) return; + foreach (var item in baseListSyntax.Types) + { + Append(item.Type); + } + } + + public void Append(SyntaxList attributeList) + { + foreach (var item in attributeList) + { + Append(item); + } + } + + public void Append(SyntaxList items) + where T : MemberDeclarationSyntax + { + if (items is { Count: 0 }) return; + foreach (var item in items.OfType()) + { + Append(item.AttributeLists); + if (item is PropertyDeclarationSyntax p) + { + Append(p.Identifier.Text); + Append(p.Type); + } + } + } + + public void Append(AttributeListSyntax attributeList) + { + if (attributeList is { Attributes: { Count: 0 } }) return; + foreach (var item in attributeList.Attributes) + { + Append(item); + } + } + + public void Append(AttributeSyntax attribute) + { + Append(attribute.Name.GetSyntaxName() ?? string.Empty); + if (attribute.ArgumentList?.Arguments is { Count: > 0 } arguments) + { + foreach (var item in arguments) + { + if (item.NameEquals is { }) + { + Append(item.NameEquals.Name.GetSyntaxName() ?? string.Empty); + } + + Append( + item switch { + { Expression: TypeOfExpressionSyntax tyof } => tyof.Type.GetSyntaxName() is { Length: > 0 } name ? name : string.Empty, + { Expression: LiteralExpressionSyntax { } literal } => literal.Token.Text, + _ => string.Empty + } + ); + } + } + } + + private string ConvertByteArrayToString() + { + _hasher.TransformFinalBlock(Array.Empty(), 0, 0); + var sb = new StringBuilder(); + foreach (var b in _hasher.Hash) + { + sb.Append(b.ToString("X2")); + } + + return sb.ToString(); + } + + public override string ToString() => ConvertByteArrayToString(); + + public static implicit operator string(CacheKeyHasher value) => value.ToString(); + + public void Dispose() => _hasher.Dispose(); + } +} diff --git a/src/JsonRpc.Generators/Cache/CachedSourceGenerator.cs b/src/JsonRpc.Generators/Cache/CachedSourceGenerator.cs new file mode 100644 index 000000000..a35ba832d --- /dev/null +++ b/src/JsonRpc.Generators/Cache/CachedSourceGenerator.cs @@ -0,0 +1,63 @@ +using System; +using Microsoft.CodeAnalysis; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + /// + /// We're not supposed to do this... but in realistic. + /// + public abstract class CachedSourceGenerator : ISourceGenerator + where T : ISyntaxReceiver, IReceiverCache + where TSyntax : SyntaxNode + { + private readonly Func _syntaxReceiverFactory; + + public CachedSourceGenerator(Func syntaxReceiverFactory) + { + _syntaxReceiverFactory = syntaxReceiverFactory; + } + + public void Initialize(GeneratorInitializationContext context) + { + context.RegisterForSyntaxNotifications(() => _syntaxReceiverFactory()); + } + + public void Execute(GeneratorExecutionContext context) + { + if (!( context.SyntaxReceiver is T syntaxReceiver )) return; + + syntaxReceiver.Start(context); + Execute( + context, syntaxReceiver, + (name, node, text) => { + context.AddSource(name, text); + + if (CacheKeyHasher.Cache) + { + syntaxReceiver.AddCacheSource(name, node, text); + } + }, + (node, diagnostic) => { + context.ReportDiagnostic(diagnostic(node)); + + if (CacheKeyHasher.Cache) + { + syntaxReceiver.ReportCacheDiagnostic(node, diagnostic); + } + } + ); + foreach (var item in syntaxReceiver.CachedSources) + { + context.AddSource(item.Name, item.SourceText); + } + foreach (var item in syntaxReceiver.CachedDiagnostics) + { + context.ReportDiagnostic(item); + } + + syntaxReceiver.Finish(context); + } + + protected abstract void Execute(GeneratorExecutionContext context, T syntaxReceiver, AddCacheSource addCacheSource, ReportCacheDiagnostic cacheDiagnostic); + } +} diff --git a/src/JsonRpc.Generators/Cache/IReceiverCache.cs b/src/JsonRpc.Generators/Cache/IReceiverCache.cs new file mode 100644 index 000000000..d1e72827e --- /dev/null +++ b/src/JsonRpc.Generators/Cache/IReceiverCache.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + public interface IReceiverCache + where T : SyntaxNode + { + string? GetKey(T syntax); + void Start(GeneratorExecutionContext context); + void Finish(GeneratorExecutionContext context); + IEnumerable CachedSources { get; } + IEnumerable CachedDiagnostics { get; } + void AddCacheSource(string hintName, T syntaxNode, SourceText sourceText); + void ReportCacheDiagnostic(T syntaxNode, CacheDiagnosticFactory diagnostic); + } +} diff --git a/src/JsonRpc.Generators/Cache/SourceTextCache.cs b/src/JsonRpc.Generators/Cache/SourceTextCache.cs new file mode 100644 index 000000000..f0f2e9ac4 --- /dev/null +++ b/src/JsonRpc.Generators/Cache/SourceTextCache.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + public record SourceTextCache(string Name, SourceText SourceText); + public record DiagnosticCache(ImmutableArray> Diagnostics) where T : SyntaxNode; +} diff --git a/src/JsonRpc.Generators/Cache/SyntaxReceiverCache.cs b/src/JsonRpc.Generators/Cache/SyntaxReceiverCache.cs new file mode 100644 index 000000000..7b3118f55 --- /dev/null +++ b/src/JsonRpc.Generators/Cache/SyntaxReceiverCache.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Cache +{ + public abstract class SyntaxReceiverCache : IReceiverCache, ISyntaxReceiver + where T : SyntaxNode + { + private readonly CacheContainer _cache; + private readonly ImmutableDictionary.Builder sources)>.Builder _foundSourceTexts; + private readonly ImmutableDictionary>.Builder>.Builder _foundDiagnosticFactories; + private readonly List _cachedSources = new(); + private readonly List _cachedDiagnostics = new(); + + protected SyntaxReceiverCache(CacheContainer cache) + { + _cache = cache; + _foundSourceTexts = ImmutableDictionary.Builder sources)>.Empty.ToBuilder(); + _foundDiagnosticFactories = ImmutableDictionary>.Builder>.Empty.ToBuilder(); + } + + public abstract string? GetKey(T syntax); + + public void Start(GeneratorExecutionContext context) + { + // TODO: Check if options disable cache + try + { + // check stuff + _cache.Swap(_foundSourceTexts, _foundDiagnosticFactories); + } + catch + { + _cachedSources.Clear(); + _cachedDiagnostics.Clear(); + foreach (var found in _foundSourceTexts.Values) + { + OnVisitNode(found.Item1); + } + } + } + + public void Finish(GeneratorExecutionContext context) + { + // TODO: Check if options disable cache + try + { + // check stuff + _cache.Swap(_foundSourceTexts, _foundDiagnosticFactories); + } + catch + { + _cache.Swap( + ImmutableDictionary.Builder sources)>.Empty.ToBuilder(), + ImmutableDictionary>.Builder>.Empty.ToBuilder() + ); + } + } + + public IEnumerable CachedSources => _cachedSources; + public IEnumerable CachedDiagnostics => _cachedDiagnostics; + + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + if (syntaxNode is not T v) return; + if (GetKey(v) is { } key) + { + if (_cache.SourceTexts.TryGetValue(key, out var cacheValue)) + { + _foundSourceTexts.Add(key, ( v, cacheValue.ToBuilder() )); + _cachedSources.AddRange(cacheValue); + } + + if (_cache.Diagnostics.TryGetValue(key, out var diagnostics)) + { + _foundDiagnosticFactories.Add(key, diagnostics.ToBuilder()); + _cachedDiagnostics.AddRange(diagnostics.Select(f => f(v))); + return; + } + + if (_foundSourceTexts.ContainsKey(key)) return; + } + + OnVisitNode(v); + } + + public void AddCacheSource(string hintName, T syntaxNode, SourceText sourceText) + { + if (GetKey(syntaxNode) is not { } key) return; + if (!_foundSourceTexts.TryGetValue(key, out var data)) + { + var array = ImmutableArray.Create(new SourceTextCache(hintName, sourceText)).ToBuilder(); + _foundSourceTexts.Add(key, ( syntaxNode, array )); + } + else + { + data.sources.Add(new SourceTextCache(hintName, sourceText)); + } + } + + public void ReportCacheDiagnostic(T syntaxNode, CacheDiagnosticFactory diagnostic) + { + if (GetKey(syntaxNode) is not { } key) return; + if (!_foundDiagnosticFactories.TryGetValue(key, out var array)) + { + array = ImmutableArray.Create(diagnostic).ToBuilder(); + _foundDiagnosticFactories.Add(key, array); + } + else + { + array.Add(diagnostic); + } + } + + public abstract void OnVisitNode(T syntaxNode); + } +} diff --git a/src/JsonRpc.Generators/Contexts/DapAttributes.cs b/src/JsonRpc.Generators/Contexts/DapAttributes.cs new file mode 100644 index 000000000..eb12f9775 --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/DapAttributes.cs @@ -0,0 +1,20 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record DapAttributes() + { + public static DapAttributes? Parse( + GeneratorExecutionContext context, + AddCacheSource addCacheSource, + ReportCacheDiagnostic cacheDiagnostic, + TypeDeclarationSyntax syntax, + INamedTypeSymbol symbol + ) + { + return null; + } + } +} diff --git a/src/JsonRpc.Generators/Contexts/ExtensionMethodContext.cs b/src/JsonRpc.Generators/Contexts/ExtensionMethodContext.cs new file mode 100644 index 000000000..3dc33a5df --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/ExtensionMethodContext.cs @@ -0,0 +1,19 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record ExtensionMethodContext( + AttributeData AttributeData, + TypeDeclarationSyntax TypeDeclaration, + INamedTypeSymbol TypeSymbol, + TypeSyntax Item, + ImmutableArray RelatedItems, + GeneratorExecutionContext Context + ) + { + public bool IsProxy { get; init; } + public bool IsRegistry { get; init; } + } +} diff --git a/src/JsonRpc.Generators/Contexts/GeneratorData.cs b/src/JsonRpc.Generators/Contexts/GeneratorData.cs new file mode 100644 index 000000000..6586abca0 --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/GeneratorData.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + abstract record GeneratorData( + TypeDeclarationSyntax TypeDeclaration, + INamedTypeSymbol TypeSymbol, + JsonRpcAttributes JsonRpcAttributes, + LspAttributes? LspAttributes, + DapAttributes? DapAttributes, + SyntaxSymbol Request, + SyntaxSymbol? Capability, + SyntaxSymbol? RegistrationOptions, + HashSet AdditionalUsings, + SemanticModel Model, + GeneratorExecutionContext Context + ) + { + private AddCacheSource AddCacheSourceDelegate { get; init; } + private ReportCacheDiagnostic CacheDiagnosticDelegate { get; init; } + + public void AddSource(string hintName, SourceText sourceText) + { + AddCacheSourceDelegate(hintName, TypeDeclaration, sourceText); + } + + public void ReportDiagnostic(CacheDiagnosticFactory diagnostic) + { + CacheDiagnosticDelegate(TypeDeclaration, diagnostic); + } + + public static GeneratorData? Create( + GeneratorExecutionContext context, + TypeDeclarationSyntax candidateClass, + AddCacheSource addCacheSource, + ReportCacheDiagnostic cacheDiagnostic, + HashSet additionalUsings + ) + { + var model = context.Compilation.GetSemanticModel(candidateClass.SyntaxTree); + var symbol = model.GetDeclaredSymbol(candidateClass); + if (symbol == null) return null; + var requestType = GetRequestType(candidateClass, symbol); + if (requestType == null) return null; + var jsonRpcAttributes = JsonRpcAttributes.Parse(context, addCacheSource, cacheDiagnostic, candidateClass, symbol, additionalUsings); + var lspAttributes = LspAttributes.Parse(context, addCacheSource, cacheDiagnostic, candidateClass, symbol); + var dapAttributes = DapAttributes.Parse(context, addCacheSource, cacheDiagnostic, candidateClass, symbol); + + additionalUsings.Add(jsonRpcAttributes.HandlerNamespace); + additionalUsings.Add(jsonRpcAttributes.ModelNamespace); + + if (IsRequest(candidateClass)) + { + var responseType = GetResponseType(candidateClass, symbol); + return new RequestItem( + candidateClass, + symbol, + jsonRpcAttributes, + lspAttributes, + dapAttributes, + requestType, + responseType, + responseType.Syntax.GetSyntaxName() == "Unit", + GetCapability(candidateClass, symbol, lspAttributes), + GetRegistrationOptions(candidateClass, symbol, lspAttributes), + GetPartialItem(candidateClass, symbol, requestType), + GetPartialItems(candidateClass, symbol, requestType), + additionalUsings, + model, + context + ) { CacheDiagnosticDelegate = cacheDiagnostic, AddCacheSourceDelegate = addCacheSource }; + } + + if (IsNotification(candidateClass)) + { + return new NotificationItem( + candidateClass, + symbol, + jsonRpcAttributes, + lspAttributes, + dapAttributes, + requestType, + GetCapability(candidateClass, symbol, lspAttributes), + GetRegistrationOptions(candidateClass, symbol, lspAttributes), + additionalUsings, + model, + context + ) { CacheDiagnosticDelegate = cacheDiagnostic, AddCacheSourceDelegate = addCacheSource }; + } + + return null; + } + + public static RequestItem? CreateForResolver(GeneratorData parent) + { + if (parent.LspAttributes?.Resolver?.Symbol.DeclaringSyntaxReferences + .FirstOrDefault( + z => z.GetSyntax() is TypeDeclarationSyntax { AttributeLists: { Count: > 0 } } tds + && tds.AttributeLists.ContainsAttribute("GenerateHandler") + )?.GetSyntax() is TypeDeclarationSyntax declarationSyntax) + { + return Create(parent.Context, declarationSyntax, parent.AddCacheSourceDelegate, parent.CacheDiagnosticDelegate, parent.AdditionalUsings) as RequestItem; + } + + return null; + } + } +} diff --git a/src/JsonRpc.Generators/Contexts/JsonRpcAttributes.cs b/src/JsonRpc.Generators/Contexts/JsonRpcAttributes.cs new file mode 100644 index 000000000..63d5b123d --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/JsonRpcAttributes.cs @@ -0,0 +1,371 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record JsonRpcAttributes( + SyntaxAttributeData? GenerateHandlerMethods, + ImmutableArray HandlerRegistries, + string HandlerMethodName, + string PartialHandlerMethodName, + bool AllowDerivedRequests, + SyntaxAttributeData? GenerateRequestMethods, + ImmutableArray RequestProxies, + string RequestMethodName, + SyntaxAttributeData? GenerateHandler, + string HandlerNamespace, + string HandlerName, + string ModelNamespace + ) + { + public static JsonRpcAttributes Parse( + GeneratorExecutionContext context, + AddCacheSource addCacheSource, + ReportCacheDiagnostic cacheDiagnostic, + TypeDeclarationSyntax syntax, + INamedTypeSymbol symbol, + HashSet additionalUsings + ) + { + var generateHandlerMethodsAttributeSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.JsonRpc.Generation.GenerateHandlerMethodsAttribute"); + var generateRequestMethodsAttributeSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.JsonRpc.Generation.GenerateRequestMethodsAttribute"); + var generateHandlerAttributeSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.JsonRpc.Generation.GenerateHandlerAttribute"); + + var handlerName = Helpers.SpecialCasedHandlerName(symbol).Split('.').Last(); + var attributes = new JsonRpcAttributes( + null, + ImmutableArray.Empty, + GetHandlerMethodName(symbol, handlerName), + GetPartialHandlerMethodName(symbol, handlerName), + false, + null, + ImmutableArray.Empty, + GetRequestMethodName(syntax, symbol, handlerName), + null, + symbol.ContainingNamespace.ToDisplayString(), + handlerName, + symbol.ContainingNamespace.ToDisplayString() + ); + + if (symbol.GetAttribute(generateHandlerAttributeSymbol) is { } generateHandlerData) + { + attributes = attributes with { + GenerateHandler = SyntaxAttributeData.Parse(generateHandlerData), + AllowDerivedRequests = generateHandlerData + .NamedArguments + .Select(z => z is { Key: "AllowDerivedRequests", Value: { Value: true } }) + .Count(z => z) is > 0, + HandlerNamespace = generateHandlerData is { ConstructorArguments: { Length: >=1 } arguments } + ? arguments[0].Value as string ?? attributes.HandlerNamespace + : attributes.HandlerNamespace, + HandlerName = generateHandlerData is { NamedArguments: { Length: >= 1 } namedArguments } + ? namedArguments + .Select(z => z is { Key: "Name", Value: { Value: string str } } ? str : null) + .FirstOrDefault(z => z is { Length: >0 }) ?? attributes.HandlerName + : attributes.HandlerName + }; + + attributes = attributes with { + HandlerMethodName = GetHandlerMethodName(symbol, attributes.HandlerName), + PartialHandlerMethodName = GetPartialHandlerMethodName(symbol, attributes.HandlerName), + RequestMethodName = GetRequestMethodName(syntax, symbol, attributes.HandlerName) + }; + } + + if (symbol.GetAttribute(generateHandlerMethodsAttributeSymbol) is { } generateHandlerMethodsData) + { + var data = SyntaxAttributeData.Parse(generateHandlerMethodsData); + attributes = attributes with { + GenerateHandlerMethods = data, + HandlerMethodName = generateHandlerMethodsData + .NamedArguments + .Select(z => z is { Key: "MethodName", Value: { Value: string value } } ? value : null) + .FirstOrDefault(z => z is not null) ?? attributes.HandlerMethodName, + HandlerRegistries = GetHandlerRegistries( + context, + a => cacheDiagnostic(syntax, a), + generateHandlerMethodsData, + symbol, + additionalUsings + ).ToImmutableArray() + }; + } + + if (symbol.GetAttribute(generateRequestMethodsAttributeSymbol) is { } generateRequestMethodsData) + { + var data = SyntaxAttributeData.Parse(generateRequestMethodsData); + attributes = attributes with { + GenerateRequestMethods = data, + RequestMethodName = generateRequestMethodsData + .NamedArguments + .Select(z => z is { Key: "MethodName", Value: { Value: string value } } ? value : null) + .FirstOrDefault(z => z is not null) ?? attributes.RequestMethodName, + RequestProxies = GetRequestProxies( + context, + (a) => cacheDiagnostic(syntax, a), + generateRequestMethodsData, + symbol, + additionalUsings + ).ToImmutableArray() + }; + } + + return attributes; + } + + private static IEnumerable GetHandlerRegistries( + GeneratorExecutionContext context, + Action> cacheDiagnostic, + AttributeData attributeData, + INamedTypeSymbol interfaceType, + HashSet additionalUsings + ) + { + if (attributeData.ApplicationSyntaxReference?.GetSyntax() is not AttributeSyntax attributeSyntax) yield break; + var foundValue = false; + foreach (var item in attributeSyntax.ArgumentList?.Arguments.ToArray() ?? Array.Empty()) + { + if (item.Expression is TypeOfExpressionSyntax typeOfExpressionSyntax) + { + yield return typeOfExpressionSyntax.Type; + foundValue = true; + } + } + + if (foundValue) yield break; + + if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.LanguageServer.Protocol")) + { + var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); + if (attribute.ConstructorArguments.Length < 2) + { + cacheDiagnostic( static c => Diagnostic.Create(GeneratorDiagnostics.MissingDirection, c.AttributeLists.GetAttribute("GenerateHandlerMethods")?.GetLocation())); + yield break; + } + + var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value!; + + /* + Unspecified = 0b0000, + ServerToClient = 0b0001, + ClientToServer = 0b0010, + Bidirectional = 0b0011 + */ + + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities"); + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); + if (( direction & 0b0001 ) == 0b0001) + { + yield return LanguageProtocolServerToClientRegistry; + } + + if (( direction & 0b0010 ) == 0b0010) + { + yield return LanguageProtocolClientToServerRegistry; + } + + yield break; + } + + if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) + { + var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); + if (attribute.ConstructorArguments.Length < 2) + { + cacheDiagnostic(static c => Diagnostic.Create(GeneratorDiagnostics.MissingDirection, c.AttributeLists.GetAttribute("GenerateHandlerMethods")?.GetLocation())); + yield break; + } + + var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value!; + + /* + Unspecified = 0b0000, + ServerToClient = 0b0001, + ClientToServer = 0b0010, + Bidirectional = 0b0011 + */ + + additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol"); + additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol.Client"); + additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol.Server"); + if (( direction & 0b0001 ) == 0b0001) + { + yield return DebugProtocolServerToClientRegistry; + } + + if (( direction & 0b0010 ) == 0b0010) + { + yield return DebugProtocolClientToServerRegistry; + } + + yield break; + } + + cacheDiagnostic(static c => Diagnostic.Create(GeneratorDiagnostics.CouldNotInferRequestRouter, c.AttributeLists.GetAttribute("GenerateHandlerMethods")?.GetLocation())); + } + + private static NameSyntax LanguageProtocolServerToClientRegistry { get; } = + SyntaxFactory.IdentifierName("ILanguageClientRegistry"); + + private static NameSyntax LanguageProtocolClientToServerRegistry { get; } = + SyntaxFactory.IdentifierName("ILanguageServerRegistry"); + + private static NameSyntax DebugProtocolServerToClientRegistry { get; } = + SyntaxFactory.IdentifierName("IDebugAdapterClientRegistry"); + + private static NameSyntax DebugProtocolClientToServerRegistry { get; } = + SyntaxFactory.IdentifierName("IDebugAdapterServerRegistry"); + + + private static IEnumerable GetRequestProxies( + GeneratorExecutionContext context, + Action> cacheDiagnostic, + AttributeData attributeData, + INamedTypeSymbol interfaceType, + HashSet additionalUsings + ) + { + if (attributeData.ApplicationSyntaxReference?.GetSyntax() is not AttributeSyntax attributeSyntax) yield break; + var foundValue = false; + foreach (var item in attributeSyntax.ArgumentList?.Arguments.ToArray() ?? Array.Empty()) + { + if (item.Expression is TypeOfExpressionSyntax typeOfExpressionSyntax) + { + yield return typeOfExpressionSyntax.Type; + foundValue = true; + } + } + + if (foundValue) yield break; + + if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.LanguageServer.Protocol")) + { + var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); + if (attribute.ConstructorArguments.Length < 2) + { + cacheDiagnostic(static c => Diagnostic.Create(GeneratorDiagnostics.MissingDirection, c.AttributeLists.GetAttribute("GenerateRequestMethods")?.GetLocation())); + yield break; + } + + var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute")!.ConstructorArguments[1].Value!; + + /* + Unspecified = 0b0000, + ServerToClient = 0b0001, + ClientToServer = 0b0010, + Bidirectional = 0b0011 + */ + + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol"); + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); + additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); + if (( direction & 0b0001 ) == 0b0001) + { + yield return LanguageProtocolServerToClient; + } + + if (( direction & 0b0010 ) == 0b0010) + { + yield return LanguageProtocolClientToServer; + } + + yield break; + } + + if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) + { + var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); + if (attribute.ConstructorArguments.Length < 2) + { + cacheDiagnostic(static c => Diagnostic.Create(GeneratorDiagnostics.MissingDirection, c.AttributeLists.GetAttribute("GenerateRequestMethods")?.GetLocation())); + yield break; + } + + var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value!; + + /* + Unspecified = 0b0000, + ServerToClient = 0b0001, + ClientToServer = 0b0010, + Bidirectional = 0b0011 + */ + var maskedDirection = 0b0011 & direction; + additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol"); + + if (( direction & 0b0001 ) == 0b0001) + { + yield return DebugProtocolServerToClient; + } + + if (( direction & 0b0010 ) == 0b0010) + { + yield return DebugProtocolClientToServer; + } + + yield break; + } + + cacheDiagnostic(static c => Diagnostic.Create(GeneratorDiagnostics.CouldNotInferRequestRouter, c.AttributeLists.GetAttribute("GenerateRequestMethods")?.GetLocation())); + } + + private static NameSyntax LanguageProtocolServerToClient { get; } = + SyntaxFactory.ParseName("ILanguageServer"); + + private static NameSyntax LanguageProtocolClientToServer { get; } = + SyntaxFactory.ParseName("ILanguageClient"); + + private static NameSyntax DebugProtocolServerToClient { get; } = + SyntaxFactory.ParseName("IDebugAdapterServer"); + + private static NameSyntax DebugProtocolClientToServer { get; } = + SyntaxFactory.ParseName("IDebugAdapterClient"); + + public static string GetHandlerMethodName(INamedTypeSymbol symbol, string? handlerName) + { + return "On" + ( handlerName is { Length: > 0 } ? handlerName : Helpers.SpecialCasedHandlerName(symbol) ); + } + + public static string GetPartialHandlerMethodName(INamedTypeSymbol symbol, string? handlerName) + { + return "Observe" + ( handlerName is { Length: > 0 } ? handlerName : Helpers.SpecialCasedHandlerName(symbol) ); + } + + public static string GetRequestMethodName(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, string? handlerName) + { + var name = handlerName is { Length: > 0 } ? handlerName : Helpers.SpecialCasedHandlerName(symbol); + if ( + name.StartsWith("Run") + || name.StartsWith("Execute") + // TODO: Change this next breaking change + // || name.StartsWith("Set") + // || name.StartsWith("Attach") + // || name.StartsWith("Read") + || name.StartsWith("Did") + || name.StartsWith("Log") + || name.StartsWith("Show") + || name.StartsWith("Register") + || name.StartsWith("Prepare") + || name.StartsWith("Publish") + || name.StartsWith("ApplyWorkspaceEdit") + || name.StartsWith("Unregister")) + { + return name; + } + + if (name.EndsWith("Resolve", StringComparison.Ordinal)) + { + return "Resolve" + name.Substring(0, name.IndexOf("Resolve", StringComparison.Ordinal)); + } + + return Helpers.IsNotification(syntax) ? "Send" + name : "Request" + name; + } + } +} diff --git a/src/JsonRpc.Generators/Contexts/LspAttributes.cs b/src/JsonRpc.Generators/Contexts/LspAttributes.cs new file mode 100644 index 000000000..c9c535e0d --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/LspAttributes.cs @@ -0,0 +1,114 @@ +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record LspAttributes( + SyntaxAttributeData? GenerateTypedDataAttribute, + bool GenerateTypedData, + SyntaxAttributeData? GenerateContainerAttribute, + bool GenerateContainer, + SyntaxAttributeData? CapabilityAttribute, + SyntaxSymbol? Capability, + SyntaxAttributeData? ResolverAttribute, + SyntaxSymbol? Resolver, + SyntaxAttributeData? RegistrationOptionsKeyAttribute, + string? RegistrationOptionsKey, + SyntaxAttributeData? RegistrationOptionsAttribute, + SyntaxSymbol? RegistrationOptions, + bool CanBeResolved, + bool CanHaveData + ) + { + public static LspAttributes? Parse( + GeneratorExecutionContext context, + AddCacheSource addCacheSource, + ReportCacheDiagnostic cacheDiagnostic, + TypeDeclarationSyntax syntax, + INamedTypeSymbol symbol) + { + var prefix = "OmniSharp.Extensions.LanguageServer.Protocol.Generation"; + + var attributes = new LspAttributes(null, false, null, false, null, null,null, null, null, null, null, null, false, false); + + attributes = attributes with + { + CanBeResolved = syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName()?.Contains("ICanBeResolved") == true) == true || symbol.AllInterfaces.Any(z => z.ToDisplayString().Contains("ICanBeResolved")) == true, + CanHaveData = syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName()?.Contains("ICanHaveData") == true) == true || symbol.AllInterfaces.Any(z => z.ToDisplayString().Contains("ICanHaveData")) == true, + }; + + { + var attributeSymbol = context.Compilation.GetTypeByMetadataName($"{prefix}.GenerateTypedDataAttribute"); + if (symbol.GetAttribute(attributeSymbol) is { } data && data.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax attributeSyntax) + { + attributes = attributes with { + GenerateTypedData = true, + GenerateTypedDataAttribute = new SyntaxAttributeData(attributeSyntax, data) + }; + } + } + { + var attributeSymbol = context.Compilation.GetTypeByMetadataName($"{prefix}.GenerateContainerAttribute"); + if (symbol.GetAttribute(attributeSymbol) is { } data && data.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax attributeSyntax) + { + attributes = attributes with { + GenerateContainer = true, + GenerateContainerAttribute = new SyntaxAttributeData(attributeSyntax, data) + }; + } + } + { + var attributeSymbol = context.Compilation.GetTypeByMetadataName($"{prefix}.RegistrationOptionsKeyAttribute"); + if (symbol.GetAttribute(attributeSymbol) is { ConstructorArguments: { Length: >=1 } arguments } data + && arguments[0].Kind is TypedConstantKind.Primitive && arguments[0].Value is string value + && data.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax attributeSyntax) + { + attributes = attributes with { + RegistrationOptionsKeyAttribute = new SyntaxAttributeData(attributeSyntax, data), + RegistrationOptionsKey = value + }; + } + } + { + var (syntaxAttributeData, syntaxSymbol) = ExtractAttributeTypeData(symbol, context.Compilation.GetTypeByMetadataName($"{prefix}.CapabilityAttribute")); + attributes = attributes with { + CapabilityAttribute = syntaxAttributeData, + Capability = syntaxSymbol + }; + } + { + var (syntaxAttributeData, syntaxSymbol) = ExtractAttributeTypeData(symbol, context.Compilation.GetTypeByMetadataName($"{prefix}.ResolverAttribute")); + attributes = attributes with { + ResolverAttribute = syntaxAttributeData, + Resolver = syntaxSymbol + }; + } + { + var (syntaxAttributeData, syntaxSymbol) = ExtractAttributeTypeData(symbol, context.Compilation.GetTypeByMetadataName($"{prefix}.RegistrationOptionsAttribute")); + attributes = attributes with { + RegistrationOptionsAttribute = syntaxAttributeData, + RegistrationOptions = syntaxSymbol + }; + } + + return attributes; + + static (SyntaxAttributeData? SyntaxAttributeData, SyntaxSymbol? SyntaxSymbol) ExtractAttributeTypeData(INamedTypeSymbol symbol, INamedTypeSymbol? attributeSymbol) + { + if (symbol.GetAttribute(attributeSymbol) is { ConstructorArguments: { Length: >=1 } arguments } data + && arguments[0].Kind is TypedConstantKind.Type && arguments[0].Value is INamedTypeSymbol value + && data.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax attributeSyntax + && attributeSyntax is { ArgumentList: { Arguments: { Count: 1 } syntaxArguments } } + && syntaxArguments[0].Expression is TypeOfExpressionSyntax typeOfExpressionSyntax) + { + return ( new SyntaxAttributeData(attributeSyntax, data), new SyntaxSymbol(typeOfExpressionSyntax.Type, value) ); + } + + return (null, null); + } + } + } +} diff --git a/src/JsonRpc.Generators/Contexts/NotificationItem.cs b/src/JsonRpc.Generators/Contexts/NotificationItem.cs new file mode 100644 index 000000000..18d758bd3 --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/NotificationItem.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record NotificationItem( + TypeDeclarationSyntax TypeDeclaration, + INamedTypeSymbol TypeSymbol, + JsonRpcAttributes JsonRpcAttributes, + LspAttributes? LspAttributes, + DapAttributes? DapAttributes, + SyntaxSymbol Request, + SyntaxSymbol? Capability, + SyntaxSymbol? RegistrationOptions, + HashSet AdditionalUsings, + SemanticModel Model, + GeneratorExecutionContext Context + ) : GeneratorData( + TypeDeclaration, TypeSymbol, JsonRpcAttributes, LspAttributes, + DapAttributes, Request, Capability, RegistrationOptions, + AdditionalUsings, Model, Context + ); +} diff --git a/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs b/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs new file mode 100644 index 000000000..3899f1b8f --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs @@ -0,0 +1,126 @@ +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record RegistrationOptionAttributes( + SyntaxAttributeData? GenerateRegistrationOptions, + string? ServerCapabilityKey, + bool SupportsWorkDoneProgress, + bool SupportsDocumentSelector, + bool SupportsStaticRegistrationOptions, + SyntaxSymbol? RegistrationOptionsConverter, + bool ImplementsWorkDoneProgress, + bool ImplementsDocumentSelector, + bool ImplementsStaticRegistrationOptions + ) + { + public static RegistrationOptionAttributes? Parse(GeneratorExecutionContext context, TypeDeclarationSyntax syntax, INamedTypeSymbol symbol) + { + var registrationOptionsAttributeSymbol = context.Compilation.GetTypeByMetadataName($"OmniSharp.Extensions.LanguageServer.Protocol.Generation.GenerateRegistrationOptionsAttribute"); + var registrationOptionsConverterAttributeSymbol = context.Compilation.GetTypeByMetadataName($"OmniSharp.Extensions.LanguageServer.Protocol.RegistrationOptionsConverterAttribute"); +// var registrationOptionsInterfaceSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions"); + var textDocumentRegistrationOptionsInterfaceSymbol = + context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions"); + var workDoneProgressOptionsInterfaceSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions"); + var staticRegistrationOptionsInterfaceSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.IStaticRegistrationOptions"); + + if (!( symbol.GetAttribute(registrationOptionsAttributeSymbol) is { } data )) return null; + if (!( data.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax attributeSyntax )) return null; + + TypeSyntax? converterSyntax = null; + ITypeSymbol? converter = null; + + var supportsDocumentSelector = data.NamedArguments.Any(z => z is { Key: nameof(SupportsDocumentSelector), Value: { Value: true } }) + || symbol.AllInterfaces.Length > 0 && symbol.AllInterfaces.Any( + z => SymbolEqualityComparer.Default.Equals(z, textDocumentRegistrationOptionsInterfaceSymbol) + ) + || textDocumentRegistrationOptionsInterfaceSymbol is { } && syntax.BaseList?.Types.Any( + type => type.Type.GetSyntaxName()?.Contains(textDocumentRegistrationOptionsInterfaceSymbol.Name) == true + ) == true; + var supportsWorkDoneProgress = data.NamedArguments.Any(z => z is { Key: nameof(SupportsWorkDoneProgress), Value: { Value: true } }) + || symbol.AllInterfaces.Length > 0 && symbol.AllInterfaces.Any( + z => SymbolEqualityComparer.Default.Equals(z, workDoneProgressOptionsInterfaceSymbol) + ) + || workDoneProgressOptionsInterfaceSymbol is { } && syntax.BaseList?.Types.Any( + type => type.Type.GetSyntaxName()?.Contains(workDoneProgressOptionsInterfaceSymbol.Name) == true + ) == true; + var supportsStaticRegistrationOptions = data.NamedArguments.Any(z => z is { Key: nameof(SupportsStaticRegistrationOptions), Value: { Value: true } }) + || symbol.AllInterfaces.Length > 0 && symbol.AllInterfaces.Any( + z => SymbolEqualityComparer.Default.Equals(z, staticRegistrationOptionsInterfaceSymbol) + ) + || staticRegistrationOptionsInterfaceSymbol is { } && syntax.BaseList?.Types.Any( + type => type.Type.GetSyntaxName()?.Contains(staticRegistrationOptionsInterfaceSymbol.Name) == true + ) == true; + + if (attributeSyntax is { ArgumentList: { Arguments: { Count: >=1 } syntaxArguments } }) + { + converter = data.NamedArguments.FirstOrDefault(z => z is { Key: "Converter" }).Value.Type; + converterSyntax = syntaxArguments + .Select( + z => z is { + Expression: TypeOfExpressionSyntax expressionSyntax, NameEquals: { Name: { Identifier: { Text: "Converter" } } } + } + ? expressionSyntax.Type + : null + ) + .FirstOrDefault(); + if (converter is null) + { + if (symbol.GetAttribute(registrationOptionsConverterAttributeSymbol) is { ConstructorArguments: { Length: >=1 } converterArguments } converterData + && converterArguments[0].Kind is TypedConstantKind.Type + && converterData.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax converterAttributeSyntax + && converterAttributeSyntax is { ArgumentList: { Arguments: { Count: 1 } converterArgumentSyntax } } + && converterArgumentSyntax[0].Expression is TypeOfExpressionSyntax converterTypeOfExpressionSyntax) + { + converter = converterArguments[0].Type; + converterSyntax = converterTypeOfExpressionSyntax.Type; + } + } + } + + string? value = null; + if (data is { ConstructorArguments: { Length: > 0 } arguments } && arguments[0].Kind is TypedConstantKind.Primitive && arguments[0].Value is string) + { + value = arguments[0].Value as string; + } + + return new RegistrationOptionAttributes( + new SyntaxAttributeData(attributeSyntax, data), + value, + supportsWorkDoneProgress, + supportsDocumentSelector, + supportsStaticRegistrationOptions, + converterSyntax is null ? null : new SyntaxSymbol(converterSyntax, (INamedTypeSymbol) converter!), + symbol + .GetMembers() + .AsEnumerable() + .All( + z => workDoneProgressOptionsInterfaceSymbol? + .GetMembers() + .AsEnumerable() + .Any(x => SymbolEqualityComparer.Default.Equals(z, x)) == true + ), + symbol + .GetMembers() + .AsEnumerable() + .All( + z => textDocumentRegistrationOptionsInterfaceSymbol? + .GetMembers() + .AsEnumerable() + .Any(x => SymbolEqualityComparer.Default.Equals(z, x)) == true + ), + symbol + .GetMembers() + .AsEnumerable() + .All( + z => staticRegistrationOptionsInterfaceSymbol? + .GetMembers() + .AsEnumerable() + .Any(x => SymbolEqualityComparer.Default.Equals(z, x)) == true + ) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Contexts/RequestItem.cs b/src/JsonRpc.Generators/Contexts/RequestItem.cs new file mode 100644 index 000000000..51a6135cc --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/RequestItem.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record RequestItem( + TypeDeclarationSyntax TypeDeclaration, + INamedTypeSymbol TypeSymbol, + JsonRpcAttributes JsonRpcAttributes, + LspAttributes? LspAttributes, + DapAttributes? DapAttributes, + SyntaxSymbol Request, + SyntaxSymbol Response, + bool IsUnit, + SyntaxSymbol? Capability, + SyntaxSymbol? RegistrationOptions, + SyntaxSymbol? PartialItem, + SyntaxSymbol? PartialItems, + HashSet AdditionalUsings, + SemanticModel Model, + GeneratorExecutionContext Context + ) : GeneratorData( + TypeDeclaration, TypeSymbol, + JsonRpcAttributes, LspAttributes, DapAttributes, Request, Capability, RegistrationOptions, + AdditionalUsings, Model, Context + ); + +// record PartialItem(TypeSyntax Syntax, INamedTypeSymbol Symbol, SyntaxSymbol Item) : SyntaxSymbol(Syntax, Symbol); +} diff --git a/src/JsonRpc.Generators/Contexts/SyntaxSymbol.cs b/src/JsonRpc.Generators/Contexts/SyntaxSymbol.cs new file mode 100644 index 000000000..d49872174 --- /dev/null +++ b/src/JsonRpc.Generators/Contexts/SyntaxSymbol.cs @@ -0,0 +1,19 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts +{ + record SyntaxSymbol(TypeSyntax Syntax, INamedTypeSymbol Symbol); + + record SyntaxAttributeData(AttributeSyntax Syntax, AttributeData Data) + { + public static SyntaxAttributeData? Parse(AttributeData? data) + { + var syntax = data?.ApplicationSyntaxReference?.GetSyntax() ; + if (syntax is AttributeSyntax attributeSyntax) + return new SyntaxAttributeData(attributeSyntax, data!); + + return null; + } + } +} diff --git a/src/JsonRpc.Generators/DelegateHelpers.cs b/src/JsonRpc.Generators/DelegateHelpers.cs new file mode 100644 index 000000000..6bf21d057 --- /dev/null +++ b/src/JsonRpc.Generators/DelegateHelpers.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + internal static class DelegateHelpers + { + public static Func MakeMethodFactory( + MethodDeclarationSyntax method, ParameterListSyntax preParameterList, ParameterListSyntax? postParameterList = null + ) => + (syntax) => method + .WithParameterList( + preParameterList.AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters(postParameterList?.Parameters.ToArray() ?? Array.Empty()) + ); + + public static Func MakeGenericFactory(Func factory, TypeSyntax constraint) + { + return syntax => factory(syntax) + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(TypeConstraint(constraint))) + ) + ); + } + + public static Func MakeGenericFactory( + Func factory, TypeSyntax constraint + ) + { + return (syntax, resolveSyntax) => factory(syntax, resolveSyntax) + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(TypeConstraint(constraint))) + ) + ); + } + + public static Func> MakeGenericFactory( + Func> factory, TypeSyntax constraint + ) + { + return (syntax, resolveSyntax) => factory(syntax, resolveSyntax) + .Select( + method => method + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(TypeConstraint(constraint))) + ) + ) + ); + } + + public static Func> MakeGenericFactory( + Func> factory, TypeSyntax constraint + ) + { + return syntax => factory(syntax) + .Select( + method => method + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(TypeConstraint(constraint))) + ) + ) + ); + } + + public static GenericNameSyntax CreateAction(bool withCancellationToken, params TypeSyntax[] arguments) + { + var typeArguments = arguments.ToList(); + if (withCancellationToken) + { + typeArguments.Add(IdentifierName("CancellationToken")); + } + + return GenericName(Identifier("Action")) + .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); + } + + public static GenericNameSyntax CreateAction(params TypeSyntax[] arguments) => CreateAction(true, arguments); + + public static GenericNameSyntax CreateAsyncAction(params TypeSyntax[] arguments) => CreateAsyncFunc(null, true, arguments); + + public static GenericNameSyntax CreateAsyncAction(bool withCancellationToken, params TypeSyntax[] arguments) => CreateAsyncFunc(null, withCancellationToken, arguments); + + public static GenericNameSyntax CreateAsyncFunc(TypeSyntax? returnType, bool withCancellationToken, params TypeSyntax[] arguments) + { + var typeArguments = arguments.ToList(); + if (withCancellationToken) + { + typeArguments.Add(IdentifierName("CancellationToken")); + } + + if (returnType == null || returnType.GetSyntaxName() == "Unit") + { + typeArguments.Add(IdentifierName("Task")); + } + else + { + typeArguments.Add( + GenericName( + Identifier("Task"), TypeArgumentList( + SeparatedList( + new[] { + returnType + } + ) + ) + ) + ); + } + + return GenericName(Identifier("Func")) + .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); + } + } +} diff --git a/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs b/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs index 99739c072..04287ed7a 100644 --- a/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs +++ b/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; @@ -9,85 +10,73 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using OmniSharp.Extensions.JsonRpc.Generators.Strategies; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; namespace OmniSharp.Extensions.JsonRpc.Generators { [Generator] - public class GenerateHandlerMethodsGenerator : ISourceGenerator + public class GenerateHandlerMethodsGenerator : CachedSourceGenerator { - public void Initialize(GeneratorInitializationContext context) + protected override void Execute(GeneratorExecutionContext context, SyntaxReceiver syntaxReceiver, AddCacheSource addCacheSource, ReportCacheDiagnostic cacheDiagnostic) { - context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); - } - - public void Execute(GeneratorExecutionContext context) - { - if (!( context.SyntaxReceiver is SyntaxReceiver syntaxReceiver )) - { - return; - } - - var options = ( context.Compilation as CSharpCompilation )?.SyntaxTrees[0].Options as CSharpParseOptions; - var compilation = context.Compilation; - - var generateHandlerMethodsAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.JsonRpc.Generation.GenerateHandlerMethodsAttribute"); - var generateRequestMethodsAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.JsonRpc.Generation.GenerateRequestMethodsAttribute"); - -// context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Message, null, $"generateHandlerMethodsAttributeSymbol: {generateHandlerMethodsAttributeSymbol.ToDisplayString()}")); -// context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Message, null, $"generateRequestMethodsAttributeSymbol: {generateRequestMethodsAttributeSymbol.ToDisplayString()}")); - foreach (var candidateClass in syntaxReceiver.Candidates) { // context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Message, null, $"candidate: {candidateClass.Identifier.ToFullString()}")); // can this be async??? context.CancellationToken.ThrowIfCancellationRequested(); - var model = compilation.GetSemanticModel(candidateClass.SyntaxTree); - var symbol = model.GetDeclaredSymbol(candidateClass); - - var methods = new List(); var additionalUsings = new HashSet { "System", "System.Collections.Generic", "System.Threading", "System.Threading.Tasks", "MediatR", - "Microsoft.Extensions.DependencyInjection", + "Microsoft.Extensions.DependencyInjection" }; -// context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Message, null, $"candidate: {candidateClass.Identifier.ToFullString()}")); + GeneratorData? actionItem = null; - var attribute = symbol?.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateHandlerMethodsAttributeSymbol)); - if (attribute != null) + try { - GetExtensionHandlers( - context, - candidateClass, - symbol, - attribute, - methods, - additionalUsings - ); + actionItem = GeneratorData.Create(context, candidateClass, addCacheSource, cacheDiagnostic, additionalUsings); } - - attribute = symbol?.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateRequestMethodsAttributeSymbol)); - if (attribute != null) + catch (Exception e) { - GetExtensionRequestHandlers( - context, - candidateClass, - symbol, - attribute, - methods, - additionalUsings - ); + context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Exception, candidateClass.GetLocation(), e.Message, e.StackTrace ?? string.Empty)); + Debug.WriteLine(e); + Debug.WriteLine(e.StackTrace); } - if (!methods.Any()) continue; + if (actionItem is null) continue; - var className = GetExtensionClassName(symbol); + var members = CompilationUnitGeneratorStrategies.Aggregate( + new List(), (m, strategy) => { + try + { + m.AddRange(strategy.Apply(actionItem)); + } + catch (Exception e) + { + context.ReportDiagnostic( + Diagnostic.Create( + GeneratorDiagnostics.Exception, candidateClass.GetLocation(), $"Strategy {strategy.GetType().FullName} failed!" + " - " + e.Message, + e.StackTrace ?? string.Empty + ) + ); + Debug.WriteLine($"Strategy {strategy.GetType().FullName} failed!"); + Debug.WriteLine(e); + Debug.WriteLine(e.StackTrace); + } + + return m; + } + ); + + if (!members.Any()) continue; var existingUsings = candidateClass.SyntaxTree.GetCompilationUnitRoot() .Usings @@ -96,7 +85,9 @@ public void Execute(GeneratorExecutionContext context) additionalUsings .Except( candidateClass.SyntaxTree.GetCompilationUnitRoot() - .Usings.Select(z => z.Name.ToFullString()) + .Usings + .Where(z => z.Alias == null) + .Select(z => z.Name.ToFullString()) ) .Distinct() .Select(z => UsingDirective(IdentifierName(z))) @@ -104,924 +95,85 @@ public void Execute(GeneratorExecutionContext context) .OrderBy(x => x.Name.ToFullString()) .ToImmutableArray(); - var obsoleteAttribute = candidateClass.AttributeLists - .SelectMany(z => z.Attributes) - .Where(z => z.Name.ToFullString() == nameof(ObsoleteAttribute) || z.Name.ToFullString() == "Obsolete") - .ToArray(); - var attributes = List( - new[] { - AttributeList( - SeparatedList( - new[] { - Attribute(ParseName("System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute")), - Attribute(ParseName("System.Runtime.CompilerServices.CompilerGeneratedAttribute")), - }.Union(obsoleteAttribute) - ) - ) - } - ); - - var isInternal = candidateClass.Modifiers.Any(z => z.IsKind(SyntaxKind.InternalKeyword)); - var cu = CompilationUnit( List(), List(existingUsings), List(), - List( - new[] { - NamespaceDeclaration(ParseName(symbol.ContainingNamespace.ToDisplayString())) - .WithMembers( - SingletonList( - ClassDeclaration(className) - .WithAttributeLists(attributes) - .WithModifiers( - TokenList( - new[] { isInternal ? Token(SyntaxKind.InternalKeyword) : Token(SyntaxKind.PublicKeyword) }.Concat( - new[] { - Token(SyntaxKind.StaticKeyword), - Token(SyntaxKind.PartialKeyword) - } - ) - ) - ) - .WithMembers(List(methods)) - .WithLeadingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)))) - .WithTrailingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)))) - .NormalizeWhitespace() - ) - ) - } - ) + List(members) ) .WithLeadingTrivia(Comment(Preamble.GeneratedByATool)) - .WithTrailingTrivia(CarriageReturnLineFeed) - .NormalizeWhitespace(); + .WithTrailingTrivia(CarriageReturnLineFeed); - context.AddSource( - $"JsonRpc_Handlers_{candidateClass.Identifier.ToFullString().Replace(".", "_")}.cs", - cu.SyntaxTree.GetRoot().GetText(Encoding.UTF8) + addCacheSource( + $"{candidateClass.Identifier.Text}{( candidateClass.Arity > 0 ? candidateClass.Arity.ToString() : "" )}.cs", + candidateClass, + cu.NormalizeWhitespace().GetText(Encoding.UTF8) ); } } + private static readonly ImmutableArray CompilationUnitGeneratorStrategies = GetCompilationUnitGeneratorStrategies(); - private void GetExtensionHandlers( - GeneratorExecutionContext context, - TypeDeclarationSyntax handlerClassOrInterface, - INamedTypeSymbol symbol, - AttributeData attributeData, - List methods, - HashSet additionalUsings - ) - { - foreach (var registry in GetRegistries(attributeData, handlerClassOrInterface, symbol, context, additionalUsings)) - { - if (IsNotification(symbol)) - { - var requestType = GetRequestType(symbol); - methods.AddRange(HandleNotifications(handlerClassOrInterface, symbol, requestType, registry, additionalUsings, attributeData)); - } - else if (IsRequest(symbol)) - { - var requestType = GetRequestType(symbol); - var responseType = GetResponseType(handlerClassOrInterface); - methods.AddRange(HandleRequest(handlerClassOrInterface, symbol, requestType, responseType!, registry, additionalUsings, attributeData)); - } - } - } - - - private void GetExtensionRequestHandlers( - GeneratorExecutionContext context, - TypeDeclarationSyntax handlerClassOrInterface, - INamedTypeSymbol symbol, - AttributeData attributeData, - List methods, - HashSet additionalUsings - ) + private static ImmutableArray GetCompilationUnitGeneratorStrategies() { - var registries = GetProxies( - context, - attributeData, - handlerClassOrInterface, - symbol, - methods, - additionalUsings + var actionContextStrategies = ImmutableArray.Create( + new WarnIfResponseRouterIsNotProvidedStrategy(), + new OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy(), + new OnNotificationMethodGeneratorWithRegistrationOptionsStrategy(), + new OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy(false), + new OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy(true), + new OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy(), + new OnRequestMethodGeneratorWithRegistrationOptionsStrategy(false), + new OnRequestMethodGeneratorWithRegistrationOptionsStrategy(true), + new OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy(), + new SendMethodNotificationStrategy(), + new SendMethodRequestStrategy() ); - - if (( attributeData.ConstructorArguments.Length == 0 || - ( attributeData.ConstructorArguments[0].Kind != TypedConstantKind.Array && attributeData.ConstructorArguments[0].Value == null ) - || ( attributeData.ConstructorArguments[0].Kind == TypedConstantKind.Array && attributeData.ConstructorArguments[0].Values.Length == 0 ) ) - && !symbol.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) - { - context.ReportDiagnostic( - Diagnostic.Create( - GeneratorDiagnostics.NoResponseRouterProvided, handlerClassOrInterface.Identifier.GetLocation(), symbol.Name, - string.Join(", ", registries.Select(z => z.ToFullString())) - ) - ); - } - - foreach (var registry in registries) - { - if (IsNotification(symbol)) - { - var requestType = GetRequestType(symbol); - methods.AddRange(HandleRequestNotifications(handlerClassOrInterface, symbol, requestType, registry, additionalUsings, attributeData)); - } - - if (IsRequest(symbol)) - { - var requestType = GetRequestType(symbol); - var responseType = GetResponseType(handlerClassOrInterface); - methods.AddRange(HandleRequestRequests(handlerClassOrInterface, symbol, requestType, responseType!, registry, additionalUsings, attributeData)); - } - } - } - - private IEnumerable HandleNotifications( - TypeDeclarationSyntax handlerInterface, - INamedTypeSymbol interfaceType, - INamedTypeSymbol requestType, - NameSyntax registryType, - HashSet additionalUsings, - AttributeData attributeData - ) - { - var methodName = GetOnMethodName(interfaceType, attributeData); - - var parameters = ParameterList( - SeparatedList( - new[] { - Parameter(Identifier("registry")) - .WithType(registryType) - .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))) - } - ) + var actionStrategies = ImmutableArray.Create( + new EnsureNamespaceStrategy(), + new HandlerRegistryActionContextRunnerStrategy(actionContextStrategies), + new RequestProxyActionContextRunnerStrategy(actionContextStrategies), + new TypedDelegatingHandlerStrategy() ); - - var capability = GetCapability(interfaceType); - var registrationOptions = GetRegistrationOptions(interfaceType); - if (capability != null) additionalUsings.Add(capability.ContainingNamespace.ToDisplayString()); - if (registrationOptions != null) additionalUsings.Add(registrationOptions.ContainingNamespace.ToDisplayString()); - - if (registrationOptions == null) - { - var method = MethodDeclaration(registryType, methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithExpressionBody(GetNotificationHandlerExpression(GetMethodName(handlerInterface))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - - MemberDeclarationSyntax MakeAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.AddParameters( - Parameter(Identifier("handler")) - .WithType(syntax) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeAction(CreateAction(false, requestType)); - yield return MakeAction(CreateAsyncAction(false, requestType)); - yield return MakeAction(CreateAction(true, requestType)); - yield return MakeAction(CreateAsyncAction(true, requestType)); - if (capability != null) - { - method = method.WithExpressionBody( - GetNotificationCapabilityHandlerExpression(GetMethodName(handlerInterface), requestType, capability) - ); - yield return MakeAction(CreateAction(requestType, capability)); - yield return MakeAction(CreateAsyncAction(requestType, capability)); - } - } - else - { - var method = MethodDeclaration(registryType, methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithBody(GetNotificationRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, registrationOptions)); - - var registrationParameter = Parameter(Identifier("registrationOptions")) - .WithType(NullableType(IdentifierName(registrationOptions.Name))); - - MemberDeclarationSyntax MakeAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.WithParameters( - SeparatedList( - parameters.Parameters.Concat( - new[] { Parameter(Identifier("handler")).WithType(syntax), registrationParameter } - ) - ) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeAction(CreateAction(false, requestType)); - yield return MakeAction(CreateAsyncAction(false, requestType)); - yield return MakeAction(CreateAction(true, requestType)); - yield return MakeAction(CreateAsyncAction(true, requestType)); - if (capability != null) - { - method = method.WithBody( - GetNotificationRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, registrationOptions, capability) - ); - yield return MakeAction(CreateAction(requestType, capability)); - yield return MakeAction(CreateAsyncAction(requestType, capability)); - } - } - } - - private IEnumerable HandleRequest( - TypeDeclarationSyntax handlerInterface, - INamedTypeSymbol interfaceType, - INamedTypeSymbol requestType, - TypeSyntax responseType, - NameSyntax registryType, - HashSet additionalUsings, - AttributeData attributeData - ) - { - var methodName = GetOnMethodName(interfaceType, attributeData); - - var capability = GetCapability(interfaceType); - var registrationOptions = GetRegistrationOptions(interfaceType); - var partialItems = GetPartialItems(requestType); - var partialItem = GetPartialItem(requestType); - if (capability != null) additionalUsings.Add(capability.ContainingNamespace.ToDisplayString()); - if (registrationOptions != null) additionalUsings.Add(registrationOptions.ContainingNamespace.ToDisplayString()); - if (partialItems != null) additionalUsings.Add(partialItems.ContainingNamespace.ToDisplayString()); - if (partialItem != null) additionalUsings.Add(partialItem.ContainingNamespace.ToDisplayString()); - - var parameters = ParameterList( - SeparatedList( - new[] { - Parameter(Identifier("registry")) - .WithType(registryType) - .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))) - } - ) + var compilationUnitStrategies = ImmutableArray.Create( + new HandlerGeneratorStrategy(), + new ExtensionMethodGeneratorStrategy(actionStrategies) ); - - var allowDerivedRequests = attributeData.NamedArguments - .Where(z => z.Key == "AllowDerivedRequests") - .Select(z => z.Value.Value) - .FirstOrDefault() is bool b && b; - - - if (registrationOptions == null) - { - var method = MethodDeclaration(registryType, methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithExpressionBody(GetRequestHandlerExpression(GetMethodName(handlerInterface))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - - MemberDeclarationSyntax MakeAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.AddParameters( - Parameter(Identifier("handler")) - .WithType(syntax) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeAction(CreateAsyncFunc(responseType, false, requestType)); - yield return MakeAction(CreateAsyncFunc(responseType, true, requestType)); - - if (allowDerivedRequests) - { - MemberDeclarationSyntax MakeDerivedAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.WithParameters( - SeparatedList( - parameters.Parameters.Concat( - new[] { Parameter(Identifier("handler")).WithType(syntax) } - ) - ) - ) - ) - .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) - .WithConstraintClauses( - SingletonList( - TypeParameterConstraintClause(IdentifierName("T")) - .WithConstraints(SingletonSeparatedList(TypeConstraint(ResolveTypeName(requestType)))) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeDerivedAction(CreateDerivedAsyncFunc(responseType, false)); - yield return MakeDerivedAction(CreateDerivedAsyncFunc(responseType, true)); - } - - if (partialItems != null) - { - var partialTypeSyntax = ResolveTypeName(partialItems); - var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialTypeSyntax }))); - - method = method.WithExpressionBody(GetPartialResultsHandlerExpression(GetMethodName(handlerInterface), requestType, partialTypeSyntax, responseType)); - - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, true)); - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, false)); - if (capability != null) - { - method = method.WithExpressionBody( - GetPartialResultsCapabilityHandlerExpression( - GetMethodName(handlerInterface), requestType, responseType, - partialTypeSyntax, capability - ) - ); - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, capability)); - } - } - - if (partialItem != null) - { - var partialTypeSyntax = ResolveTypeName(partialItem); - - method = method.WithExpressionBody(GetPartialResultHandlerExpression(GetMethodName(handlerInterface), requestType, partialTypeSyntax, responseType)); - - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, true)); - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, false)); - if (capability != null) - { - method = method.WithExpressionBody( - GetPartialResultCapabilityHandlerExpression(GetMethodName(handlerInterface), requestType, partialTypeSyntax, responseType, capability) - ); - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, capability)); - } - } - - if (capability != null) - { - method = method.WithExpressionBody( - GetRequestCapabilityHandlerExpression(GetMethodName(handlerInterface), requestType, responseType, capability) - ); - if (responseType.ToFullString().EndsWith("Unit")) - { - method = method.WithExpressionBody(GetVoidRequestCapabilityHandlerExpression(GetMethodName(handlerInterface), requestType, capability)); - } - - yield return MakeAction(CreateAsyncFunc(responseType, requestType, capability)); - } - } - else - { - var method = MethodDeclaration(registryType, methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithBody(GetRequestRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, responseType, registrationOptions)); - if (responseType.ToFullString().EndsWith("Unit")) - { - method = method.WithBody(GetVoidRequestRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, registrationOptions)); - } - - var registrationParameter = Parameter(Identifier("registrationOptions")) - .WithType(NullableType(IdentifierName(registrationOptions.Name))) - ; - - MemberDeclarationSyntax MakeAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.WithParameters( - SeparatedList( - parameters.Parameters.Concat( - new[] { Parameter(Identifier("handler")).WithType(syntax), registrationParameter } - ) - ) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeAction(CreateAsyncFunc(responseType, false, requestType)); - yield return MakeAction(CreateAsyncFunc(responseType, true, requestType)); - - if (allowDerivedRequests) - { - MemberDeclarationSyntax MakeDerivedAction(TypeSyntax syntax) - { - return method - .WithParameterList( - parameters.WithParameters( - SeparatedList( - parameters.Parameters.Concat( - new[] { Parameter(Identifier("handler")).WithType(syntax), registrationParameter } - ) - ) - ) - ) - .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) - .WithConstraintClauses( - SingletonList( - TypeParameterConstraintClause(IdentifierName("T")) - .WithConstraints(SingletonSeparatedList(TypeConstraint(ResolveTypeName(requestType)))) - ) - ) - .NormalizeWhitespace(); - } - - yield return MakeDerivedAction(CreateDerivedAsyncFunc(responseType, false)); - yield return MakeDerivedAction(CreateDerivedAsyncFunc(responseType, true)); - } - - if (partialItems != null) - { - var partialTypeSyntax = ResolveTypeName(partialItems); - var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialTypeSyntax }))); - - method = method.WithBody( - GetPartialResultsRegistrationHandlerExpression( - GetMethodName(handlerInterface), requestType, responseType, partialTypeSyntax, - registrationOptions - ) - ); - - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, true)); - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, false)); - if (capability != null) - { - method = method.WithBody( - GetPartialResultsRegistrationHandlerExpression( - GetMethodName(handlerInterface), requestType, responseType, partialTypeSyntax, - registrationOptions, capability - ) - ); - yield return MakeAction(CreatePartialAction(requestType, partialItemsSyntax, capability)); - } - } - - if (partialItem != null) - { - var partialTypeSyntax = ResolveTypeName(partialItem); - - method = method.WithBody( - GetPartialResultRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, partialTypeSyntax, responseType, registrationOptions) - ); - - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, true)); - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, false)); - if (capability != null) - { - method = method.WithBody( - GetPartialResultRegistrationHandlerExpression( - GetMethodName(handlerInterface), requestType, partialTypeSyntax, responseType, registrationOptions, - capability - ) - ); - yield return MakeAction(CreatePartialAction(requestType, partialTypeSyntax, capability)); - } - } - - if (capability != null) - { - method = method.WithBody( - GetRequestRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, responseType, registrationOptions, capability) - ); - if (responseType.ToFullString().EndsWith("Unit")) - { - method = method.WithBody(GetVoidRequestRegistrationHandlerExpression(GetMethodName(handlerInterface), requestType, registrationOptions, capability)); - } - - yield return MakeAction(CreateAsyncFunc(responseType, requestType, capability)); - } - } - } - - private static IEnumerable GetRegistries( - AttributeData attributeData, - TypeDeclarationSyntax interfaceSyntax, - INamedTypeSymbol interfaceType, - GeneratorExecutionContext context, - HashSet additionalUsings - ) - { - if (attributeData.ConstructorArguments[0].Kind != TypedConstantKind.Array) - { - if (attributeData.ConstructorArguments[0].Value is INamedTypeSymbol namedTypeSymbol) - return new[] { ResolveTypeName(namedTypeSymbol) }; - } - else if (attributeData.ConstructorArguments[0].Kind == TypedConstantKind.Array && attributeData.ConstructorArguments[0].Values.Length > 0) - { - return attributeData.ConstructorArguments[0].Values.Select(z => z.Value).OfType() - .Select(ResolveTypeName); - } - - if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.LanguageServer.Protocol")) - { - var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); - if (attribute.ConstructorArguments.Length < 2) - { - context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.MissingDirection, interfaceSyntax.Identifier.GetLocation())); - return Enumerable.Empty(); - } - - var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value!; - - /* - Unspecified = 0b0000, - ServerToClient = 0b0001, - ClientToServer = 0b0010, - Bidirectional = 0b0011 - */ - var maskedDirection = 0b0011 & direction; - - - if (maskedDirection == 1) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities"); - return new[] { LanguageProtocolServerToClientRegistry }; - } - - if (maskedDirection == 2) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); - return new[] { LanguageProtocolClientToServerRegistry }; - } - - if (maskedDirection == 3) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities"); - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); - return new[] { LanguageProtocolClientToServerRegistry, LanguageProtocolServerToClientRegistry }; - } - } - - if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) - { - var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); - if (attribute.ConstructorArguments.Length < 2) - { - context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.MissingDirection, interfaceSyntax.Identifier.GetLocation())); - return Enumerable.Empty(); - } - - var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value!; - - /* - Unspecified = 0b0000, - ServerToClient = 0b0001, - ClientToServer = 0b0010, - Bidirectional = 0b0011 - */ - var maskedDirection = 0b0011 & direction; - additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol"); - additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol.Client"); - additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol.Server"); - - if (maskedDirection == 1) - { - return new[] { DebugProtocolServerToClientRegistry }; - } - - if (maskedDirection == 2) - { - return new[] { DebugProtocolClientToServerRegistry }; - } - - if (maskedDirection == 3) - { - return new[] { DebugProtocolClientToServerRegistry, DebugProtocolServerToClientRegistry }; - } - } - - throw new NotImplementedException("Add inference logic here " + interfaceSyntax.Identifier.ToFullString()); - } - - private static NameSyntax LanguageProtocolServerToClientRegistry { get; } = - IdentifierName("ILanguageClientRegistry"); - - private static NameSyntax LanguageProtocolClientToServerRegistry { get; } = - IdentifierName("ILanguageServerRegistry"); - - private static NameSyntax DebugProtocolServerToClientRegistry { get; } = - IdentifierName("IDebugAdapterClientRegistry"); - - private static NameSyntax DebugProtocolClientToServerRegistry { get; } = - IdentifierName("IDebugAdapterServerRegistry"); - - - public static IEnumerable GetProxies( - GeneratorExecutionContext context, - AttributeData attributeData, - TypeDeclarationSyntax interfaceSyntax, - INamedTypeSymbol interfaceType, - List methods, - HashSet additionalUsings - ) - { - if (attributeData.ConstructorArguments[0].Kind != TypedConstantKind.Array) - { - if (attributeData.ConstructorArguments[0].Value is INamedTypeSymbol namedTypeSymbol) - return new[] { ResolveTypeName(namedTypeSymbol) }; - } - else if (attributeData.ConstructorArguments[0].Kind == TypedConstantKind.Array && attributeData.ConstructorArguments[0].Values.Length > 0) - { - return attributeData.ConstructorArguments[0].Values.Select(z => z.Value).OfType() - .Select(ResolveTypeName); - } - - if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.LanguageServer.Protocol")) - { - var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); - if (attribute.ConstructorArguments.Length < 2) - { - context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.MissingDirection, interfaceSyntax.Identifier.GetLocation())); - return Enumerable.Empty(); - } - - var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value; - - /* - Unspecified = 0b0000, - ServerToClient = 0b0001, - ClientToServer = 0b0010, - Bidirectional = 0b0011 - */ - var maskedDirection = 0b0011 & direction; - - if (maskedDirection == 1) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); - return new[] { LanguageProtocolServerToClient }; - } - - if (maskedDirection == 2) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); - return new[] { LanguageProtocolClientToServer }; - } - - if (maskedDirection == 3) - { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Server"); - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Client"); - return new[] { LanguageProtocolClientToServer, LanguageProtocolServerToClient }; - } - } - - if (interfaceType.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) - { - var attribute = interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute"); - if (attribute.ConstructorArguments.Length < 2) - { - context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.MissingDirection, interfaceSyntax.Identifier.GetLocation())); - return Enumerable.Empty(); - } - - var direction = (int) interfaceType.GetAttributes().First(z => z.AttributeClass?.Name == "MethodAttribute").ConstructorArguments[1].Value; - - /* - Unspecified = 0b0000, - ServerToClient = 0b0001, - ClientToServer = 0b0010, - Bidirectional = 0b0011 - */ - var maskedDirection = 0b0011 & direction; - additionalUsings.Add("OmniSharp.Extensions.DebugAdapter.Protocol"); - - if (maskedDirection == 1) - { - return new[] { DebugProtocolServerToClient }; - } - - if (maskedDirection == 2) - { - return new[] { DebugProtocolClientToServer }; - } - - if (maskedDirection == 3) - { - return new[] { DebugProtocolClientToServer, DebugProtocolServerToClient }; - } - } - - throw new NotImplementedException("Add inference logic here " + interfaceSyntax.Identifier.ToFullString()); + return compilationUnitStrategies; } - private static NameSyntax LanguageProtocolServerToClient { get; } = - ParseName("ILanguageServer"); - - private static NameSyntax LanguageProtocolClientToServer { get; } = - ParseName("ILanguageClient"); - - private static NameSyntax DebugProtocolServerToClient { get; } = - ParseName("IDebugAdapterServer"); - - private static NameSyntax DebugProtocolClientToServer { get; } = - ParseName("IDebugAdapterClient"); - - private IEnumerable HandleRequestNotifications( - TypeDeclarationSyntax handlerInterface, - INamedTypeSymbol interfaceType, - INamedTypeSymbol requestType, - NameSyntax registryType, - HashSet additionalUsings, - AttributeData attributeData - ) + public GenerateHandlerMethodsGenerator() : base(() => new SyntaxReceiver(Cache)) { } + public static CacheContainer Cache = new (); + public class SyntaxReceiver : SyntaxReceiverCache { - var methodName = GetSendMethodName(interfaceType, attributeData); - var method = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithExpressionBody(GetNotificationInvokeExpression()) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - - yield return method - .WithParameterList( - ParameterList( - SeparatedList( - new[] { - Parameter(Identifier("mediator")) - .WithType(registryType) - .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))), - Parameter(Identifier("@params")) - .WithType(IdentifierName(requestType.Name)) - } - ) - ) - ) - .NormalizeWhitespace(); - } + private string _attributes; + public List Candidates { get; } = new(); - private IEnumerable HandleRequestRequests( - TypeDeclarationSyntax handlerInterface, - INamedTypeSymbol interfaceType, - INamedTypeSymbol requestType, - TypeSyntax responseType, - NameSyntax registryType, - HashSet additionalUsings, - AttributeData attributeData - ) - { - var methodName = GetSendMethodName(interfaceType, attributeData); - var parameterList = ParameterList( - SeparatedList( - new[] { - Parameter(Identifier("mediator")) - .WithType(registryType) - .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))), - Parameter(Identifier("@params")) - .WithType(IdentifierName(requestType.Name)), - Parameter(Identifier("cancellationToken")) - .WithType(IdentifierName("CancellationToken")) - .WithDefault( - EqualsValueClause( - LiteralExpression(SyntaxKind.DefaultLiteralExpression, Token(SyntaxKind.DefaultKeyword)) - ) - ) - } - ) - ); - var partialItem = GetPartialItem(requestType); - if (partialItem != null) + public SyntaxReceiver(CacheContainer cache) : base(cache) { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); - var partialTypeSyntax = ResolveTypeName(partialItem); - yield return MethodDeclaration( - GenericName( - Identifier("IRequestProgressObservable") - ) - .WithTypeArgumentList( - TypeArgumentList( - SeparatedList( - new TypeSyntax[] { - partialTypeSyntax, - responseType - } - ) - ) - ), - Identifier(methodName) - ) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithParameterList(parameterList) - .WithExpressionBody(GetPartialInvokeExpression(responseType)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .NormalizeWhitespace(); - yield break; + _attributes = "GenerateHandler,GenerateRequestMethods,GenerateHandlerMethods"; } - var partialItems = GetPartialItems(requestType); - if (partialItems != null) + public override string? GetKey(TypeDeclarationSyntax syntax) { - additionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); - var partialTypeSyntax = ResolveTypeName(partialItems); - var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialTypeSyntax }))); - yield return MethodDeclaration( - GenericName( - Identifier("IRequestProgressObservable") - ) - .WithTypeArgumentList( - TypeArgumentList( - SeparatedList( - new TypeSyntax[] { - partialItemsSyntax, - responseType - } - ) - ) - ), - Identifier(methodName) - ) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithParameterList(parameterList) - .WithExpressionBody(GetPartialInvokeExpression(responseType)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .NormalizeWhitespace(); - ; - yield break; + var hasher = new CacheKeyHasher(); + hasher.Append(syntax.SyntaxTree.FilePath); + hasher.Append(syntax.Identifier.Text); + hasher.Append(syntax.TypeParameterList); + hasher.Append(syntax.AttributeLists); + hasher.Append(syntax.BaseList); + return hasher; } - - var responseSyntax = responseType.ToFullString().EndsWith("Unit") - ? IdentifierName("Task") as NameSyntax - : GenericName("Task").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { responseType }))); - yield return MethodDeclaration(responseSyntax, methodName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithParameterList(parameterList) - .WithExpressionBody(GetRequestInvokeExpression()) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .NormalizeWhitespace(); - } - - - /// - /// Created on demand before each generation pass - /// - internal class SyntaxReceiver : ISyntaxReceiver - { - public List Candidates { get; } = new List(); - /// /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation /// - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + public override void OnVisitNode(TypeDeclarationSyntax syntaxNode) { // any field with at least one attribute is a candidate for property generation - if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax && - classDeclarationSyntax.AttributeLists.Count > 0 - ) - { - Candidates.Add(classDeclarationSyntax); - } - - // any field with at least one attribute is a candidate for property generation - if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && - interfaceDeclarationSyntax.AttributeLists.Count > 0 - ) + if (syntaxNode is ( ClassDeclarationSyntax { } or InterfaceDeclarationSyntax { }) && syntaxNode.AttributeLists.ContainsAttribute(_attributes)) { - Candidates.Add(interfaceDeclarationSyntax); + Candidates.Add(syntaxNode); } } } diff --git a/src/JsonRpc.Generators/GeneratorDiagnostics.cs b/src/JsonRpc.Generators/GeneratorDiagnostics.cs index 3642d47d0..2fcce71c7 100644 --- a/src/JsonRpc.Generators/GeneratorDiagnostics.cs +++ b/src/JsonRpc.Generators/GeneratorDiagnostics.cs @@ -4,13 +4,9 @@ namespace OmniSharp.Extensions.JsonRpc.Generators { internal static class GeneratorDiagnostics { - public static DiagnosticDescriptor MissingDirection { get; } = new DiagnosticDescriptor( - "LSP1000", "Missing Direction", - "No direction defined for Language Server Protocol Handler", "LSP", DiagnosticSeverity.Warning, true - ); public static DiagnosticDescriptor Exception { get; } = new DiagnosticDescriptor( "JRPC0001", "Exception", - "{0}", "JRPC", DiagnosticSeverity.Error, true + "{0} - {1}", "JRPC", DiagnosticSeverity.Error, true ); public static DiagnosticDescriptor NoHandlerRegistryProvided { get; } = new DiagnosticDescriptor( @@ -23,9 +19,19 @@ internal static class GeneratorDiagnostics "No Response Router Provided for handler {0}, defaulting to {1}.", "JsonRPC", DiagnosticSeverity.Info, true ); - public static DiagnosticDescriptor ClassMustBePartial { get; } = new DiagnosticDescriptor( - "JRPC1002", "Class must be made partial", - "Class {0} must be made partial.", "JsonRPC", DiagnosticSeverity.Warning, true + public static DiagnosticDescriptor MissingDirection { get; } = new DiagnosticDescriptor( + "JRPC1002", "Missing Direction", + "No direction defined on request Debug Adapter Protocol or Language Server Protocol for inference to work correctly, please specify the target interface(s).", "JsonRPC", DiagnosticSeverity.Error, true + ); + + public static DiagnosticDescriptor CouldNotInferRequestRouter { get; } = new DiagnosticDescriptor( + "JRPC1003", "Cannot infer request router(s)", + "Could not infer the request router(s) to use, please specify the target interface(s).", "JsonRPC", DiagnosticSeverity.Error, true + ); + + public static DiagnosticDescriptor MustBePartial { get; } = new DiagnosticDescriptor( + "JRPC1004", "Type must be made partial", + "Type {0} must be made partial.", "JsonRPC", DiagnosticSeverity.Error, true ); public static DiagnosticDescriptor MustInheritFromCanBeResolved { get; } = new DiagnosticDescriptor( diff --git a/src/JsonRpc.Generators/Helpers.cs b/src/JsonRpc.Generators/Helpers.cs index 7aab668bd..2608e64fc 100644 --- a/src/JsonRpc.Generators/Helpers.cs +++ b/src/JsonRpc.Generators/Helpers.cs @@ -1,22 +1,45 @@ #nullable enable using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace OmniSharp.Extensions.JsonRpc.Generators { internal static class Helpers { - public static bool IsNotification(INamedTypeSymbol symbol) => symbol.AllInterfaces.Any(z => z.Name == "IJsonRpcNotificationHandler"); - - public static bool IsRequest(INamedTypeSymbol symbol) => symbol.AllInterfaces.Any(z => z.Name == "IJsonRpcRequestHandler"); - - public static ExpressionSyntax GetMethodName(TypeDeclarationSyntax interfaceSyntax) + public static bool IsNotification(TypeDeclarationSyntax symbol) => + symbol.BaseList?.Types + .Any( + z => + z.Type is SimpleNameSyntax and ( + { Identifier: { Text: "IJsonRpcNotificationHandler" }, Arity: 0 or 1 } + or { Identifier: { Text: "IRequest" }, Arity: 0 } + ) + ) == true; + + public static bool IsRequest(TypeDeclarationSyntax symbol) => + symbol.BaseList?.Types + .Any( + z => + z.Type is SimpleNameSyntax and ( + { Identifier: { Text: "IJsonRpcRequestHandler" }, Arity: 1 or 2 } + or { Identifier: { Text: "ICanBeResolvedHandler" }, Arity: 1 } + or { Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } + or { Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } + or { Identifier: { Text: "IRequest" }, Arity: 1 } + or { Identifier: { Text: "IJsonRpcRequest" }, Arity: 0 } + ) + ) == true; + + public static ExpressionSyntax GetJsonRpcMethodName(TypeDeclarationSyntax interfaceSyntax) { var methodAttribute = interfaceSyntax.AttributeLists .SelectMany(z => z.Attributes) @@ -25,102 +48,203 @@ public static ExpressionSyntax GetMethodName(TypeDeclarationSyntax interfaceSynt return methodAttribute.ArgumentList!.Arguments[0].Expression; } - public static TypeSyntax GetRequestType(InterfaceDeclarationSyntax syntax) + public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol) { - if (syntax.ConstraintClauses.Any()) + TypeSyntax? type = null!; + foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) { - return syntax.ConstraintClauses.First() - .Constraints - .OfType() - .FirstOrDefault()?.Type - ?? throw new ArgumentException("Generic type does not have a constraint", nameof(syntax)); + type = baseType.Type switch { + GenericNameSyntax gns => gns switch { + { Identifier: { Text: "IJsonRpcRequestHandler" }, Arity: 1 } => ParseName("MediatR.Unit"), + { Identifier: { Text: "IJsonRpcRequestHandler" }, Arity: 2 } => gns.TypeArgumentList.Arguments[1], + { Identifier: { Text: "ICanBeResolvedHandler" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IRequest" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0], + _ => null + }, + SimpleNameSyntax sns and { Identifier: { Text: "IRequest" } } => ParseName("MediatR.Unit"), + SimpleNameSyntax sns and { Identifier: { Text: "IJsonRpcRequest" } } => ParseName("MediatR.Unit"), + _ => null + }; + if (type != null) break; } - var interfaceType = syntax.BaseList?.Types - .Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null) - .Where(z => z != null) - .First(z => z!.Identifier.Text == "IJsonRpcRequestHandler" || z.Identifier.Text == "ICanBeResolvedHandler" || z.Identifier.Text == "IJsonRpcNotificationHandler")!; + if (type == null) throw new ArgumentException($"Response Type {symbol.ToDisplayString()} is not a name symbol", nameof(symbol)); - return interfaceType.TypeArgumentList.Arguments[0]; + var handlerInterface = symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2); + if (handlerInterface?.TypeArguments[1] is INamedTypeSymbol ns) + return new SyntaxSymbol(type, ns); + handlerInterface = symbol.AllInterfaces.FirstOrDefault(z => ( z.Name == "IRequest" && z.Arity == 1 )); + if (handlerInterface?.TypeArguments[0] is INamedTypeSymbol ns2) + return new SyntaxSymbol(type, ns2); + throw new ArgumentException($"Response Type {symbol.ToDisplayString()} is not a name symbol", nameof(symbol)); } - public static TypeSyntax? GetResponseType(TypeDeclarationSyntax syntax) + public static SyntaxSymbol? GetRequestType(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol) { - return syntax.BaseList?.Types - .Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null) - .Where(z => z != null) - .Where(z => z!.Identifier.Text == "IJsonRpcRequestHandler") - .Select(z => z!.Arity == 1 ? IdentifierName("MediatR.Unit") : z.TypeArgumentList.Arguments[1]) - .FirstOrDefault() - ?? syntax.BaseList?.Types - .Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null) - .Where(z => z != null) - .Where(z => z!.Identifier.Text == "ICanBeResolvedHandler") - .Select(z => z!.TypeArgumentList.Arguments[0]) - .FirstOrDefault(); - } + TypeSyntax? type = null; + if (syntax.ConstraintClauses.Any()) + { + type = syntax.ConstraintClauses.First() + .Constraints + .OfType() + .FirstOrDefault()?.Type; + } + else if (syntax.BaseList?.Types.Select(z => z.Type).OfType().Any(z => z.Identifier.Text == "IRequest" || z.Identifier.Text == "IJsonRpcRequest") + == true) + { + type = IdentifierName(syntax.Identifier.Text); + } + else + { + foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) + { + type = baseType.Type switch { + GenericNameSyntax gns => gns switch { + { Identifier: { Text: "IJsonRpcRequestHandler" } } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IJsonRpcNotificationHandler" } } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "ICanBeResolvedHandler" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IRequest" } } => ParseTypeName(syntax.Identifier.Text), + { Identifier: { Text: "IJsonRpcRequest" } } => ParseTypeName(syntax.Identifier.Text), + { Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } => ParseTypeName(syntax.Identifier.Text), + { Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } => ParseTypeName(syntax.Identifier.Text), + _ => null, + }, + _ => null, + }; + if (type != null) break; + } + } - public static INamedTypeSymbol GetRequestType(INamedTypeSymbol symbol) - { - var handlerInterface = symbol.AllInterfaces.First(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2); - var arg = handlerInterface.TypeArguments[0]; + if (type == null) return null; + + var handlerInterface = symbol.AllInterfaces + .FirstOrDefault(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2); + var arg = handlerInterface?.TypeArguments[0] + ?? ( symbol.AllInterfaces.Any(z => ( z.Name == "IRequest" && z.Arity == 1 ) || z.Name == "IJsonRpcRequest") ? symbol as ITypeSymbol : null ); if (arg is ITypeParameterSymbol typeParameterSymbol) { - return typeParameterSymbol.ConstraintTypes.OfType().FirstOrDefault() ?? throw new ArgumentException("Generic type does not have a constraint", nameof(symbol)); + return new SyntaxSymbol( + type, typeParameterSymbol.ConstraintTypes.OfType().FirstOrDefault() + ?? throw new ArgumentException("Generic type does not have a constraint", nameof(symbol)) + ); } if (arg is INamedTypeSymbol namedTypeSymbol) { - return namedTypeSymbol; + return new SyntaxSymbol(type, namedTypeSymbol); } - throw new NotSupportedException($"Request Type {symbol.ToDisplayString()} is not supported!"); + return null; } - public static INamedTypeSymbol GetResponseType(INamedTypeSymbol symbol) + public static SyntaxSymbol? GetCapability(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, LspAttributes? lspAttributes) { - var handlerInterface = symbol.AllInterfaces.First(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2); - return handlerInterface.TypeArguments[1] is INamedTypeSymbol ns ? ns : throw new ArgumentException($"Response Type {symbol.ToDisplayString()} is not a name symbol", nameof(symbol)); - } + TypeSyntax? type = null!; + foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) + { + type = baseType.Type switch { + GenericNameSyntax gns => gns switch { + { Identifier: { Text: "ICapability" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IRegistration" }, Arity: 2 } => gns.TypeArgumentList.Arguments[1], + _ => null + }, + _ => null + }; + if (type != null) break; + } - public static INamedTypeSymbol? GetCapability(INamedTypeSymbol symbol) - { - var handlerInterface = symbol.AllInterfaces - .FirstOrDefault(z => z.Name == "ICapability" && z.TypeArguments.Length == 1); - return handlerInterface?.TypeArguments[0] as INamedTypeSymbol; - } + if (type == null + && lspAttributes?.CapabilityAttribute?.Syntax is { } and { ArgumentList: { Arguments: { Count: > 0 } } arguments } + && arguments.Arguments[0].Expression is TypeOfExpressionSyntax toes) + { + type = toes.Type; + } + + if (type == null) + return null; - public static INamedTypeSymbol? GetRegistrationOptions(INamedTypeSymbol symbol) - { var handlerInterface = symbol.AllInterfaces - .FirstOrDefault(z => z.Name == "IRegistration" && z.TypeArguments.Length == 1); - return handlerInterface?.TypeArguments[0] as INamedTypeSymbol; + .FirstOrDefault(z => z.Name == "ICapability" && z.TypeArguments.Length == 1)?.TypeArguments[0] + ?? symbol.AllInterfaces + .FirstOrDefault(z => z.Name == "IRegistration" && z.TypeArguments.Length == 2)?.TypeArguments[1]; + if (handlerInterface == null + && lspAttributes?.CapabilityAttribute?.Data is { } and { ConstructorArguments: { Length: > 0 } constructorArguments } + && constructorArguments[0].Value is INamedTypeSymbol nts) + { + handlerInterface = nts; + } + + return new SyntaxSymbol(type, ( handlerInterface as INamedTypeSymbol )!); } - public static INamedTypeSymbol? GetPartialItems(INamedTypeSymbol symbol) + public static SyntaxSymbol? GetRegistrationOptions(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, LspAttributes? lspAttributes) { + TypeSyntax? type = null!; + foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) + { + type = baseType.Type switch { + GenericNameSyntax gns and { Identifier: { Text: "IRegistration" }, Arity: >0 } => gns.TypeArgumentList.Arguments[0], + _ => null + }; + if (type != null) break; + } + + if (type == null + && lspAttributes?.RegistrationOptionsAttribute?.Syntax is { } and { ArgumentList: { Arguments: { Count: > 0 } } arguments } + && arguments.Arguments[0].Expression is TypeOfExpressionSyntax toes) + { + type = toes.Type; + } + + if (type == null) + return null; var handlerInterface = symbol.AllInterfaces - .FirstOrDefault(z => z.Name == "IPartialItems" && z.TypeArguments.Length == 1); - return handlerInterface?.TypeArguments[0] as INamedTypeSymbol; + .FirstOrDefault(z => z.Name == "IRegistration" && z.TypeArguments.Length == 1)?.TypeArguments[0] + ?? symbol.AllInterfaces + .FirstOrDefault(z => z.Name == "IRegistration" && z.TypeArguments.Length == 2)?.TypeArguments[0]; + if (handlerInterface == null + && lspAttributes?.RegistrationOptionsAttribute?.Data is { } and { ConstructorArguments: { Length: > 0 } constructorArguments } + && constructorArguments[0].Value is INamedTypeSymbol nts) + { + handlerInterface = nts; + } + + return new SyntaxSymbol(type, ( handlerInterface as INamedTypeSymbol )!); } - public static INamedTypeSymbol? GetPartialItem(INamedTypeSymbol symbol) + public static SyntaxSymbol? GetPartialItems(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType) { var handlerInterface = symbol.AllInterfaces - .FirstOrDefault(z => z.Name == "IPartialItem" && z.TypeArguments.Length == 1); - return handlerInterface?.TypeArguments[0] as INamedTypeSymbol; + .FirstOrDefault(z => z.Name == "IPartialItems" && z.TypeArguments.Length == 1) + ?? requestType.Symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IPartialItems" && z.TypeArguments.Length == 1); + var localSymbol = ( handlerInterface?.TypeArguments[0] as INamedTypeSymbol ); + if (localSymbol == null) return null; + var type = syntax.BaseList?.Types + .Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null) + .Where(z => z != null) + .Where(z => z!.Identifier.Text == "IPartialItemsRequest" && z.Arity == 2) + .Select(z => z!.TypeArgumentList.Arguments[1]) + .FirstOrDefault(); + + return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol); } - public static GenericNameSyntax CreateAction(bool withCancellationToken, params ITypeSymbol[] types) + public static SyntaxSymbol? GetPartialItem(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType) { - var typeArguments = types.Select(ResolveTypeName).ToList(); - if (withCancellationToken) - { - typeArguments.Add(IdentifierName("CancellationToken")); - } - - return GenericName(Identifier("Action")) - .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); + var handlerInterface = symbol.AllInterfaces + .FirstOrDefault(z => z.Name == "IPartialItem" && z.TypeArguments.Length == 1) + ?? requestType.Symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IPartialItem" && z.TypeArguments.Length == 1); + var localSymbol = ( handlerInterface?.TypeArguments[0] as INamedTypeSymbol ); + if (localSymbol == null) return null; + var type = syntax.BaseList?.Types + .Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null) + .Where(z => z != null) + .Where(z => z!.Identifier.Text == "IPartialItemRequest" && z.Arity == 2) + .Select(z => z!.TypeArgumentList.Arguments[1]) + .FirstOrDefault(); + return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol); } public static NameSyntax ResolveTypeName(ITypeSymbol symbol) @@ -129,7 +253,7 @@ public static NameSyntax ResolveTypeName(ITypeSymbol symbol) { if (namedTypeSymbol.IsGenericType) { - // TODO: Fix for generic types + // TODO: Fix for generic arguments return ParseName(namedTypeSymbol.ToString()); } @@ -140,108 +264,43 @@ public static NameSyntax ResolveTypeName(ITypeSymbol symbol) return IdentifierName(symbol.Name); } - public static GenericNameSyntax CreateAction(params ITypeSymbol[] types) => CreateAction(true, types); - - public static GenericNameSyntax CreateAsyncAction(params ITypeSymbol[] types) => CreateAsyncFunc(null, true, types); - - public static GenericNameSyntax CreateAsyncAction(bool withCancellationToken, params ITypeSymbol[] types) => CreateAsyncFunc(null, withCancellationToken, types); - - public static GenericNameSyntax CreateAsyncFunc(TypeSyntax? responseType, params ITypeSymbol[] types) => CreateAsyncFunc(responseType, true, types); - - public static GenericNameSyntax CreateAsyncFunc(TypeSyntax? responseType, bool withCancellationToken, params ITypeSymbol[] types) - { - var typeArguments = types.Select(ResolveTypeName).ToList(); - if (withCancellationToken) - { - typeArguments.Add(IdentifierName("CancellationToken")); - } - - if (responseType == null || responseType.ToFullString().EndsWith("Unit")) - { - typeArguments.Add(IdentifierName("Task")); - } - else - { - typeArguments.Add( - GenericName( - Identifier("Task"), TypeArgumentList( - SeparatedList( - new[] { - responseType - } - ) - ) - ) - ); - } - - return GenericName(Identifier("Func")) - .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); - } - - public static GenericNameSyntax CreateDerivedAsyncFunc(TypeSyntax? responseType, bool withCancellationToken) + public static GenericNameSyntax CreatePartialAction(TypeSyntax requestType, TypeSyntax partialType, bool withCancellationToken, params TypeSyntax[] types) { var typeArguments = new List { - IdentifierName("T") - }; - if (withCancellationToken) - { - typeArguments.Add(IdentifierName("CancellationToken")); - } - - if (responseType == null || responseType.ToFullString().EndsWith("Unit")) - { - typeArguments.Add(IdentifierName("Task")); - } - else - { - typeArguments.Add( - GenericName( - Identifier("Task"), TypeArgumentList( - SeparatedList( - new[] { - responseType - } - ) - ) - ) - ); - } - - return GenericName(Identifier("Func")) - .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); - } - - public static GenericNameSyntax CreatePartialAction(ITypeSymbol requestType, NameSyntax partialType, bool withCancellationToken, params ITypeSymbol[] types) - { - var typeArguments = new List { - ResolveTypeName(requestType), + requestType, GenericName("IObserver").WithTypeArgumentList(TypeArgumentList(SeparatedList(new TypeSyntax[] { partialType }))), }; - typeArguments.AddRange(types.Select(ResolveTypeName)); + typeArguments.AddRange(types); if (withCancellationToken) { typeArguments.Add(IdentifierName("CancellationToken")); } return GenericName(Identifier("Action")) - .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); + .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); } - public static GenericNameSyntax CreatePartialAction(ITypeSymbol requestType, NameSyntax partialType, params ITypeSymbol[] types) => - CreatePartialAction(requestType, partialType, true, types); - - private static ExpressionStatementSyntax EnsureRegistrationOptionsIsSet(NameSyntax registrationOptionsName, TypeSyntax registrationOptionsType) => + public static ExpressionStatementSyntax EnsureRegistrationOptionsIsSet(NameSyntax registrationOptionsName, TypeSyntax registrationOptionsType, bool hasCapability) => ExpressionStatement( AssignmentExpression( SyntaxKind.CoalesceAssignmentExpression, registrationOptionsName, - ObjectCreationExpression(registrationOptionsType is NullableTypeSyntax nts ? nts.ElementType : registrationOptionsType) - .WithArgumentList(ArgumentList()) + ( hasCapability + ? SimpleLambdaExpression( + Parameter( + Identifier("_") + ) + ) + : ParenthesizedLambdaExpression() as LambdaExpressionSyntax + ) + .WithExpressionBody( + ObjectCreationExpression(registrationOptionsType is NullableTypeSyntax nts ? nts.ElementType : registrationOptionsType) + .WithArgumentList(ArgumentList()) + ) ) ); - private static InvocationExpressionSyntax AddHandler(params ArgumentSyntax[] arguments) => InvocationExpression( + public static InvocationExpressionSyntax AddHandler(params ArgumentSyntax[] arguments) => InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("registry"), @@ -250,83 +309,89 @@ private static InvocationExpressionSyntax AddHandler(params ArgumentSyntax[] arg ) .WithArgumentList(ArgumentList(SeparatedList(arguments))); + public static InvocationExpressionSyntax AddHandler(ExpressionSyntax syntax, params ArgumentSyntax[] arguments) => + InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, syntax, IdentifierName("AddHandler"))) + .WithArgumentList(ArgumentList(SeparatedList(arguments))); + private static ArgumentListSyntax GetHandlerArgumentList() => ArgumentList( SeparatedList( new[] { - Argument(IdentifierName("handler")) + HandlerArgument } ) ); - private static ArgumentListSyntax GetRegistrationHandlerArgumentList(NameSyntax registrationOptionsName) => + public static ArgumentListSyntax GetRegistrationHandlerArgumentList( + TypeSyntax registrationOptionsName, TypeSyntax registrationType, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType, bool includeId + ) => ArgumentList( SeparatedList( - new[] { - Argument(IdentifierName("handler")), - Argument(registrationOptionsName) - } + includeId + ? new[] { + Argument(IdentifierName("id")), + handlerArgument, + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)) + } + : new[] { + handlerArgument, + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)) + } ) ); - private static ArgumentListSyntax GetPartialResultArgumentList(TypeSyntax responseName) => - ArgumentList( - SeparatedList( - new[] { - Argument(IdentifierName("handler")), - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("_"), - GenericName(Identifier("GetService")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) - ) - ) - ), - Argument( - SimpleLambdaExpression( - Parameter(Identifier("values")), - ObjectCreationExpression(responseName is NullableTypeSyntax nts ? nts.ElementType : responseName) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("values"))))) - ) + public static ArgumentSyntax HandlerArgument = Argument(IdentifierName("handler")); + public static ArgumentSyntax ResolveHandlerArgument = Argument(IdentifierName("resolveHandler")); + + public static ArgumentSyntax GetHandlerAdapterArgument( + TypeArgumentListSyntax typeArgumentListSyntax, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType, bool isPartial + ) + { + var adapterName = ( isPartial ? "Partial" : "Handler" ) + "Adapter"; + TypeSyntax name = IdentifierName(adapterName); + if (capabilityType is { }) + { + name = GenericName(Identifier(adapterName)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(capabilityType))); + } + + return Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + name, + GenericName(Identifier("Adapt")) + .WithTypeArgumentList(typeArgumentListSyntax) ) - } - ) + ) + .WithArgumentList(ArgumentList(SingletonSeparatedList(handlerArgument))) ); + } - private static ArgumentListSyntax GetPartialResultRegistrationArgumentList(TypeSyntax registrationOptionsName, TypeSyntax responseName) => - ArgumentList( - SeparatedList( - new[] { - Argument(IdentifierName("handler")), - Argument(registrationOptionsName), - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("_"), - GenericName(Identifier("GetService")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) - ) - ) - ), - Argument( - SimpleLambdaExpression( - Parameter(Identifier("values")), - ObjectCreationExpression(responseName is NullableTypeSyntax nts ? nts.ElementType : responseName) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("values"))))) - ) - ) - } + public static InvocationExpressionSyntax GetRegistrationOptionsAdapter( + TypeSyntax registrationOptionsName, + TypeSyntax registrationType, + TypeSyntax? capabilityType + ) + { + NameSyntax name = IdentifierName("RegistrationAdapter"); + if (capabilityType is { }) + { + name = GenericName(Identifier("RegistrationAdapter")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(capabilityType))); + } + + return InvocationExpression( + QualifiedName(name, GenericName("Adapt").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { registrationType })))) ) - ); + .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(registrationOptionsName)))); + } - private static ArgumentListSyntax GetPartialItemsArgumentList(TypeSyntax responseName) => + private static ArgumentListSyntax GetPartialResultArgumentList(TypeSyntax responseName, ArgumentSyntax handlerArgument) => ArgumentList( SeparatedList( new[] { - Argument(IdentifierName("handler")), + handlerArgument, Argument( InvocationExpression( MemberAccessExpression( @@ -340,7 +405,7 @@ private static ArgumentListSyntax GetPartialItemsArgumentList(TypeSyntax respons Argument( SimpleLambdaExpression( Parameter(Identifier("values")), - ObjectCreationExpression(responseName) + ObjectCreationExpression(responseName is NullableTypeSyntax nts ? nts.ElementType : responseName) .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("values"))))) ) ) @@ -348,12 +413,11 @@ private static ArgumentListSyntax GetPartialItemsArgumentList(TypeSyntax respons ) ); - private static ArgumentListSyntax GetPartialItemsRegistrationArgumentList(TypeSyntax registrationOptionsName, TypeSyntax responseName) => + private static ArgumentListSyntax GetPartialItemsArgumentList(TypeSyntax responseName, ArgumentSyntax handlerArgument) => ArgumentList( SeparatedList( new[] { - Argument(IdentifierName("handler")), - Argument(registrationOptionsName), + handlerArgument, Argument( InvocationExpression( MemberAccessExpression( @@ -367,7 +431,7 @@ private static ArgumentListSyntax GetPartialItemsRegistrationArgumentList(TypeSy Argument( SimpleLambdaExpression( Parameter(Identifier("values")), - ObjectCreationExpression(responseName is NullableTypeSyntax nts ? nts.ElementType : responseName) + ObjectCreationExpression(responseName) .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("values"))))) ) ) @@ -375,7 +439,7 @@ private static ArgumentListSyntax GetPartialItemsRegistrationArgumentList(TypeSy ) ); - private static ObjectCreationExpressionSyntax CreateHandlerArgument(NameSyntax className, string innerClassName, params TypeSyntax[] genericArguments) => + public static ObjectCreationExpressionSyntax CreateHandlerArgument(NameSyntax className, string innerClassName, params TypeSyntax[] genericArguments) => ObjectCreationExpression( QualifiedName( className, @@ -383,10 +447,11 @@ private static ObjectCreationExpressionSyntax CreateHandlerArgument(NameSyntax c ) ); - public static ArrowExpressionClauseSyntax GetNotificationCapabilityHandlerExpression(ExpressionSyntax nameExpression, ITypeSymbol requestType, ITypeSymbol capability) + public static ObjectCreationExpressionSyntax CreateHandlerArgument(string innerClassName, params TypeSyntax[] genericArguments) => + ObjectCreationExpression(GenericName(innerClassName).WithTypeArgumentList(TypeArgumentList(SeparatedList(genericArguments)))); + + public static ArrowExpressionClauseSyntax GetNotificationCapabilityHandlerExpression(ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax capabilityName) { - var requestName = ResolveTypeName(requestType); - var capabilityName = ResolveTypeName(capability); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -397,70 +462,24 @@ public static ArrowExpressionClauseSyntax GetNotificationCapabilityHandlerExpres requestName, capabilityName ) - .WithArgumentList(GetHandlerArgumentList()) - ) - ) - ); - } - - public static BlockSyntax GetNotificationRegistrationHandlerExpression(ExpressionSyntax nameExpression, ITypeSymbol requestType, ITypeSymbol registrationOptions) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "Notification", - requestName, - registrationOptionsName - ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) - ) - ) - ); - } - - public static BlockSyntax GetNotificationRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, ITypeSymbol registrationOptions, - ITypeSymbol capability - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - var capabilityName = ResolveTypeName(capability); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "Notification", - requestName, + .AddArgumentListArguments( + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName })), + HandlerArgument, capabilityName, - registrationOptionsName + false ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) + ) ) ) ); } public static ArrowExpressionClauseSyntax GetRequestCapabilityHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - ITypeSymbol capability + ExpressionSyntax nameExpression, TypeSyntax requestType, TypeSyntax responseType, + TypeSyntax capability ) { - var requestName = ResolveTypeName(requestType); - var capabilityName = ResolveTypeName(capability); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -468,23 +487,28 @@ ITypeSymbol capability CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), "RequestCapability", - requestName, + requestType, responseType, - capabilityName + capability + ) + .AddArgumentListArguments( + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestType, responseType })), + HandlerArgument, + capability, + false + ) ) - .WithArgumentList(GetHandlerArgumentList()) ) ) ); } public static ArrowExpressionClauseSyntax GetVoidRequestCapabilityHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, - ITypeSymbol capability + ExpressionSyntax nameExpression, TypeSyntax requestType, + TypeSyntax capability ) { - var requestName = ResolveTypeName(requestType); - var capabilityName = ResolveTypeName(capability); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -492,118 +516,17 @@ ITypeSymbol capability CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), "RequestCapability", - requestName, - capabilityName + requestType, + capability ) - .WithArgumentList(GetHandlerArgumentList()) - ) - ) - ); - } - - public static BlockSyntax GetRequestRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - ITypeSymbol registrationOptions - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "RequestRegistration", - requestName, - responseType, - registrationOptionsName - ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) - ) - ) - ); - } - - public static BlockSyntax GetVoidRequestRegistrationHandlerExpression(ExpressionSyntax nameExpression, ITypeSymbol requestType, ITypeSymbol registrationOptions) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "RequestRegistration", - requestName, - registrationOptionsName - ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) - ) - ) - ); - } - - public static BlockSyntax GetRequestRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - ITypeSymbol registrationOptions, - ITypeSymbol capability - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - var capabilityName = ResolveTypeName(capability); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "Request", - requestName, - responseType, - capabilityName, - registrationOptionsName + .AddArgumentListArguments( + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestType })), + HandlerArgument, + capability, + false ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) - ) - ) - ); - } - - public static BlockSyntax GetVoidRequestRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, ITypeSymbol registrationOptions, - ITypeSymbol capability - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - var capabilityName = ResolveTypeName(capability); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "Request", - requestName, - capabilityName, - registrationOptionsName - ) - .WithArgumentList(GetRegistrationHandlerArgumentList(IdentifierName("registrationOptions"))) - ) + ) ) ) ); @@ -648,12 +571,10 @@ public static ArrowExpressionClauseSyntax GetRequestHandlerExpression(Expression } public static ArrowExpressionClauseSyntax GetPartialResultCapabilityHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax itemType, TypeSyntax responseType, - ITypeSymbol capability + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax itemType, TypeSyntax responseType, + TypeSyntax capabilityName ) { - var requestName = ResolveTypeName(requestType); - var capabilityName = ResolveTypeName(capability); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -662,47 +583,21 @@ ITypeSymbol capability Parameter( Identifier("_") ), - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResultCapability", - requestName, - responseType, - itemType, - capabilityName - ) - .WithArgumentList(GetPartialResultArgumentList(responseType)) - ) - ) - ) - ); - } - - public static BlockSyntax GetPartialResultRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax itemType, TypeSyntax responseType, - ITypeSymbol registrationOptions - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - SimpleLambdaExpression( - Parameter( - Identifier("_") - ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResult", + "PartialResultCapability", requestName, responseType, itemType, - registrationOptionsName + capabilityName ) - .WithArgumentList(GetPartialResultRegistrationArgumentList(IdentifierName("registrationOptions"), responseType)) + .AddArgumentListArguments( + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, itemType })), + HandlerArgument, + capabilityName, + true + ) ) ) ) @@ -710,45 +605,10 @@ ITypeSymbol registrationOptions ); } - public static BlockSyntax GetPartialResultRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax itemType, TypeSyntax responseType, - ITypeSymbol registrationOptions, - ITypeSymbol capability + public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression( + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax partialItem, TypeSyntax responseType ) { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - var capabilityName = ResolveTypeName(capability); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - SimpleLambdaExpression( - Parameter( - Identifier("_") - ), - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResult", - requestName, - responseType, - itemType, - capabilityName, - registrationOptionsName - ) - .WithArgumentList(GetPartialResultRegistrationArgumentList(IdentifierName("registrationOptions"), responseType)) - ) - ) - ) - ) - ); - } - - public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression(ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax partialItem, TypeSyntax responseType) - { - var requestName = ResolveTypeName(requestType); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -757,14 +617,14 @@ public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression(Expr Parameter( Identifier("_") ), - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResult", - requestName, - responseType, - partialItem - ) - .WithArgumentList(GetPartialResultArgumentList(responseType)) + CreateHandlerArgument( + IdentifierName("LanguageProtocolDelegatingHandlers"), + "PartialResult", + requestName, + responseType, + partialItem + ) + .WithArgumentList(GetPartialResultArgumentList(responseType, HandlerArgument)) ) ) ) @@ -772,12 +632,10 @@ public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression(Expr } public static ArrowExpressionClauseSyntax GetPartialResultsCapabilityHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - NameSyntax itemName, ITypeSymbol capability + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax responseType, + NameSyntax itemName, TypeSyntax capabilityName ) { - var requestName = ResolveTypeName(requestType); - var capabilityName = ResolveTypeName(capability); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -794,76 +652,14 @@ public static ArrowExpressionClauseSyntax GetPartialResultsCapabilityHandlerExpr itemName, capabilityName ) - .WithArgumentList(GetPartialItemsArgumentList(responseType)) - ) - ) - ) - ); - } - - public static BlockSyntax GetPartialResultsRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - NameSyntax itemName, ITypeSymbol registrationOptions - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - SimpleLambdaExpression( - Parameter( - Identifier("_") - ), - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResults", - requestName, - responseType, - itemName, - registrationOptionsName - ) - .WithArgumentList(GetPartialItemsRegistrationArgumentList(IdentifierName("registrationOptions"), responseType)) - ) - ) - ) - ) - ); - } - - public static BlockSyntax GetPartialResultsRegistrationHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, TypeSyntax responseType, - NameSyntax itemName, ITypeSymbol registrationOptions, - ITypeSymbol capability - ) - { - var requestName = ResolveTypeName(requestType); - var registrationOptionsName = ResolveTypeName(registrationOptions); - var capabilityName = ResolveTypeName(capability); - return Block( - EnsureRegistrationOptionsIsSet(IdentifierName("registrationOptions"), registrationOptionsName), - ReturnStatement( - AddHandler( - Argument(nameExpression), - Argument( - SimpleLambdaExpression( - Parameter( - Identifier("_") - ), - CreateHandlerArgument( - IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResults", - requestName, - responseType, - itemName, + .AddArgumentListArguments( + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, itemName })), + HandlerArgument, capabilityName, - registrationOptionsName + true ) - .WithArgumentList(GetPartialItemsRegistrationArgumentList(IdentifierName("registrationOptions"), responseType)) - ) + ) ) ) ) @@ -871,11 +667,10 @@ ITypeSymbol capability } public static ArrowExpressionClauseSyntax GetPartialResultsHandlerExpression( - ExpressionSyntax nameExpression, ITypeSymbol requestType, NameSyntax itemName, + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax itemName, TypeSyntax responseType ) { - var requestName = ResolveTypeName(requestType); return ArrowExpressionClause( AddHandler( Argument(nameExpression), @@ -891,7 +686,7 @@ TypeSyntax responseType responseType, itemName ) - .WithArgumentList(GetPartialItemsArgumentList(responseType)) + .WithArgumentList(GetPartialItemsArgumentList(responseType, HandlerArgument)) ) ) ) @@ -921,7 +716,7 @@ public static ArrowExpressionClauseSyntax GetNotificationHandlerExpression(Expre IdentifierName("For") ) ) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("handler"))))) + .WithArgumentList(ArgumentList(SingletonSeparatedList(HandlerArgument))) ) } ) @@ -929,7 +724,10 @@ public static ArrowExpressionClauseSyntax GetNotificationHandlerExpression(Expre ) ); - public static ArrowExpressionClauseSyntax GetRequestHandlerExpression(ExpressionSyntax nameExpression) => + public static ArrowExpressionClauseSyntax GetRequestHandlerExpression( + RequestItem item, + ExpressionSyntax nameExpression + ) => ArrowExpressionClause( InvocationExpression( MemberAccessExpression( @@ -940,19 +738,27 @@ public static ArrowExpressionClauseSyntax GetRequestHandlerExpression(Expression ) .WithArgumentList( ArgumentList( - SeparatedList( - new SyntaxNodeOrToken[] { + SeparatedList( + new[] { Argument(nameExpression), - Token(SyntaxKind.CommaToken), Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("RequestHandler"), - IdentifierName("For") + item.IsUnit + ? ObjectCreationExpression( + QualifiedName( + IdentifierName("DelegatingHandlers"), + GenericName(Identifier("Request")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.Request.Syntax))) + ) ) - ) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("handler"))))) + .WithArgumentList(ArgumentList(SingletonSeparatedList(HandlerArgument))) + : InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("RequestHandler"), + IdentifierName("For") + ) + ) + .WithArgumentList(ArgumentList(SingletonSeparatedList(HandlerArgument))) ) } ) @@ -973,7 +779,7 @@ public static ArrowExpressionClauseSyntax GetNotificationInvokeExpression() => ArgumentList( SeparatedList( new[] { - Argument(IdentifierName(@"@params")) + Argument(IdentifierName(@"request")) } ) ) @@ -993,7 +799,7 @@ public static ArrowExpressionClauseSyntax GetRequestInvokeExpression() => ArgumentList( SeparatedList( new[] { - Argument(IdentifierName(@"@params")), + Argument(IdentifierName(@"request")), Argument(IdentifierName("cancellationToken")) } ) @@ -1019,7 +825,7 @@ public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(TypeSyntax SeparatedList( new[] { Argument( - IdentifierName(@"@params") + IdentifierName(@"request") ), Argument( SimpleLambdaExpression( @@ -1039,16 +845,35 @@ public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(TypeSyntax private static string SpecialCasedHandlerFullName(INamedTypeSymbol symbol) { - if (symbol.IsGenericType) + var substringIndex = symbol.Name.LastIndexOf("Handler", StringComparison.Ordinal); + if (substringIndex is -1) { + substringIndex = symbol.Name.LastIndexOf("Params", StringComparison.Ordinal); } - return new Regex(@"(\w+(?:\<\w\>)?)$") - .Replace( - symbol.ToDisplayString(), - symbol.Name.Substring(1, symbol.Name.IndexOf("Handler", StringComparison.Ordinal) - 1) - ) - ; + if (substringIndex is -1) + { + substringIndex = symbol.Name.LastIndexOf("Arguments", StringComparison.Ordinal); + } + + if (substringIndex is -1) + { + substringIndex = symbol.Name.LastIndexOf("Event", StringComparison.Ordinal); + } + + if (substringIndex is -1) + { + substringIndex = symbol.Name.Length; + } + + var start = 0; + if (symbol.Name.StartsWith("I", StringComparison.Ordinal) && char.IsUpper(symbol.Name[1])) + { + start = 1; + substringIndex -= 1; + } + + return symbol.Name.Substring(start, substringIndex); } public static string SpecialCasedHandlerName(INamedTypeSymbol symbol) @@ -1057,49 +882,277 @@ public static string SpecialCasedHandlerName(INamedTypeSymbol symbol) return name.Substring(name.LastIndexOf('.') + 1); } - public static string GetOnMethodName(INamedTypeSymbol symbol, AttributeData attributeData) + public static TypeParameterConstraintSyntax HandlerIdentityConstraint { get; } = TypeConstraint(NullableType(IdentifierName("HandlerIdentity"))); + + public static SyntaxList HandlerIdentityConstraintClause(bool withHandlerIdentity, IdentifierNameSyntax? openGenericType = null) { - var namedMethod = attributeData.NamedArguments - .Where(z => z.Key == "MethodName") - .Select(z => z.Value.Value) - .FirstOrDefault(); - if (namedMethod is string value) return value; - return "On" + SpecialCasedHandlerName(symbol); + if (!withHandlerIdentity) + return SingletonList( + TypeParameterConstraintClause(openGenericType ?? IdentifierName("T")).WithConstraints( + SingletonSeparatedList( + ClassOrStructConstraint(SyntaxKind.ClassConstraint) + .WithQuestionToken(Token(SyntaxKind.QuestionToken)) + ) + ) + ); + return SingletonList( + TypeParameterConstraintClause(openGenericType ?? IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(HandlerIdentityConstraint)) + ); } - public static string GetSendMethodName(INamedTypeSymbol symbol, AttributeData attributeData) + public static LocalDeclarationStatementSyntax NewGuid { get; } = LocalDeclarationStatement( + VariableDeclaration(IdentifierName("var")) + .WithVariables( + SingletonSeparatedList( + VariableDeclarator(Identifier("id")) + .WithInitializer( + EqualsValueClause( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Guid"), IdentifierName("NewGuid")) + ) + ) + ) + ) + ) + ); + } + + public static class LazyFactory + { + public static Lazy Create(Func func) => new(func); + } + + public static class CommonElements + { + public static AccessorListSyntax GetSetAccessor => GetSetAccessorLazy.Value; + + private static readonly Lazy GetSetAccessorLazy = LazyFactory.Create( + () => AccessorList( + List( + new[] { + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + } + ) + ) + ); + + private static readonly Lazy GetInitAccessorLazy = LazyFactory.Create( + () => AccessorList( + List( + new[] { + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + AccessorDeclaration(SyntaxKind.InitAccessorDeclaration) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + } + ) + ) + ); + + public static AccessorListSyntax GetInitAccessor => GetInitAccessorLazy.Value; + + private static readonly Lazy GetAccessorLazy = LazyFactory.Create( + () => AccessorList( + List( + new[] { + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + } + ) + ) + ); + + public static AccessorListSyntax GetAccessor => GetAccessorLazy.Value; + } + + public static class SyntaxExtensions + { + public static TypeSyntax EnsureNullable(this TypeSyntax typeSyntax) => typeSyntax is NullableTypeSyntax nts ? nts : NullableType(typeSyntax); + public static TypeSyntax EnsureNotNullable(this TypeSyntax typeSyntax) => typeSyntax is NullableTypeSyntax nts ? nts.ElementType : typeSyntax; + + public static string? GetSyntaxName(this TypeSyntax typeSyntax) { - var namedMethod = attributeData.NamedArguments - .Where(z => z.Key == "MethodName") - .Select(z => z.Value.Value) - .FirstOrDefault(); - if (namedMethod is string value) return value; - var name = SpecialCasedHandlerName(symbol); - if ( - name.StartsWith("Run") - || name.StartsWith("Execute") - // TODO: Change this next breaking change - // || name.StartsWith("Set") - // || name.StartsWith("Attach") - // || name.StartsWith("Read") - || name.StartsWith("Did") - || name.StartsWith("Log") - || name.StartsWith("Show") - || name.StartsWith("Register") - || name.StartsWith("Prepare") - || name.StartsWith("Publish") - || name.StartsWith("ApplyWorkspaceEdit") - || name.StartsWith("Unregister")) + return typeSyntax switch { + SimpleNameSyntax sns => sns.Identifier.Text, + QualifiedNameSyntax qns => qns.Right.Identifier.Text, + NullableTypeSyntax nts => nts.ElementType.GetSyntaxName() + "?", + PredefinedTypeSyntax pts => pts.Keyword.Text, + ArrayTypeSyntax ats => ats.ElementType.GetSyntaxName() + "[]", + TupleTypeSyntax tts => "(" + tts.Elements.Select(z => $"{z.Type.GetSyntaxName()}{z.Identifier.Text}") + ")", + _ => null// there might be more but for now... throw new NotSupportedException(typeSyntax.GetType().FullName) + }; + } + + private static readonly ConcurrentDictionary> AttributeNames = new(); + + private static HashSet GetNames(string attributePrefixes) + { + if (!AttributeNames.TryGetValue(attributePrefixes, out var names)) { - return name; + names = new HashSet(attributePrefixes.Split(',').SelectMany(z => new[] { z, z + "Attribute" })); + AttributeNames.TryAdd(attributePrefixes, names); } - if (name.EndsWith("Resolve", StringComparison.Ordinal)) + return names; + } + + public static bool ContainsAttribute(this AttributeListSyntax list, string attributePrefixes) // string is comma separated + { + if (list is { Attributes: { Count: 0 } }) return false; + var names = GetNames(attributePrefixes); + + foreach (var item in list.Attributes) { - return "Resolve" + name.Substring(0, name.IndexOf("Resolve", StringComparison.Ordinal)); + if (item.Name.GetSyntaxName() is { } n && names.Contains(n)) return true; } - return IsNotification(symbol) ? "Send" + name : "Request" + name; + return false; + } + + public static bool ContainsAttribute(this in SyntaxList list, string attributePrefixes) // string is comma separated + { + if (list is { Count: 0 }) return false; + var names = GetNames(attributePrefixes); + + foreach (var item in list) + { + foreach (var attribute in item.Attributes) + { + if (attribute.Name.GetSyntaxName() is { } n && names.Contains(n)) return true; + } + } + + return false; + } + + public static AttributeSyntax? GetAttribute(this AttributeListSyntax list, string attributePrefixes) // string is comma separated + { + if (list is { Attributes: { Count: 0 } }) return null; + var names = GetNames(attributePrefixes); + + foreach (var item in list.Attributes) + { + if (item.Name.GetSyntaxName() is { } n && names.Contains(n)) return item; + } + + return null; + } + + public static AttributeSyntax? GetAttribute(this in SyntaxList list, string attributePrefixes) // string is comma separated + { + if (list is { Count: 0 }) return null; + var names = GetNames(attributePrefixes); + + foreach (var item in list) + { + foreach (var attribute in item.Attributes) + { + if (attribute.Name.GetSyntaxName() is { } n && names.Contains(n)) return attribute; + } + } + + return null; + } + + public static bool IsAttribute(this AttributeSyntax attributeSyntax, string attributePrefixes) // string is comma separated + { + var names = GetNames(attributePrefixes); + return attributeSyntax.Name.GetSyntaxName() is { } n && names.Contains(n); + } + + public static BaseMethodDeclarationSyntax MakeMethodNullable(this BaseMethodDeclarationSyntax syntax, IdentifierNameSyntax identifierNameSyntax) + { + if (syntax is MethodDeclarationSyntax mds) + { + syntax = mds.WithReturnType(mds.ReturnType.EnsureNullable()); + } + + if (syntax is ConversionOperatorDeclarationSyntax cods) + { + syntax = cods.WithType(cods.Type.EnsureNullable()); + } + + if (syntax.ExpressionBody is not null) + { + syntax = syntax.WithExpressionBody(syntax.ExpressionBody.WithExpression(syntax.ExpressionBody.Expression.InsideNullableSwitchExpression(identifierNameSyntax))); + } + + return syntax + .WithParameterList( + ParameterList(SeparatedList(syntax.ParameterList.Parameters.Select(parameter => parameter.WithType(parameter.Type?.EnsureNullable())).ToArray())) + ) + .AddAttributeLists( + AttributeList( + SingletonSeparatedList( + Attribute( + QualifiedName( + QualifiedName(QualifiedName(IdentifierName("System"), IdentifierName("Diagnostics")), IdentifierName("CodeAnalysis")), + IdentifierName("NotNullIfNotNull") + ) + ) + .WithArgumentList( + AttributeArgumentList( + SingletonSeparatedList( + AttributeArgument( + LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(identifierNameSyntax.Identifier.Text) + ) + ) + ) + ) + ) + ) + ) + .WithTarget(AttributeTargetSpecifier(Token(SyntaxKind.ReturnKeyword))) + ); + } + + public static MethodDeclarationSyntax MakeMethodNullable(this MethodDeclarationSyntax syntax, IdentifierNameSyntax identifierNameSyntax) + { + return ( MakeMethodNullable(syntax as BaseMethodDeclarationSyntax, identifierNameSyntax) as MethodDeclarationSyntax )!; + } + + public static ConversionOperatorDeclarationSyntax MakeMethodNullable(this ConversionOperatorDeclarationSyntax syntax, IdentifierNameSyntax identifierNameSyntax) + { + return ( MakeMethodNullable(syntax as BaseMethodDeclarationSyntax, identifierNameSyntax) as ConversionOperatorDeclarationSyntax )!; + } + + public static SwitchExpressionSyntax InsideNullableSwitchExpression(this ExpressionSyntax creationExpression, IdentifierNameSyntax name) + { + return SwitchExpression(name) + .WithArms( + SeparatedList( + new[] { + SwitchExpressionArm( + UnaryPattern(ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression))), + creationExpression + ), + SwitchExpressionArm(DiscardPattern(), LiteralExpression(SyntaxKind.NullLiteralExpression)) + } + ) + ); + } + + public static ClassDeclarationSyntax WithHandlerIdentityConstraint( + this ClassDeclarationSyntax syntax, bool includeHandlerIdentity, IdentifierNameSyntax? openGenericType = null + ) + { + openGenericType ??= IdentifierName("T"); + return syntax + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(openGenericType.Identifier.Text)))) + .WithConstraintClauses(Helpers.HandlerIdentityConstraintClause(includeHandlerIdentity, openGenericType)); + } + + public static MethodDeclarationSyntax WithHandlerIdentityConstraint( + this MethodDeclarationSyntax syntax, bool includeHandlerIdentity, IdentifierNameSyntax? openGenericType = null + ) + { + openGenericType ??= IdentifierName("T"); + return syntax + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(openGenericType.Identifier.Text)))) + .WithConstraintClauses(Helpers.HandlerIdentityConstraintClause(includeHandlerIdentity, openGenericType)); } } } diff --git a/src/JsonRpc.Generators/ICompilationUnitGeneratorStrategy.cs b/src/JsonRpc.Generators/ICompilationUnitGeneratorStrategy.cs new file mode 100644 index 000000000..c3a147903 --- /dev/null +++ b/src/JsonRpc.Generators/ICompilationUnitGeneratorStrategy.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + internal interface ICompilationUnitGeneratorStrategy + { + IEnumerable Apply(GeneratorData item); + } +} diff --git a/src/JsonRpc.Generators/IExtensionMethodContextGeneratorStrategy.cs b/src/JsonRpc.Generators/IExtensionMethodContextGeneratorStrategy.cs new file mode 100644 index 000000000..7160e8285 --- /dev/null +++ b/src/JsonRpc.Generators/IExtensionMethodContextGeneratorStrategy.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + internal interface IExtensionMethodContextGeneratorStrategy + { + IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item); + } +} diff --git a/src/JsonRpc.Generators/IExtensionMethodGeneratorStrategy.cs b/src/JsonRpc.Generators/IExtensionMethodGeneratorStrategy.cs new file mode 100644 index 000000000..c1bf09b8b --- /dev/null +++ b/src/JsonRpc.Generators/IExtensionMethodGeneratorStrategy.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + internal interface IExtensionMethodGeneratorStrategy + { + IEnumerable Apply(GeneratorData item); + } +} diff --git a/src/JsonRpc.Generators/Records.cs b/src/JsonRpc.Generators/Records.cs new file mode 100644 index 000000000..66cef4915 --- /dev/null +++ b/src/JsonRpc.Generators/Records.cs @@ -0,0 +1,23 @@ +#pragma warning disable MA0048 // File name must match type name +#define INTERNAL_RECORD_ATTRIBUTES +#if NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NET45 || NET451 || NET452 || NET6 || NET461 || NET462 || NET47 || NET471 || NET472 || NET48 +using System.ComponentModel; + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] +#if INTERNAL_RECORD_ATTRIBUTES + internal +#else + public +#endif + static class IsExternalInit + { + } +} +#endif diff --git a/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs b/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs index 90bb604e8..b23e5a134 100644 --- a/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs +++ b/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs @@ -1,155 +1,199 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using SyntaxTrivia = Microsoft.CodeAnalysis.SyntaxTrivia; namespace OmniSharp.Extensions.JsonRpc.Generators { [Generator] - public class RegistrationOptionsGenerator : ISourceGenerator + public class RegistrationOptionsGenerator : CachedSourceGenerator { private static string[] RequiredUsings = new[] { - "OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities", "OmniSharp.Extensions.LanguageServer.Protocol", + "OmniSharp.Extensions.LanguageServer.Protocol.Serialization", + "OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities", }; - public void Initialize(GeneratorInitializationContext context) - { - context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); - } - - public void Execute(GeneratorExecutionContext context) + protected override void Execute(GeneratorExecutionContext context, SyntaxReceiver syntaxReceiver, AddCacheSource addCacheSource, ReportCacheDiagnostic cacheDiagnostic) { - if (!( context.SyntaxReceiver is SyntaxReceiver syntaxReceiver )) - { - return; - } - var options = ( context.Compilation as CSharpCompilation )?.SyntaxTrees[0].Options as CSharpParseOptions; var compilation = context.Compilation; - var registrationOptionsAttribute = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.RegistrationOptionsAttribute")!; - var textDocumentAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.TextDocumentAttribute")!; - var workDoneProgressAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.WorkDoneProgressAttribute")!; - var registrationOptionsConverterAttributeSymbol = - compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.RegistrationOptionsConverterAttribute")!; var registrationOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions")!; var textDocumentRegistrationOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions")!; var workDoneProgressOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions")!; + // TODO: + var staticRegistrationOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.IStaticRegistrationOptions")!; foreach (var registrationOptions in syntaxReceiver.RegistrationOptions) { - var semanticModel = context.Compilation.GetSemanticModel(registrationOptions.SyntaxTree); - var typeSymbol = semanticModel.GetDeclaredSymbol(registrationOptions); - var hasAttribute = typeSymbol?.GetAttributes().Any(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, registrationOptionsAttribute)); - if (typeSymbol == null || typeSymbol.IsAbstract || hasAttribute != true) continue; - - var converterAttribute = typeSymbol.GetAttributes() - .FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, registrationOptionsConverterAttributeSymbol)); - - var extendedRegistrationOptions = registrationOptions - .WithAttributeLists(List()) - .WithBaseList( - BaseList( - SingletonSeparatedList( - SimpleBaseType(ParseName(registrationOptionsInterfaceSymbol.ToDisplayString())) + try + { + var semanticModel = context.Compilation.GetSemanticModel(registrationOptions.SyntaxTree); + var typeSymbol = semanticModel.GetDeclaredSymbol(registrationOptions); + + if (typeSymbol is not { }) continue; + var data = RegistrationOptionAttributes.Parse(context, registrationOptions, typeSymbol); + if (data is not { }) continue; + + if (!registrationOptions.Modifiers.Any(z => z.IsKind(SyntaxKind.PartialKeyword))) + { + cacheDiagnostic(registrationOptions, static r => Diagnostic.Create(GeneratorDiagnostics.MustBePartial, r.Identifier.GetLocation(), r.Identifier.Text)); + continue; + } + + var extendedRegistrationOptions = registrationOptions + .WithAttributeLists(List()) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType(ParseName(registrationOptionsInterfaceSymbol.ToDisplayString())) + ) ) ) - ) - .WithMembers(List()); + .WithMembers(List()); - var staticRegistrationOptions = registrationOptions - .WithIdentifier(Identifier($"Static{registrationOptions.Identifier.Text}")) - .WithMembers(List(registrationOptions.Members.OfType())) - .WithAttributeLists(List()); - if (typeSymbol.GetAttributes().Any(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, textDocumentAttributeSymbol))) - { - extendedRegistrationOptions = ExtendAndImplementInterface(extendedRegistrationOptions, textDocumentRegistrationOptionsInterfaceSymbol) - .AddMembers( - PropertyDeclaration(NullableType(IdentifierName("DocumentSelector")), Identifier("DocumentSelector")) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) - .WithAccessorList( - AccessorList( - List( - new[] { - AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - } + var staticRegistrationOptions = registrationOptions + .WithIdentifier(Identifier($"StaticOptions")) + .WithMembers(List(registrationOptions.Members.OfType())) + .WithAttributeLists(List()); + + var staticBaseList = + registrationOptions.BaseList?.Types.Where(z => z.Type.GetSyntaxName() != textDocumentRegistrationOptionsInterfaceSymbol.Name).ToArray() + ?? Array.Empty(); + if (staticBaseList.Length > 0) + { + staticRegistrationOptions = staticRegistrationOptions.WithBaseList(BaseList(SeparatedList(staticBaseList))); + } + else + { + staticRegistrationOptions = staticRegistrationOptions.WithBaseList(null); + } + + if (data.SupportsDocumentSelector && !data.ImplementsDocumentSelector) + { + if (registrationOptions.BaseList?.Types.Any(z => z.Type.ToFullString().Contains(textDocumentRegistrationOptionsInterfaceSymbol.Name)) != true) + { + extendedRegistrationOptions = ExtendAndImplementInterface(extendedRegistrationOptions, textDocumentRegistrationOptionsInterfaceSymbol); + } + + extendedRegistrationOptions = extendedRegistrationOptions + .AddMembers( + PropertyDeclaration(NullableType(IdentifierName("DocumentSelector")), Identifier("DocumentSelector")) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithAccessorList( + AccessorList( + List( + new[] { + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + } + ) ) ) - ) - ); - } + ); + } - if (typeSymbol.GetAttributes().Any(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, workDoneProgressAttributeSymbol))) - { - extendedRegistrationOptions = ExtendAndImplementInterface(extendedRegistrationOptions, workDoneProgressOptionsInterfaceSymbol) - .AddMembers(GetWorkDoneProperty()); - staticRegistrationOptions = ExtendAndImplementInterface(staticRegistrationOptions, workDoneProgressOptionsInterfaceSymbol) - .AddMembers(GetWorkDoneProperty()); - } + if (data.SupportsWorkDoneProgress && !data.ImplementsWorkDoneProgress) + { + if (registrationOptions.BaseList?.Types.Any(z => z.Type.GetSyntaxName() == workDoneProgressOptionsInterfaceSymbol.Name) != true) + { + extendedRegistrationOptions = ExtendAndImplementInterface(extendedRegistrationOptions, workDoneProgressOptionsInterfaceSymbol); + staticRegistrationOptions = ExtendAndImplementInterface(staticRegistrationOptions, workDoneProgressOptionsInterfaceSymbol); + } - if (converterAttribute == null) - { - var converter = CreateConverter(registrationOptions); - extendedRegistrationOptions = extendedRegistrationOptions - .AddAttributeLists( - AttributeList( - SingletonSeparatedList( - Attribute( - IdentifierName("RegistrationOptionsConverterAttribute"), - AttributeArgumentList( - SingletonSeparatedList( - AttributeArgument( - TypeOfExpression(IdentifierName(converter.Identifier.Text)) + staticRegistrationOptions = staticRegistrationOptions.AddMembers(GetWorkDoneProperty()); + extendedRegistrationOptions = extendedRegistrationOptions.AddMembers(GetWorkDoneProperty()); + } + + if (data.SupportsStaticRegistrationOptions && !data.ImplementsStaticRegistrationOptions) + { + if (registrationOptions.BaseList?.Types.Any(z => z.Type.GetSyntaxName() == staticRegistrationOptionsInterfaceSymbol.Name) != true) + { + extendedRegistrationOptions = ExtendAndImplementInterface(extendedRegistrationOptions, staticRegistrationOptionsInterfaceSymbol); + staticRegistrationOptions = ExtendAndImplementInterface(staticRegistrationOptions, staticRegistrationOptionsInterfaceSymbol); + } + + staticRegistrationOptions = staticRegistrationOptions.AddMembers(GetIdProperty()); + extendedRegistrationOptions = extendedRegistrationOptions.AddMembers(GetIdProperty()); + } + + if (data.RegistrationOptionsConverter is null + && CreateConverter(registrationOptions, staticRegistrationOptions.Members.OfType()) is { } converter) + { + extendedRegistrationOptions = extendedRegistrationOptions + .AddAttributeLists( + AttributeList( + SingletonSeparatedList( + Attribute( + IdentifierName("RegistrationOptionsConverterAttribute"), + AttributeArgumentList( + SingletonSeparatedList( + AttributeArgument( + TypeOfExpression(IdentifierName(converter.Identifier.Text)) + ) ) ) ) ) ) ) - ) - .AddMembers(converter); - } + .AddMembers(converter); + } - var cu = CompilationUnit() - .WithUsings(registrationOptions.SyntaxTree.GetCompilationUnitRoot().Usings) - .AddMembers( - NamespaceDeclaration(ParseName(typeSymbol.ContainingNamespace.ToDisplayString())) - .AddMembers(extendedRegistrationOptions, staticRegistrationOptions) - .WithLeadingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)))) - .WithTrailingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)))) - ) - .WithLeadingTrivia(Comment(Preamble.GeneratedByATool)) - .WithTrailingTrivia(CarriageReturnLineFeed); - - foreach (var ns in RequiredUsings) - { - if (cu.Usings.All(z => z.Name.ToFullString() != ns)) + extendedRegistrationOptions = extendedRegistrationOptions.AddMembers(staticRegistrationOptions); + + var members = new List() { extendedRegistrationOptions }; + + var cu = CompilationUnit() + .WithUsings(registrationOptions.SyntaxTree.GetCompilationUnitRoot().Usings) + .AddMembers( + NamespaceDeclaration(ParseName(typeSymbol.ContainingNamespace.ToDisplayString())) + .WithMembers(List(members)) + .WithLeadingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)))) + .WithTrailingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)))) + ) + .WithLeadingTrivia(Comment(Preamble.GeneratedByATool)) + .WithTrailingTrivia(CarriageReturnLineFeed); + + foreach (var ns in RequiredUsings) { - cu = cu.AddUsings(UsingDirective(ParseName(ns))); + if (cu.Usings.All(z => z.Name.ToFullString() != ns)) + { + cu = cu.AddUsings(UsingDirective(ParseName(ns))); + } } - } - context.AddSource( - $"{registrationOptions.Identifier.Text}Container.cs", - cu.NormalizeWhitespace().SyntaxTree.GetRoot().GetText(Encoding.UTF8) - ); + addCacheSource( + $"{registrationOptions.Identifier.Text}.cs", + registrationOptions, + cu.NormalizeWhitespace().GetText(Encoding.UTF8) + ); + } + catch (Exception e) + { + context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.Exception, registrationOptions.GetLocation(), e.Message, e.StackTrace ?? string.Empty)); + Debug.WriteLine(e); + Debug.WriteLine(e.StackTrace); + } } static ClassDeclarationSyntax ExtendAndImplementInterface(ClassDeclarationSyntax syntax, ITypeSymbol symbolToExtendFrom) { return syntax - .AddBaseListTypes(SimpleBaseType(ParseName(symbolToExtendFrom.Name))); + .AddBaseListTypes(SimpleBaseType(ParseName(symbolToExtendFrom.ToDisplayString()))); } static PropertyDeclarationSyntax GetWorkDoneProperty() @@ -174,30 +218,56 @@ static PropertyDeclarationSyntax GetWorkDoneProperty() ) ); } + + static PropertyDeclarationSyntax GetIdProperty() + { + return PropertyDeclaration(NullableType(PredefinedType(Token(SyntaxKind.StringKeyword))), Identifier("Id")) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithAttributeLists( + SingletonList( + AttributeList( + SingletonSeparatedList(Attribute(IdentifierName("Optional"))) + ) + ) + ) + .WithAccessorList( + AccessorList( + List( + new[] { + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + } + ) + ) + ); + } } - private static IEnumerable GetMapping(ClassDeclarationSyntax syntax, IdentifierNameSyntax paramName) + private static IEnumerable GetMapping(IEnumerable properties, IdentifierNameSyntax paramName) { - return syntax.Members.OfType() - .Where(z => z.AccessorList?.Accessors.Any(a => a.Keyword.Kind() == SyntaxKind.SetKeyword || a.Keyword.Kind() == SyntaxKind.InitKeyword) == true) - .Select( - property => AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(property.Identifier.Text), - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - paramName, - IdentifierName(property.Identifier.Text) - ) - ) - ); + return properties + .Where(z => z.AccessorList?.Accessors.Any(a => a.Keyword.Kind() == SyntaxKind.SetKeyword || a.Keyword.Kind() == SyntaxKind.InitKeyword) == true) + .Select( + property => AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(property.Identifier.Text), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + paramName, + IdentifierName(property.Identifier.Text) + ) + ) + ); } - private ClassDeclarationSyntax CreateConverter(ClassDeclarationSyntax syntax) + private ClassDeclarationSyntax? CreateConverter(ClassDeclarationSyntax syntax, IEnumerable properties) { var attribute = syntax.AttributeLists .SelectMany(z => z.Attributes) - .FirstOrDefault(z => z.Name.ToFullString().Contains("RegistrationOptions") && !z.Name.ToFullString().Contains("RegistrationOptionsConverter")); + .FirstOrDefault(z => z.IsAttribute("GenerateRegistrationOptions") && !z.IsAttribute("RegistrationOptionsConverter")); + + var expression = attribute is { ArgumentList: { Arguments: { Count: > 0 } arguments } } ? arguments[0].Expression : null; + if (expression is null) return null; return ClassDeclaration($"{syntax.Identifier.Text}Converter") .WithBaseList( @@ -207,11 +277,10 @@ private ClassDeclarationSyntax CreateConverter(ClassDeclarationSyntax syntax) GenericName(Identifier("RegistrationOptionsConverterBase")) .WithTypeArgumentList( TypeArgumentList( - SeparatedList( - new SyntaxNodeOrToken[] { + SeparatedList( + new TypeSyntax[] { IdentifierName(syntax.Identifier.Text), - Token(SyntaxKind.CommaToken), - IdentifierName($"Static{syntax.Identifier.Text}") + IdentifierName("StaticOptions") } ) ) @@ -223,16 +292,16 @@ private ClassDeclarationSyntax CreateConverter(ClassDeclarationSyntax syntax) .WithMembers( List( new MemberDeclarationSyntax[] { - ConstructorDeclaration(Identifier("Converter")) + ConstructorDeclaration(Identifier($"{syntax.Identifier.Text}Converter")) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithInitializer( ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, - ArgumentList(SingletonSeparatedList(Argument(attribute!.ArgumentList!.Arguments[0].Expression))) + ArgumentList(SingletonSeparatedList(Argument(expression))) ) ) .WithBody(Block()), - MethodDeclaration(IdentifierName($"Static{syntax.Identifier.Text}"), Identifier("Convert")) + MethodDeclaration(IdentifierName("StaticOptions"), Identifier("Convert")) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.OverrideKeyword))) .WithParameterList( ParameterList( @@ -247,13 +316,13 @@ private ClassDeclarationSyntax CreateConverter(ClassDeclarationSyntax syntax) SingletonList( ReturnStatement( ObjectCreationExpression( - IdentifierName($"Static{syntax.Identifier.Text}") + IdentifierName("StaticOptions") ) .WithInitializer( InitializerExpression( SyntaxKind.ObjectInitializerExpression, SeparatedList( - GetMapping(syntax, IdentifierName("source")).ToArray() + GetMapping(properties, IdentifierName("source")).ToArray() ) ) ) @@ -266,30 +335,46 @@ private ClassDeclarationSyntax CreateConverter(ClassDeclarationSyntax syntax) ); } - /// - /// Created on demand before each generation pass - /// - internal class SyntaxReceiver : ISyntaxReceiver + public RegistrationOptionsGenerator() : base(() => new SyntaxReceiver(Cache)) + { + + } + public static CacheContainer Cache = new(); + + public class SyntaxReceiver : SyntaxReceiverCache { public List RegistrationOptions { get; } = new(); + public override string? GetKey(ClassDeclarationSyntax syntax) + { + var hasher = new CacheKeyHasher(); + hasher.Append(syntax.SyntaxTree.FilePath); + hasher.Append(syntax.Identifier.Text); + hasher.Append(syntax.TypeParameterList); + hasher.Append(syntax.AttributeLists); + hasher.Append(syntax.BaseList); + foreach (var item in syntax.Members.OfType().Select(z => z.Identifier.Text)) + { + hasher.Append(item); + } + return hasher; + } + /// /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation /// - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + public override void OnVisitNode(ClassDeclarationSyntax syntaxNode) { - // any field with at least one attribute is a candidate for property generation - if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax) + if (syntaxNode.AttributeLists + .SelectMany(z => z.Attributes) + .Any(z => z.Name.ToFullString().Contains("GenerateRegistrationOptions")) + ) { - if (classDeclarationSyntax.AttributeLists - .SelectMany(z => z.Attributes) - .Any(z => z.Name.ToFullString().Contains("RegistrationOptions")) - ) - { - RegistrationOptions.Add(classDeclarationSyntax); - } + RegistrationOptions.Add(syntaxNode); } } + + public SyntaxReceiver(CacheContainer cache) : base(cache) { } } } } diff --git a/src/JsonRpc.Generators/Strategies/EnsureNamespaceStrategy.cs b/src/JsonRpc.Generators/Strategies/EnsureNamespaceStrategy.cs new file mode 100644 index 000000000..50ee19788 --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/EnsureNamespaceStrategy.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class EnsureNamespaceStrategy : IExtensionMethodGeneratorStrategy + { + public IEnumerable Apply(GeneratorData item) + { + if (item.Capability != null) item.AdditionalUsings.Add(item.Capability.Symbol.ContainingNamespace.ToDisplayString()); + if (item.RegistrationOptions != null) item.AdditionalUsings.Add(item.RegistrationOptions.Symbol.ContainingNamespace.ToDisplayString()); + if (item is RequestItem requestItem) + { + if (requestItem.PartialItem != null) item.AdditionalUsings.Add(requestItem.PartialItem.Symbol.ContainingNamespace.ToDisplayString()); + if (requestItem.PartialItems != null) item.AdditionalUsings.Add(requestItem.PartialItems.Symbol.ContainingNamespace.ToDisplayString()); + } + + yield break; + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/ExtensionMethodGeneratorStrategy.cs b/src/JsonRpc.Generators/Strategies/ExtensionMethodGeneratorStrategy.cs new file mode 100644 index 000000000..eef6dfb57 --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/ExtensionMethodGeneratorStrategy.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class ExtensionMethodGeneratorStrategy : ICompilationUnitGeneratorStrategy + { + private readonly ImmutableArray _extensionMethodGeneratorStrategies; + + public ExtensionMethodGeneratorStrategy(ImmutableArray extensionMethodGeneratorStrategies) + { + _extensionMethodGeneratorStrategies = extensionMethodGeneratorStrategies; + } + public IEnumerable Apply(GeneratorData item) + { + var methods = _extensionMethodGeneratorStrategies.Aggregate( + new List(), (m, strategy) => { + try + { + m.AddRange(strategy.Apply(item)); + } + catch (Exception e) + { + Debug.WriteLine($"Strategy {strategy.GetType().FullName} failed!"); + Debug.WriteLine(e); + Debug.WriteLine(e.StackTrace); + } + + return m; + } + ); + + var className = item.JsonRpcAttributes.HandlerName + "Extensions"; + + var obsoleteAttribute = item.TypeDeclaration.AttributeLists + .SelectMany(z => z.Attributes) + .Where(z => z.IsAttribute("Obsolete")) + .ToArray(); + + var attributes = List( + new[] { + AttributeList( + SeparatedList( + new[] { + Attribute(ParseName("System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute")), + Attribute(ParseName("System.Runtime.CompilerServices.CompilerGeneratedAttribute")), + }.Union(obsoleteAttribute) + ) + ) + } + ); + + if (methods.Count == 0) yield break; + + yield return NamespaceDeclaration(ParseName(item.JsonRpcAttributes.HandlerNamespace)) + .WithMembers( + SingletonList( + ClassDeclaration(className) + .WithAttributeLists(attributes) + .WithModifiers( + TokenList( + new [] { + Token(item.TypeSymbol.DeclaredAccessibility == Accessibility.Public ? SyntaxKind.PublicKeyword : SyntaxKind.InternalKeyword), + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.PartialKeyword) + } + ) + ) + .WithMembers(List(methods)) + .WithLeadingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)))) + .WithTrailingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)))) + ) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs b/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs new file mode 100644 index 000000000..85f3904d1 --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs @@ -0,0 +1,1095 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.Mail; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class HandlerGeneratorStrategy : ICompilationUnitGeneratorStrategy + { + public IEnumerable Apply(GeneratorData item) + { + if (item.JsonRpcAttributes.GenerateHandler is not { }) yield break; + var members = new List(); + + var resolver = GeneratorData.CreateForResolver(item); + + var attributesToCopy = AttributeList( + SeparatedList( + item.TypeDeclaration.AttributeLists + .SelectMany(z => z.Attributes.Where(AttributeFilter)) + ) + ); + + var handlerInterface = InterfaceDeclaration(Identifier($"I{item.JsonRpcAttributes.HandlerName}Handler")) + .WithAttributeLists( + List( + new[] { + attributesToCopy, + AttributeList(SingletonSeparatedList(Attribute(ParseName("System.Runtime.CompilerServices.CompilerGeneratedAttribute")))) + } + ) + ) + .WithModifiers(item.TypeDeclaration.Modifiers) + .AddBaseListTypes(SimpleBaseType(GetBaseHandlerInterface(item))); + + if (!handlerInterface.Modifiers.Any(z => z.IsKind(SyntaxKind.PartialKeyword))) + { + handlerInterface = handlerInterface.AddModifiers(Token(SyntaxKind.PartialKeyword)); + } + + if (item.JsonRpcAttributes.AllowDerivedRequests) + { + handlerInterface = handlerInterface + .WithTypeParameterList( + TypeParameterList( + SingletonSeparatedList( + TypeParameter(Identifier("T")).WithVarianceKeyword(Token(SyntaxKind.InKeyword)) + ) + ) + ) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints( + SingletonSeparatedList( + TypeConstraint(item.Request.Syntax) + ) + ) + ) + ); + + members.Add( + InterfaceDeclaration(handlerInterface.Identifier) + .WithModifiers(handlerInterface.Modifiers) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType(GenericName(handlerInterface.Identifier.Text).AddTypeArgumentListArguments(item.Request.Syntax)) + ) + ) + ) + ); + } + + if (GetRegistrationAndOrCapability(item) is { } registrationAndOrCapability) + { + handlerInterface = handlerInterface.AddBaseListTypes(SimpleBaseType(registrationAndOrCapability)); + } + + var classAttributes = + SingletonList( + AttributeList( + SeparatedList( + new[] { + Attribute(ParseName("System.Runtime.CompilerServices.CompilerGeneratedAttribute")), + Attribute(ParseName("System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute")), + }.Concat( + attributesToCopy.Attributes + .Where(z => z.IsAttribute("Obsolete")) + ).ToArray() + ) + ) + ); + + { + var baseClass = GetBaseHandlerClass(item); + var handlerClass = ClassDeclaration(Identifier($"{item.JsonRpcAttributes.HandlerName}HandlerBase")) + .WithAttributeLists(classAttributes) + .AddModifiers(Token(SyntaxKind.AbstractKeyword)) + .AddModifiers(handlerInterface.Modifiers.ToArray()); + if (item.JsonRpcAttributes.AllowDerivedRequests) + { + handlerClass = handlerClass + .WithTypeParameterList( + TypeParameterList( + SingletonSeparatedList( + TypeParameter(Identifier("T")) + ) + ) + ) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints( + SingletonSeparatedList( + TypeConstraint(item.Request.Syntax) + ) + ) + ) + ); + + members.Add( + ClassDeclaration(handlerClass.Identifier) + .WithAttributeLists(handlerClass.AttributeLists) + .AddModifiers(Token(SyntaxKind.AbstractKeyword)) + .AddModifiers(handlerInterface.Modifiers.ToArray()) + .WithBaseList( + BaseList( + SeparatedList( + new[] { + SimpleBaseType(GenericName(handlerClass.Identifier.Text).AddTypeArgumentListArguments(item.Request.Syntax)), + SimpleBaseType(IdentifierName(handlerInterface.Identifier.Text)), + } + ) + ) + ) + ); + } + + if (baseClass is { }) + { + handlerClass = handlerClass.AddBaseListTypes(SimpleBaseType(baseClass)); + } + + if (item.JsonRpcAttributes.AllowDerivedRequests) + { + handlerClass = handlerClass.AddBaseListTypes( + SimpleBaseType( + GenericName($"I{item.JsonRpcAttributes.HandlerName}Handler") + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) + ) + ); + } + else + { + handlerClass = handlerClass.AddBaseListTypes(SimpleBaseType(IdentifierName($"I{item.JsonRpcAttributes.HandlerName}Handler"))); + } + + if (resolver is { }) + { + handlerClass = handlerClass + .AddBaseListTypes(SimpleBaseType(IdentifierName($"I{resolver.JsonRpcAttributes.HandlerName}Handler"))); + } + + if (item.LspAttributes?.CanBeResolved == true && item is RequestItem r) + { + handlerInterface = handlerInterface.AddBaseListTypes(SimpleBaseType(IdentifierName("ICanBeIdentifiedHandler"))); + handlerClass = handlerClass + .AddMembers(AddConstructors(r, r, false).ToArray()) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()); + } + else if (resolver is { } && item is RequestItem r2) + { + handlerClass = handlerClass + .AddMembers(AddConstructors(r2, resolver, false).ToArray()) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()) + .AddMembers(AddResolveMethod(resolver.Request.Syntax)); + } + + members.Insert(0, handlerClass); + members.Insert(0, handlerInterface); + + if (item is RequestItem r3) + { + if (resolver is { LspAttributes: { GenerateTypedData: true } }) + { + members.Add( + GenerateTypedHandler( + handlerClass, + r3, + resolver + ) + ); + } + } + } + + if (item is RequestItem request) + { + ClassDeclarationSyntax? handlerClass = null; + if (request is { PartialItem: { } }) + { + handlerClass = ClassDeclaration(Identifier($"{item.JsonRpcAttributes.HandlerName}PartialHandlerBase")) + .WithAttributeLists(classAttributes) + .AddModifiers(Token(SyntaxKind.AbstractKeyword)) + .AddModifiers(handlerInterface.Modifiers.ToArray()) + .AddBaseListTypes( + SimpleBaseType(GetPartialResultBaseClass(request, request.PartialItem)), + SimpleBaseType(IdentifierName($"I{item.JsonRpcAttributes.HandlerName}Handler")) + ); + if (item.LspAttributes?.CanBeResolved == true && item is RequestItem r) + { + handlerClass = handlerClass + .AddMembers(AddConstructors(r, r, true).ToArray()) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()); + } + else if (resolver is { }) + { + handlerClass = handlerClass + .AddMembers(AddConstructors(request, resolver, true).ToArray()) + .AddBaseListTypes(SimpleBaseType(IdentifierName($"I{resolver.JsonRpcAttributes.HandlerName}Handler"))) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()) + .AddMembers(AddResolveMethod(resolver.Request.Syntax)); + } + else + { + handlerClass = handlerClass + .AddMembers(AddConstructors(request, resolver, true).ToArray()); + } + + members.Add(handlerClass); + } + else if (request is { PartialItems: { } partialItems }) + { + handlerClass = ClassDeclaration(Identifier($"{item.JsonRpcAttributes.HandlerName}PartialHandlerBase")) + .WithAttributeLists(classAttributes) + .AddModifiers(Token(SyntaxKind.AbstractKeyword)) + .AddModifiers(handlerInterface.Modifiers.ToArray()) + .AddBaseListTypes( + SimpleBaseType(GetPartialResultsBaseClass(request, request.PartialItems)), + SimpleBaseType(IdentifierName($"I{item.JsonRpcAttributes.HandlerName}Handler")) + ); + + if (item.LspAttributes?.CanBeResolved == true && item is RequestItem r) + { + handlerClass = handlerClass + .AddMembers(AddConstructors(r, r, true).ToArray()) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()); + } + else if (resolver is { }) + { + handlerClass = handlerClass + .AddMembers(AddConstructors(request, resolver, true).ToArray()) + .AddBaseListTypes(SimpleBaseType(IdentifierName($"I{resolver.JsonRpcAttributes.HandlerName}Handler"))) + .AddMembers(AddCanBeIdentifiedMembers().ToArray()) + .AddMembers(AddResolveMethod(resolver.Request.Syntax)); + } + else + { + handlerClass = handlerClass + .AddMembers(AddConstructors(request, resolver, true).ToArray()); + } + + members.Add(handlerClass); + + if (resolver is { LspAttributes: { GenerateTypedData: true } } && handlerClass is { }) + { + members.Add( + GenerateTypedPartialHandler( + handlerClass, + request, + resolver, + partialItems + ) + ); + } + + if (request is { LspAttributes: { GenerateTypedData: true } } && handlerClass is { }) + { + members.Add( + GenerateTypedPartialHandler( + handlerClass, + request, + request, + partialItems + ) + ); + } + } + } + + if (members.Count == 0) yield break; + + yield return NamespaceDeclaration(ParseName(item.JsonRpcAttributes.HandlerNamespace)) + .WithMembers(List(members)) + .WithLeadingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)))) + .WithTrailingTrivia(TriviaList(Trivia(NullableDirectiveTrivia(Token(SyntaxKind.RestoreKeyword), true)))); + } + + private static GenericNameSyntax GetBaseHandlerInterface(GeneratorData item) + { + var requestType = item.JsonRpcAttributes.AllowDerivedRequests ? IdentifierName("T") : item.Request.Syntax; + if (item is NotificationItem notification) + { + return GenericName("IJsonRpcNotificationHandler") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(requestType))); + } + + if (item is RequestItem request) + { + return GenericName("IJsonRpcRequestHandler") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { requestType, request.Response.Syntax }))); + } + + throw new NotSupportedException(); + } + + private static TypeSyntax? GetBaseHandlerClass(GeneratorData item) + { + var onlyCapability = item is { Capability: { }, RegistrationOptions: null }; + var requestType = item.JsonRpcAttributes.AllowDerivedRequests ? IdentifierName("T") : item.Request.Syntax; + var types = new List() { requestType }; + if (item.RegistrationOptions is { }) + { + types.Add(item.RegistrationOptions.Syntax); + } + + if (item.Capability is { }) + { + types.Add(item.Capability.Syntax); + } + + if (item is NotificationItem notification) + { + return QualifiedName( + IdentifierName("AbstractHandlers"), + GenericName($"Notification{( onlyCapability ? "Capability" : "" )}") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) + ); + } + + if (item is RequestItem request) + { + types.Insert(1, request.Response.Syntax); + return QualifiedName( + IdentifierName("AbstractHandlers"), + GenericName($"Request{( onlyCapability ? "Capability" : "" )}") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) + ); + } + + + return null; + } + + private static TypeSyntax GetPartialResultBaseClass(RequestItem request, SyntaxSymbol item) + { + var onlyCapability = request is { Capability: { }, RegistrationOptions: null }; + var types = new List { request.Request.Syntax, request.Response.Syntax, item.Syntax }; + + if (request.RegistrationOptions is { }) + { + types.Add(request.RegistrationOptions.Syntax); + } + + if (request.Capability is { }) + { + types.Add(request.Capability.Syntax); + } + + return QualifiedName( + IdentifierName("AbstractHandlers"), + GenericName($"PartialResult{( onlyCapability ? "Capability" : "" )}") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) + ); + } + + private static TypeSyntax GetPartialResultsBaseClass(RequestItem request, SyntaxSymbol item) + { + var onlyCapability = request is { Capability: { }, RegistrationOptions: null }; + var types = new List { request.Request.Syntax, request.Response.Syntax, item.Syntax }; + + if (request.RegistrationOptions is { }) + { + types.Add(request.RegistrationOptions.Syntax); + } + + if (request.Capability is { }) + { + types.Add(request.Capability.Syntax); + } + + return QualifiedName( + IdentifierName("AbstractHandlers"), + GenericName($"PartialResults{( onlyCapability ? "Capability" : "" )}") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) + ); + } + + private static GenericNameSyntax? GetRegistrationAndOrCapability(GeneratorData item) + { + if (item.Capability is { } && item.RegistrationOptions is { }) + { + return GenericName("IRegistration") + .WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { item.RegistrationOptions.Syntax, item.Capability.Syntax }))); + } + + if (item.RegistrationOptions is { }) + { + return GenericName("IRegistration") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.RegistrationOptions.Syntax))); + } + + if (item.Capability is { }) + { + return GenericName("ICapability") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.Capability.Syntax))); + } + + return null; + } + + private static bool AttributeFilter(AttributeSyntax syntax) + { + var fullString = syntax.Name.ToFullString(); + return !fullString.Contains("Generate") + && !fullString.Contains("DebuggerDisplay") + && !fullString.Contains("RegistrationOptions") + && !fullString.Contains("Capability") + && !fullString.Contains("Resolver"); + } + + private static ConstructorDeclarationSyntax GetConstructor( + RequestItem request, + ParameterListSyntax parameters, + ConstructorInitializerSyntax constructorInitializerSyntax, + bool isPartial + ) + { + return ConstructorDeclaration( + Identifier( + isPartial + ? $"{request.JsonRpcAttributes.HandlerName}PartialHandlerBase" + : $"{request.JsonRpcAttributes.HandlerName}HandlerBase" + ) + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) + .WithParameterList(parameters) + .WithInitializer(constructorInitializerSyntax) + .WithBody(Block()); + } + + private static MemberDeclarationSyntax AddResolveMethod(TypeSyntax syntax) + { + return MethodDeclaration( + GenericName(Identifier("Task")).WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(syntax))), + Identifier("Handle") + ) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.AbstractKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(syntax), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } + + private static IEnumerable AddCanBeIdentifiedMembers() + { + yield return FieldDeclaration(VariableDeclaration(IdentifierName("Guid")).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_id"))))) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))); + yield return PropertyDeclaration(IdentifierName("Guid"), Identifier("Id")) + .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName("ICanBeIdentifiedHandler"))) + .WithExpressionBody(ArrowExpressionClause(IdentifierName("_id"))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } + + private static IEnumerable AddConstructors(RequestItem request, RequestItem? resolver, bool isPartial) + { + var parameters = ParameterList(); + var arguments = ArgumentList(); + if (isPartial) + { + parameters = parameters.AddParameters(Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager"))); + arguments = arguments.AddArguments(Argument(IdentifierName("progressManager"))); + + if (request.PartialItem is { } || request.PartialItems is { }) + { + arguments = arguments.AddArguments( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + request.Response.Syntax.EnsureNotNullable(), + IdentifierName("From") + ) + ) + ); + } + } + + if (resolver is { }) + { + yield return GetConstructor( + request, + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("id")).WithType( + ParseName("System.Guid") + ) + ) + ).AddParameters(parameters.Parameters.ToArray()), + ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, arguments), + isPartial + ) + .WithBody( + Block( + SingletonList( + ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("_id"), IdentifierName("id")) + ) + ) + ) + ); + yield return GetConstructor( + request, + parameters, + ConstructorInitializer( + SyntaxKind.ThisConstructorInitializer, + ArgumentList( + SingletonSeparatedList( + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("Guid"), + IdentifierName("NewGuid") + ) + ) + ) + ) + ) + .AddArguments(arguments.Arguments.Take(Math.Max(0, arguments.Arguments.Count - 1)).ToArray()) + ), + isPartial + ); + } + else + { + yield return GetConstructor( + request, + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("id")).WithType( + ParseName("System.Guid") + ) + ) + ).AddParameters(parameters.Parameters.ToArray()), + ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, arguments), + isPartial + ); + } + } + + private static ClassDeclarationSyntax GenerateTypedPartialHandler( + ClassDeclarationSyntax classDeclarationSyntax, + RequestItem item, + RequestItem resolver, + SyntaxSymbol partialItems + ) + { + return ClassDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(classDeclarationSyntax.Modifiers) + .WithAttributeLists(classDeclarationSyntax.AttributeLists) + .WithHandlerIdentityConstraint(true) + .WithBaseList(BaseList(SingletonSeparatedList(SimpleBaseType(IdentifierName(classDeclarationSyntax.Identifier.Text))))) + .AddMembers( + ConstructorDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("id")).WithType(IdentifierName("Guid")), + Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager")) + } + ) + ) + ) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.BaseConstructorInitializer, + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("id")), + Argument( + IdentifierName("progressManager") + ) + } + ) + ) + ) + ) + .WithBody(Block()), + ConstructorDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) + .WithParameterList(ParameterList(SingletonSeparatedList(Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager"))))) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.ThisConstructorInitializer, + ArgumentList( + SeparatedList( + new[] { + Argument( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Guid"), IdentifierName("NewGuid")) + ) + ), + Argument( + IdentifierName("progressManager") + ) + } + ) + ) + ) + ) + .WithBody(Block()), + MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Handle")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(item.Request.Syntax), + Parameter(Identifier("results")) + .WithType( + GenericName(Identifier("IObserver")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName(Identifier("IEnumerable")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(partialItems.Syntax))) + ) + ) + ) + ), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("Handle")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("request")), + Argument( + ObjectCreationExpression( + QualifiedName( + IdentifierName("LanguageProtocolDelegatingHandlers"), + GenericName( + Identifier("TypedPartialObserver") + ) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new TypeSyntax[] { + GenericName(Identifier(resolver.Response.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ), + partialItems.Syntax + } + ) + ) + ) + ) + ) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument( + IdentifierName("results") + ), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + partialItems.Syntax, + IdentifierName("From") + ) + ) + } + ) + ) + ) + ), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + resolver.Response.Syntax + ) + ) + ), + Identifier("Handle") + ) + .WithModifiers( + TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.OverrideKeyword), Token(SyntaxKind.AsyncKeyword)) + ) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(resolver.Request.Syntax), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithBody( + Block( + LocalDeclarationStatement( + VariableDeclaration(IdentifierName("var")) + .WithVariables( + SingletonSeparatedList( + VariableDeclarator(Identifier("response")) + .WithInitializer( + EqualsValueClause( + AwaitExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression( + IdentifierName("HandleResolve") + ) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("request")), + Argument( + IdentifierName("cancellationToken") + ) + } + ) + ) + ), + IdentifierName("ConfigureAwait") + ) + ) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList(Argument(LiteralExpression(SyntaxKind.FalseLiteralExpression))) + ) + ) + ) + ) + ) + ) + ) + ), + ReturnStatement(IdentifierName("response")) + ) + ), + MethodDeclaration( + PredefinedType(Token(SyntaxKind.VoidKeyword)), + Identifier("Handle") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(item.Request.Syntax), + Parameter(Identifier("results")) + .WithType( + GenericName(Identifier("IObserver")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName(Identifier("IEnumerable")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) + ) + ) + ) + ) + ) + ) + ), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) + ) + ) + ), + Identifier("HandleResolve") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")) + .WithType( + GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) + ), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + } + + private static ClassDeclarationSyntax GenerateTypedHandler( + ClassDeclarationSyntax classDeclarationSyntax, + RequestItem item, + RequestItem resolver + ) + { + TypeSyntax responseType = GenericName(Identifier(item.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + // Special case... because the spec is awesome + if (item.Response.Symbol.Name == "CommandOrCodeActionContainer") + { + responseType = GenericName(Identifier("CodeActionContainer")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + } + + return ClassDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(classDeclarationSyntax.Modifiers) + .WithAttributeLists(classDeclarationSyntax.AttributeLists) + .WithHandlerIdentityConstraint(true) + .WithBaseList(BaseList(SingletonSeparatedList(SimpleBaseType(IdentifierName(classDeclarationSyntax.Identifier.Text))))) + .AddMembers( + ConstructorDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) + .WithParameterList(ParameterList(SingletonSeparatedList(Parameter(Identifier("id")).WithType(IdentifierName("Guid"))))) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.BaseConstructorInitializer, + ArgumentList(SingletonSeparatedList(Argument(IdentifierName("id")))) + ) + ) + .WithBody(Block()), + ConstructorDeclaration(classDeclarationSyntax.Identifier) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.ThisConstructorInitializer, + ArgumentList( + SingletonSeparatedList( + Argument( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Guid"), IdentifierName("NewGuid")) + ) + ) + ) + ) + ) + ) + .WithBody(Block()), + MethodDeclaration( + GenericName(Identifier("Task")).WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.Response.Syntax))), + Identifier("Handle") + ) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.OverrideKeyword), Token(SyntaxKind.AsyncKeyword) + ) + ) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(item.Request.Syntax), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + AwaitExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression(IdentifierName("HandleParams")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ), + IdentifierName("ConfigureAwait") + ) + ) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + LiteralExpression( + SyntaxKind.FalseLiteralExpression + ) + ) + ) + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + MethodDeclaration( + GenericName(Identifier("Task")).WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolver.Response.Syntax))), + Identifier("Handle") + ) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.OverrideKeyword), Token(SyntaxKind.AsyncKeyword) + ) + ) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(resolver.Response.Syntax), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + AwaitExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression(IdentifierName("HandleResolve")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument( + IdentifierName("request") + ), + Argument( + IdentifierName("cancellationToken") + ) + } + ) + ) + ), + IdentifierName("ConfigureAwait") + ) + ) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + LiteralExpression( + SyntaxKind.FalseLiteralExpression + ) + ) + ) + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(responseType))), + Identifier("HandleParams") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(item.Request.Syntax), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithSemicolonToken( + Token(SyntaxKind.SemicolonToken) + ), + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName(Identifier(resolver.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))) + ) + ) + ), + Identifier("HandleResolve") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")) + .WithType( + GenericName(Identifier(resolver.Response.Symbol.Name)).WithTypeArgumentList( + TypeArgumentList(SingletonSeparatedList(IdentifierName("T"))) + ) + ), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/HandlerRegistryActionContextRunnerStrategy.cs b/src/JsonRpc.Generators/Strategies/HandlerRegistryActionContextRunnerStrategy.cs new file mode 100644 index 000000000..ffda7747c --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/HandlerRegistryActionContextRunnerStrategy.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class HandlerRegistryActionContextRunnerStrategy : IExtensionMethodGeneratorStrategy + { + private readonly ImmutableArray _strategies; + + public HandlerRegistryActionContextRunnerStrategy(ImmutableArray strategies) + { + _strategies = strategies; + } + public IEnumerable Apply(GeneratorData item) + { + return item.JsonRpcAttributes.HandlerRegistries + .Select( + registry => new ExtensionMethodContext( + item.JsonRpcAttributes.GenerateHandlerMethods!.Data, item.TypeDeclaration, item.TypeSymbol, registry, item.JsonRpcAttributes.HandlerRegistries, + item.Context + ) { IsRegistry = true } + ) + .SelectMany(_ => _strategies, (actionContext, strategy) => new { actionContext, strategy }) + .SelectMany(@t => @t.strategy.Apply(@t.actionContext, item)); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..3f9de03ac --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -0,0 +1,151 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnNotificationMethodGeneratorWithRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not { RegistrationOptions: { } registrationOptions }) yield break; + if (item is not NotificationItem notification) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + + var allowDerivedRequests = item.JsonRpcAttributes.AllowDerivedRequests; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithBody( + GetNotificationRegistrationHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), item.Request.Syntax, registrationOptions.Syntax, item.Capability?.Syntax + ) + ); + + + var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList(), registrationOptions.Syntax, item.Capability?.Syntax); + var factory = methodFactory(method); + + yield return factory(CreateAction(false, item.Request.Syntax)); + yield return factory(CreateAsyncAction(false, item.Request.Syntax)); + yield return factory(CreateAction(true, item.Request.Syntax)); + yield return factory(CreateAsyncAction(true, item.Request.Syntax)); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, notification.Request.Syntax); + yield return genericFactory(CreateAction(IdentifierName("T"))); + yield return genericFactory(CreateAsyncAction(false, IdentifierName("T"))); + yield return genericFactory(CreateAction(true, IdentifierName("T"))); + yield return genericFactory(CreateAsyncAction(true, IdentifierName("T"))); + } + + if (item.Capability is { } capability) + { + yield return factory(CreateAction(true, item.Request.Syntax, capability.Syntax)); + yield return factory(CreateAsyncAction(true, item.Request.Syntax, capability.Syntax)); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, notification.Request.Syntax); + yield return genericFactory(CreateAction(true, IdentifierName("T"), capability.Syntax, capability.Syntax)); + yield return genericFactory(CreateAsyncAction(true, IdentifierName("T"), capability.Syntax, capability.Syntax)); + } + } + } + + private static Func> MakeFactory( + ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName + ) + { + return method => syntax => GenerateMethods(method, syntax); + + MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, ParameterSyntax registrationParameter) + { + return method + .WithParameterList( + preParameterList.AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters(registrationParameter) + ); + } + + MethodDeclarationSyntax GenerateMethods(MethodDeclarationSyntax method, TypeSyntax syntax) + { + if (capabilityName is { }) + { + return MethodFactory( + method, syntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")).WithTypeArgumentList( + TypeArgumentList(SeparatedList(new[] { registrationOptions, capabilityName })) + ) + ) + ); + } + + return MethodFactory( + method, syntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList( + TypeArgumentList(SingletonSeparatedList(registrationOptions)) + ) + ) + ); + } + } + + private static BlockSyntax GetNotificationRegistrationHandlerExpression( + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax registrationOptions, + TypeSyntax? capabilityName + ) + { + var args = ImmutableArray.Create(requestName, registrationOptions); + var adapterArgs = ImmutableArray.Create(requestName); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + return Block( + ReturnStatement( + AddHandler( + Argument(nameExpression), + Argument( + CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), "Notification", args.ToArray()) + .WithArgumentList( + GetRegistrationHandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + HandlerArgument, + capabilityName, + false + ), + capabilityName, + false + ) + ) + ) + ) + ) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..b86cf9457 --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is { RegistrationOptions: {} }) yield break; + if (item is not NotificationItem notification) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + + var allowDerivedRequests = item.JsonRpcAttributes.AllowDerivedRequests; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody(GetNotificationHandlerExpression(GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + + var factory = MakeMethodFactory(method, extensionMethodContext.GetRegistryParameterList()); + yield return factory(CreateAction(false, item.Request.Syntax)); + yield return factory(CreateAsyncAction(false, item.Request.Syntax)); + yield return factory(CreateAction(true, item.Request.Syntax)); + yield return factory(CreateAsyncAction(true, item.Request.Syntax)); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, notification.Request.Syntax); + yield return genericFactory(CreateAction(IdentifierName("T"))); + yield return genericFactory(CreateAsyncAction(false, IdentifierName("T"))); + yield return genericFactory(CreateAction(true, IdentifierName("T"))); + yield return genericFactory(CreateAsyncAction(true, IdentifierName("T"))); + } + + if (item.Capability is not null) + { + factory = MakeMethodFactory( + method + .WithExpressionBody( + GetNotificationCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), + item.Request.Syntax, + item.Capability.Syntax + ) + ), + extensionMethodContext.GetRegistryParameterList() + ); + // might cause issues + yield return factory(CreateAction(true, item.Request.Syntax, item.Capability.Syntax)); + yield return factory(CreateAsyncAction(true, item.Request.Syntax, item.Capability.Syntax)); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, IdentifierName("T")); + yield return genericFactory(CreateAction(true, IdentifierName("T"), item.Capability.Syntax)); + yield return genericFactory(CreateAsyncAction(true, IdentifierName("T"), item.Capability.Syntax)); + } + } + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..b859551ca --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -0,0 +1,530 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnRequestMethodGeneratorWithRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + private readonly bool _doResolve; + + public OnRequestMethodGeneratorWithRegistrationOptionsStrategy(bool doResolve) + { + _doResolve = doResolve; + } + + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not { RegistrationOptions: { } registrationOptions }) yield break; + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + + var resolve = GeneratorData.CreateForResolver(item); + if (!_doResolve) resolve = null; + if (_doResolve && resolve is null) yield break; + + var allowDerivedRequests = item.JsonRpcAttributes.AllowDerivedRequests && !_doResolve; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithBody( + GetRequestHandlerExpression( + request, + registrationOptions.Syntax, + item.Capability?.Syntax, + resolve + ) + ); + if (request.IsUnit) + { + method = method + .WithBody( + GetVoidRequestHandlerExpression( + request, + registrationOptions.Syntax, + item.Capability?.Syntax, + resolve + ) + ); + } + + var methodFactory = MakeFactory( + extensionMethodContext.GetRegistryParameterList(), + registrationOptions.Syntax, + item.Capability?.Syntax + ); + var factory = methodFactory(method); + + yield return factory( + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax), + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax), + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, false, IdentifierName("T")), null); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T")), null); + } + + { + if (request.Capability is { } capability) + { + yield return factory( + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T"), capability.Syntax), null); + } + } + } + + if (request.PartialItems is { } partialItems) + { + var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialItems.Syntax }))); + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithBody( + GetPartialResultsHandlerExpression( + request, + partialItems.Syntax, + registrationOptions.Syntax, + item.Capability?.Syntax, + resolve + ) + ) + ); + + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, false), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItemsSyntax, false), null); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItemsSyntax, true), null); + } + + if (request.Capability is { } capability) + { + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + } + } + + if (request.PartialItem is { } partialItem) + { + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithBody( + GetPartialResultHandlerExpression( + request, + partialItem.Syntax, + registrationOptions.Syntax, + item.Capability?.Syntax, + resolve + ) + ) + ); + + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, false), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, false), null); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true), null); + } + + if (request.Capability is { } capability) + { + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null); + } + } + } + } + + private static Func> MakeFactory( + ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName + ) + { + return method => (syntax, resolveSyntax) => GenerateMethod(method, syntax, resolveSyntax); + + MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, ParameterSyntax registrationParameter) + { + return method + .WithParameterList( + preParameterList + .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters( + resolveSyntax is { } + ? new[] { + Parameter(Identifier("resolveHandler")) + .WithType(resolveSyntax) + } + : new ParameterSyntax[] { } + ) + .AddParameters(registrationParameter) + ); + } + + MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + { + if (capabilityName is { }) + { + return MethodFactory( + method, syntax, resolveSyntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")).WithTypeArgumentList( + TypeArgumentList(SeparatedList(new[] { registrationOptions, capabilityName })) + ) + ) + ); + } + + return MethodFactory( + method, syntax, resolveSyntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList( + TypeArgumentList(SingletonSeparatedList(registrationOptions)) + ) + ) + ); + } + } + + private static BlockSyntax GetRequestHandlerExpression( + RequestItem item, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName, + RequestItem? resolve + ) + { + var args = ImmutableArray.Create(item.Request.Syntax, item.Response.Syntax, registrationOptions); + var adapterArgs = ImmutableArray.Create(item.Request.Syntax, item.Response.Syntax); + var statements = ImmutableArray.Create(); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + var returnStatement = ReturnStatement( + AddHandler( + Argument(GetJsonRpcMethodName(item.TypeDeclaration)), + Argument( + CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), capabilityName is { } ? "Request" : "RequestRegistration", args.ToArray()) + .WithArgumentList( + GetRegistrationHandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + HandlerArgument, + capabilityName, + false + ), + capabilityName, + resolve is not null + ) + ) + ) + ) + ); + + InsertResolveHandler(ref statements, ref returnStatement, resolve, registrationOptions, capabilityName); + + return Block(statements.Add(returnStatement)); + } + + private static BlockSyntax GetVoidRequestHandlerExpression( + RequestItem item, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName, + RequestItem? resolve + ) + { + var args = ImmutableArray.Create(item.Request.Syntax, registrationOptions); + var adapterArgs = ImmutableArray.Create(item.Request.Syntax); + var statements = ImmutableArray.Create(); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + var returnStatement = ReturnStatement( + AddHandler( + Argument(GetJsonRpcMethodName(item.TypeDeclaration)), + Argument( + CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), capabilityName is { } ? "Request" : "RequestRegistration", args.ToArray()) + .WithArgumentList( + GetRegistrationHandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + HandlerArgument, + capabilityName, + false + ), + capabilityName, + resolve is not null + ) + ) + ) + ) + ); + + InsertResolveHandler(ref statements, ref returnStatement, resolve, registrationOptions, capabilityName); + + return Block(statements.Add(returnStatement)); + } + + private static BlockSyntax GetPartialResultsHandlerExpression( + RequestItem item, + TypeSyntax itemName, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName, + RequestItem? resolve + ) + { + var args = ImmutableArray.Create(item.Request.Syntax, item.Response.Syntax, itemName, registrationOptions); + var adapterArgs = ImmutableArray.Create(item.Request.Syntax, itemName); + var statements = ImmutableArray.Create(); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + var returnStatement = ReturnStatement( + AddHandler( + Argument(GetJsonRpcMethodName(item.TypeDeclaration)), + Argument( + SimpleLambdaExpression( + Parameter( + Identifier("_") + ), + CreateHandlerArgument( + IdentifierName("LanguageProtocolDelegatingHandlers"), + "PartialResults", + args.ToArray() + ) + .WithArgumentList( + GetPartialItemsArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + item.Response.Syntax, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + HandlerArgument, + capabilityName, + true + ), + capabilityName + ) + ) + ) + ) + ) + ); + + InsertResolveHandler(ref statements, ref returnStatement, resolve, registrationOptions, capabilityName); + + return Block(statements.Add(returnStatement)); + } + + private static BlockSyntax GetPartialResultHandlerExpression( + RequestItem item, + TypeSyntax itemType, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName, + RequestItem? resolve + ) + { + var args = ImmutableArray.Create(item.Request.Syntax, item.Response.Syntax, itemType, registrationOptions); + var adapterArgs = ImmutableArray.Create(item.Request.Syntax, itemType); + var statements = ImmutableArray.Create(); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + var returnStatement = ReturnStatement( + AddHandler( + Argument(GetJsonRpcMethodName(item.TypeDeclaration)), + Argument( + SimpleLambdaExpression( + Parameter( + Identifier("_") + ), + CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), "PartialResult", args.ToArray()) + .WithArgumentList( + GetPartialResultArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + item.Response.Syntax, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + HandlerArgument, + capabilityName, + true + ), + capabilityName + ) + ) + ) + ) + ) + ); + + InsertResolveHandler(ref statements, ref returnStatement, resolve, registrationOptions, capabilityName); + + return Block(statements.Add(returnStatement)); + } + + private static void InsertResolveHandler( + ref ImmutableArray statements, + ref ReturnStatementSyntax returnStatement, + RequestItem? resolve, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName + ) + { + if (resolve is null) return; + var args = ImmutableArray.Create(resolve.Request.Syntax, resolve.Response.Syntax, registrationOptions); + var adapterArgs = ImmutableArray.Create(resolve.Request.Syntax, resolve.Response.Syntax); + if (capabilityName is { }) + { + args = args.Add(capabilityName); + } + + statements = statements.Add(NewGuid); + returnStatement = returnStatement.WithExpression( + AddHandler( + returnStatement.Expression!, + Argument(GetJsonRpcMethodName(resolve.TypeDeclaration)), + Argument( + CreateHandlerArgument( + IdentifierName("LanguageProtocolDelegatingHandlers"), capabilityName is { } ? "Request" : "RequestRegistration", + args.ToArray() + ) + .WithArgumentList( + GetRegistrationHandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(adapterArgs.ToArray())), + ResolveHandlerArgument, + capabilityName, + false + ), + capabilityName, + true + ) + ) + ) + ) + ); + } + + private static ArgumentListSyntax GetPartialItemsArgumentList( + TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType + ) => + ArgumentList( + SeparatedList( + new[] { + handlerArgument, + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)), + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("_"), + GenericName(Identifier("GetService")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) + ) + ) + ), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + responseName is NullableTypeSyntax nts ? nts.ElementType : responseName, + IdentifierName("From") + ) + ) + } + ) + ); + + private static ArgumentListSyntax GetPartialResultArgumentList( + TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType + ) => + ArgumentList( + SeparatedList( + new[] { + handlerArgument, + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)), + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("_"), + GenericName(Identifier("GetService")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) + ) + ) + ), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + responseName is NullableTypeSyntax nts ? nts.ElementType : responseName, + IdentifierName("From") + ) + ) + } + ) + ); + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..dcfabb9af --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + private readonly bool _doResolve; + + public OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy(bool doResolve) + { + _doResolve = doResolve; + } + + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is { RegistrationOptions: { } }) yield break; + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + + var resolve = GeneratorData.CreateForResolver(item); + if (!_doResolve) resolve = null; + if (_doResolve && resolve is null) yield break; + + var allowDerivedRequests = item.JsonRpcAttributes.AllowDerivedRequests && !_doResolve; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody(GetRequestHandlerExpression(request, GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + + var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList()); + + var factory = methodFactory(method); + yield return factory( + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax), + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax), + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + + yield return genericFactory( + CreateAsyncFunc(request.Response.Syntax, false, IdentifierName("T")), null + ); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T")), null); + } + + { + if (request.Capability is { } capability) + { + if (request.IsUnit) + { + factory = methodFactory( + method.WithExpressionBody( + GetVoidRequestCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, capability.Syntax + ) + ) + ); + } + else + { + factory = methodFactory( + method.WithExpressionBody( + GetRequestCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, request.Response.Syntax, capability.Syntax + ) + ) + ); + } + + yield return factory( + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory( + CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T"), capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + } + } + } + + if (request.PartialItems is { } partialItems) + { + var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialItems.Syntax }))); + + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithExpressionBody( + GetPartialResultsHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItems.Syntax, request.Response.Syntax + ) + ) + ); + + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, false), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory( + CreatePartialAction(IdentifierName("T"), partialItemsSyntax, false), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return genericFactory( + CreatePartialAction(IdentifierName("T"), partialItemsSyntax, true), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + } + + if (request.Capability is { } capability) + { + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithExpressionBody( + GetPartialResultsCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, request.Response.Syntax, + partialItemsSyntax, capability.Syntax + ) + ) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory( + CreatePartialAction(IdentifierName("T"), partialItemsSyntax, true, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + } + } + } + + if (request.PartialItem is { } partialItem) + { + factory = methodFactory( + method.WithExpressionBody( + GetPartialResultHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax + ) + ) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, false), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, false), null); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true), null); + } + + if (request.Capability is { } capability) + { + factory = methodFactory( + method.WithExpressionBody( + GetPartialResultCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax, capability.Syntax + ) + ) + ); + yield return factory( + CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true, capability.Syntax), + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + ); + + if (allowDerivedRequests) + { + var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null); + } + } + } + } + + private static Func> MakeFactory( + ParameterListSyntax preParameterList + ) + { + return method => (syntax, resolveSyntax) => GenerateMethods(method, syntax, resolveSyntax); + + MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + { + return method + .WithParameterList( + preParameterList + .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters( + resolveSyntax is { } + ? new[] { + Parameter(Identifier("resolveHandler")) + .WithType(resolveSyntax) + } + : new ParameterSyntax[] { } + ) + ); + } + + MethodDeclarationSyntax GenerateMethods(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) => MethodFactory(method, syntax, resolveSyntax); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..40ca7420b --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -0,0 +1,356 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not { RegistrationOptions: { } registrationOptions }) yield break; + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + if (item is not { LspAttributes: { Resolver: { } } }) yield break; + if (request.IsUnit) yield break; + + var resolver = GeneratorData.CreateForResolver(item)!; + + TypeSyntax requestType = item.Request.Syntax; + TypeSyntax resolveType = GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ); + TypeSyntax responseType = GenericName(Identifier(request.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + + // Special case... because the spec is awesome + if (request.Response.Symbol.Name == "CommandOrCodeActionContainer") + { + responseType = GenericName(Identifier("CodeActionContainer")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + } + responseType = request.Response.Syntax is NullableTypeSyntax ? NullableType(responseType) : responseType; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithHandlerIdentityConstraint(true) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithBody( + GetRequestHandlerExpression( + request, + requestType, + responseType, + resolveType, + registrationOptions.Syntax, + item.Capability?.Syntax + ) + ); + + var methodFactory = MakeFactory( + extensionMethodContext.GetRegistryParameterList(), + registrationOptions.Syntax, + item.Capability?.Syntax + ); + var factory = methodFactory(method); + + yield return factory( + CreateAsyncFunc(responseType, false, requestType), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreateAsyncFunc(responseType, true, requestType), + CreateAsyncFunc(resolveType, true, resolveType) + ); + + { + if (request.Capability is { } capability) + { + yield return factory( + CreateAsyncFunc(responseType, true, requestType, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + + if (request.PartialItems is { } partialItems) + { + var enumerableType = GenericName("IEnumerable") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))); + var observerType = GenericName("IObserver") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(enumerableType))); + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithBody( + GetPartialHandlerExpression( + request, + requestType, + resolveType, + registrationOptions.Syntax, + item.Capability?.Syntax + ) + ) + ); + + yield return factory( + CreatePartialAction(requestType, enumerableType, false), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreatePartialAction(requestType, enumerableType, true), + CreateAsyncFunc(resolveType, true, resolveType) + ); + + if (request.Capability is { } capability) + { + yield return factory( + CreatePartialAction(requestType, enumerableType, true, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + + if (request.PartialItem is { } partialItem ) + { + var observerType = GenericName("IObserver").WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))); + + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithBody( + GetPartialHandlerExpression( + request, + requestType, + resolveType, + registrationOptions.Syntax, + item.Capability?.Syntax + ) + ) + ); + + yield return factory( + CreatePartialAction(requestType, resolveType, false), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreatePartialAction(requestType, resolveType, true), + CreateAsyncFunc(resolveType, true, resolveType) + ); + + if (request.Capability is { } capability) + { + yield return factory( + CreatePartialAction(requestType, resolveType, true, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + } + + private static Func> MakeFactory( + ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName + ) + { + return method => (syntax, resolveSyntax) => GenerateMethod(method, syntax, resolveSyntax); + + MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, ParameterSyntax registrationParameter) + { + return method + .WithParameterList( + preParameterList + .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters( + resolveSyntax is { } + ? new[] { + Parameter(Identifier("resolveHandler")) + .WithType(resolveSyntax) + } + : new ParameterSyntax[] { } + ) + .AddParameters(registrationParameter) + ); + } + + MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + { + if (capabilityName is { }) + { + return MethodFactory( + method, syntax, resolveSyntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")).WithTypeArgumentList( + TypeArgumentList(SeparatedList(new[] { registrationOptions, capabilityName })) + ) + ) + ); + } + + return MethodFactory( + method, syntax, resolveSyntax, + Parameter(Identifier("registrationOptions")) + .WithType( + GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList( + TypeArgumentList(SingletonSeparatedList(registrationOptions)) + ) + ) + ); + } + } + + private static BlockSyntax GetRequestHandlerExpression( + RequestItem request, + TypeSyntax requestSyntax, + TypeSyntax responseSyntax, + TypeSyntax resolveSyntax, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName + ) + { + var typeArgs = ImmutableArray.Create(registrationOptions); + var handlerAdapterArgs = ImmutableArray.Create(requestSyntax, responseSyntax); + var resolveAdapterArgs = ImmutableArray.Create(resolveSyntax, resolveSyntax); + if (capabilityName is { }) + { + typeArgs = typeArgs.Add(capabilityName); + } + + return Block(ReturnStatement( + AddHandler( + Argument( + CreateHandlerArgument($"Delegating{request.JsonRpcAttributes.HandlerName}Handler", IdentifierName("T")) + .WithArgumentList( + HandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + capabilityName, + TypeArgumentList(SeparatedList(handlerAdapterArgs)), + TypeArgumentList(SeparatedList(resolveAdapterArgs)), + TypeArgumentList(SeparatedList(typeArgs.ToArray())) + ) + ) + ) + ) + )); + } + + private static BlockSyntax GetPartialHandlerExpression( + RequestItem request, + TypeSyntax requestSyntax, + TypeSyntax resolveSyntax, + TypeSyntax registrationOptions, + TypeSyntax? capabilityName + ) + { + var typeArgs = ImmutableArray.Create(registrationOptions); + var handlerAdapterArgs = ImmutableArray.Create(requestSyntax, resolveSyntax); + var resolveAdapterArgs = ImmutableArray.Create(resolveSyntax, resolveSyntax); + if (capabilityName is { }) + { + typeArgs = typeArgs.Add(capabilityName); + } + + return Block(ReturnStatement( + AddHandler( + Argument( + SimpleLambdaExpression( + Parameter( + Identifier("_") + ), + CreateHandlerArgument($"Delegating{request.JsonRpcAttributes.HandlerName}PartialHandler", IdentifierName("T")) + .WithArgumentList( + PartialHandlerArgumentList( + IdentifierName("registrationOptions"), + registrationOptions, + capabilityName, + TypeArgumentList(SeparatedList(handlerAdapterArgs)), + TypeArgumentList(SeparatedList(resolveAdapterArgs)), + TypeArgumentList(SeparatedList(typeArgs.ToArray())) + ) + ) + ) + ) + ) + )); + } + + public static ArgumentListSyntax HandlerArgumentList( + TypeSyntax registrationOptionsName, + TypeSyntax registrationType, + TypeSyntax? capabilityName, + TypeArgumentListSyntax handlerAdapterArgs, + TypeArgumentListSyntax resolveAdapterArgs, + TypeArgumentListSyntax registrationAdapterArgs + ) => + ArgumentList( + SeparatedList( + new[] { + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityName)), + GetHandlerAdapterArgument( + handlerAdapterArgs, + HandlerArgument, + capabilityName, + false + ), + GetHandlerAdapterArgument( + resolveAdapterArgs, + ResolveHandlerArgument, + capabilityName, + false + ) + } + ) + ); + + public static ArgumentListSyntax PartialHandlerArgumentList( + TypeSyntax registrationOptionsName, + TypeSyntax registrationType, + TypeSyntax? capabilityName, + TypeArgumentListSyntax handlerAdapterArgs, + TypeArgumentListSyntax resolveAdapterArgs, + TypeArgumentListSyntax registrationAdapterArgs + ) => + ArgumentList( + SeparatedList( + new[] { + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("_"), + GenericName(Identifier("GetService")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) + ) + ) + ), + Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityName)), + GetHandlerAdapterArgument( + handlerAdapterArgs, + HandlerArgument, + capabilityName, + true + ), + GetHandlerAdapterArgument( + resolveAdapterArgs, + ResolveHandlerArgument, + capabilityName, + false + ) + } + ) + ); + } +} diff --git a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs new file mode 100644 index 000000000..b4e0e3fcf --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; +using static OmniSharp.Extensions.JsonRpc.Generators.DelegateHelpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy : IExtensionMethodContextGeneratorStrategy + { + + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is { RegistrationOptions: { } }) yield break; + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsRegistry: true }) yield break; + if (item is not { LspAttributes: { Resolver: {} } }) yield break; + + var resolver = GeneratorData.CreateForResolver(item)!; + + TypeSyntax requestType = request.Request.Syntax; + TypeSyntax resolveType = GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ); + TypeSyntax responseType = GenericName(Identifier(request.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + + // Special case... because the spec is awesome + if (request.Response.Symbol.Name == "CommandOrCodeActionContainer") + { + responseType = GenericName(Identifier("CodeActionContainer")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + } + responseType = request.Response.Syntax is NullableTypeSyntax ? NullableType(responseType) : responseType; + + var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName) + .WithHandlerIdentityConstraint(true) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody(GetRequestHandlerExpression(request, GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + + var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList()); + + var factory = methodFactory(method); + yield return factory( + CreateAsyncFunc(responseType, false, requestType), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreateAsyncFunc(responseType, true, requestType), + CreateAsyncFunc(resolveType, false, resolveType) + ); + + { + if (request.Capability is { } capability) + { + if (request.IsUnit) + { + factory = methodFactory( + method.WithExpressionBody( + GetVoidRequestCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, capability.Syntax + ) + ) + ); + } + else + { + factory = methodFactory( + method.WithExpressionBody( + GetRequestCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, responseType, capability.Syntax + ) + ) + ); + } + + yield return factory( + CreateAsyncFunc(responseType, true, requestType, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + + if (request.PartialItems is { } partialItems) + { + var observerType = GenericName("IObserver") + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName("IEnumerable") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))) + ) + ) + ); + + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithExpressionBody( + GetPartialResultsHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, partialItems.Syntax, responseType + ) + ) + ); + + yield return factory( + CreatePartialAction(requestType, observerType, false), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreatePartialAction(requestType, observerType, true), + CreateAsyncFunc(resolveType, true, resolveType) + ); + + if (request.Capability is { } capability) + { + factory = methodFactory( + method + .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) + .WithExpressionBody( + GetPartialResultsCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, responseType, + observerType, capability.Syntax + ) + ) + ); + yield return factory( + CreatePartialAction(requestType, observerType, true, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + + if (request.PartialItem is { } partialItem) + { + var observerType = GenericName("IObserver").WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))); + factory = methodFactory( + method.WithExpressionBody( + GetPartialResultHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType + ) + ) + ); + yield return factory( + CreatePartialAction(requestType, observerType, false), + CreateAsyncFunc(resolveType, false, resolveType) + ); + yield return factory( + CreatePartialAction(requestType, observerType, true), + CreateAsyncFunc(resolveType, true, resolveType) + ); + + if (request.Capability is { } capability) + { + factory = methodFactory( + method.WithExpressionBody( + GetPartialResultCapabilityHandlerExpression( + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType, capability.Syntax + ) + ) + ); + yield return factory( + CreatePartialAction(requestType, observerType, true, capability.Syntax), + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + ); + } + } + } + + private static Func> MakeFactory( + ParameterListSyntax preParameterList + ) + { + return method => (syntax, resolveSyntax) => GenerateMethods(method, syntax, resolveSyntax); + + MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + { + return method + .WithParameterList( + preParameterList + .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) + .AddParameters( + resolveSyntax is { } + ? new[] { + Parameter(Identifier("resolveHandler")) + .WithType(resolveSyntax) + } + : new ParameterSyntax[] { } + ) + ); + } + + MethodDeclarationSyntax GenerateMethods(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) => MethodFactory(method, syntax, resolveSyntax); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/RequestProxyActionContextRunnerStrategy.cs b/src/JsonRpc.Generators/Strategies/RequestProxyActionContextRunnerStrategy.cs new file mode 100644 index 000000000..17ee67b1f --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/RequestProxyActionContextRunnerStrategy.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class RequestProxyActionContextRunnerStrategy : IExtensionMethodGeneratorStrategy + { + private readonly ImmutableArray _strategies; + + public RequestProxyActionContextRunnerStrategy(ImmutableArray strategies) + { + _strategies = strategies; + } + public IEnumerable Apply(GeneratorData item) + { + return item.JsonRpcAttributes.RequestProxies + .Select( + registry => new ExtensionMethodContext( + item.JsonRpcAttributes.GenerateRequestMethods!.Data, item.TypeDeclaration, item.TypeSymbol, registry, item.JsonRpcAttributes.RequestProxies, + item.Context + ) { IsProxy = true } + ) + .SelectMany(_ => _strategies, (actionContext, strategy) => new { actionContext, strategy }) + .SelectMany(t => t.strategy.Apply(t.actionContext, item)); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs b/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs new file mode 100644 index 000000000..f83312cff --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class SendMethodNotificationStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not NotificationItem notification) yield break; + if (extensionMethodContext is not { IsProxy: true }) yield break; + + var method = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), item.JsonRpcAttributes.RequestMethodName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody(Helpers.GetNotificationInvokeExpression()) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + + yield return method + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("mediator")) + .WithType(extensionMethodContext.Item) + .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))), + Parameter(Identifier("request")) + .WithType(notification.Request.Syntax) + } + ) + ) + ); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs b/src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs new file mode 100644 index 000000000..336d4b3af --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs @@ -0,0 +1,115 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class SendMethodRequestStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsProxy: true }) yield break; + + var parameterList = SyntaxFactory.ParameterList( + SyntaxFactory.SeparatedList( + new[] { + SyntaxFactory.Parameter(SyntaxFactory.Identifier("mediator")) + .WithType(extensionMethodContext.Item) + .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ThisKeyword))), + SyntaxFactory.Parameter(SyntaxFactory.Identifier("request")) + .WithType(request.Request.Syntax), + SyntaxFactory.Parameter(SyntaxFactory.Identifier("cancellationToken")) + .WithType(SyntaxFactory.IdentifierName("CancellationToken")) + .WithDefault( + SyntaxFactory.EqualsValueClause( + SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression, SyntaxFactory.Token(SyntaxKind.DefaultKeyword)) + ) + ) + } + ) + ); + + if (request.PartialItem is not null) + { + request.AdditionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); + yield return SyntaxFactory.MethodDeclaration( + SyntaxFactory.GenericName( + SyntaxFactory.Identifier("IRequestProgressObservable") + ) + .WithTypeArgumentList( + SyntaxFactory.TypeArgumentList( + SyntaxFactory.SeparatedList( + new[] { + request.PartialItem.Syntax, + request.Response!.Syntax + } + ) + ) + ), + SyntaxFactory.Identifier(item.JsonRpcAttributes.RequestMethodName) + ) + .WithModifiers( + SyntaxFactory.TokenList( + SyntaxFactory.Token(SyntaxKind.PublicKeyword), + SyntaxFactory.Token(SyntaxKind.StaticKeyword) + ) + ) + .WithParameterList(parameterList) + .WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax)) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + yield break; + } + + if (request.PartialItems is not null) + { + request.AdditionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); + var partialItemsSyntax = SyntaxFactory.GenericName("IEnumerable").WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(new[] { request.PartialItems!.Syntax }))); + yield return SyntaxFactory.MethodDeclaration( + SyntaxFactory.GenericName( + SyntaxFactory.Identifier("IRequestProgressObservable") + ) + .WithTypeArgumentList( + SyntaxFactory.TypeArgumentList( + SyntaxFactory.SeparatedList( + new TypeSyntax[] { + partialItemsSyntax, + request.Response!.Syntax + } + ) + ) + ), + SyntaxFactory.Identifier(item.JsonRpcAttributes.RequestMethodName) + ) + .WithModifiers( + SyntaxFactory.TokenList( + SyntaxFactory.Token(SyntaxKind.PublicKeyword), + SyntaxFactory.Token(SyntaxKind.StaticKeyword) + ) + ) + .WithParameterList(parameterList) + .WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax)) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + ; + yield break; + } + + + var responseSyntax = request.Response.Syntax.GetSyntaxName() == "Unit" + ? SyntaxFactory.IdentifierName("Task") as NameSyntax + : SyntaxFactory.GenericName("Task").WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(new[] { request.Response.Syntax }))); + yield return SyntaxFactory.MethodDeclaration(responseSyntax, item.JsonRpcAttributes.RequestMethodName) + .WithModifiers( + SyntaxFactory.TokenList( + SyntaxFactory.Token(SyntaxKind.PublicKeyword), + SyntaxFactory.Token(SyntaxKind.StaticKeyword) + ) + ) + .WithParameterList(parameterList) + .WithExpressionBody(Helpers.GetRequestInvokeExpression()) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs b/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs new file mode 100644 index 000000000..9fe54df32 --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs @@ -0,0 +1,639 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using Microsoft.CodeAnalysis.Text; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class TypedDelegatingHandlerStrategy : IExtensionMethodGeneratorStrategy + { + public IEnumerable Apply(GeneratorData item) + { + if (item is not RequestItem requestItem) yield break; + if (requestItem is not { LspAttributes: { Resolver: { } } }) yield break; + var resolverData = GeneratorData.CreateForResolver(item); + if (resolverData is not { LspAttributes: { GenerateTypedData: true } }) yield break; + + yield return CreateDelegatingHandler(requestItem, resolverData); + + if (requestItem is { PartialItem: { } } or { PartialItems: { } }) + { + yield return CreateDelegatingPartialHandler(requestItem, resolverData); + } + } + + private ClassDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestItem resolver) + { + TypeSyntax requestType = item.Request.Syntax; + TypeSyntax resolveType = GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ); + TypeSyntax responseType = GenericName(Identifier(item.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + + // Special case... because the spec is awesome + if (item.Response.Symbol.Name == "CommandOrCodeActionContainer") + { + responseType = GenericName(Identifier("CodeActionContainer")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + } + + responseType = item.Response.Syntax is NullableTypeSyntax ? NullableType(responseType) : responseType; + + var handler = ClassDeclaration($"Delegating{item.JsonRpcAttributes.HandlerName}Handler") + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.SealedKeyword))) + .WithHandlerIdentityConstraint(true) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType( + GenericName(Identifier($"{item.JsonRpcAttributes.HandlerName}HandlerBase")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))) + ) + ) + ) + ); + + var constructorParams = ParameterList(); + + if (item.RegistrationOptions is { }) + { + if (item.Capability is { }) + { + var type = GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] { + item.RegistrationOptions.Syntax, + item.Capability.Syntax + } + ) + ) + ); + + handler = handler.AddMembers( + FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + MethodDeclaration(item.RegistrationOptions.Syntax, Identifier("CreateRegistrationOptions")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("capability")).WithType(item.Capability.Syntax), + Parameter(Identifier("clientCapabilities")).WithType(IdentifierName("ClientCapabilities")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_registrationOptionsFactory")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("capability")), + Argument(IdentifierName("clientCapabilities")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + constructorParams = constructorParams.AddParameters(Parameter(Identifier("registrationOptionsFactory")).WithType(type)); + } + else + { + var type = GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.RegistrationOptions.Syntax))); + + handler = handler.AddMembers( + FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + MethodDeclaration(item.RegistrationOptions.Syntax, Identifier("CreateRegistrationOptions")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_registrationOptionsFactory")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("capability")), + Argument(IdentifierName("clientCapabilities")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("registrationOptionsFactory")) + .WithType(type) + ); + } + } + else + { + // set capability? + } + + if (item.Capability is { }) + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType, item.Capability.Syntax)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleParams")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType, item.Capability.Syntax)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleResolve")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handleParams")) + .WithType(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType, item.Capability.Syntax)), + Parameter(Identifier("handleResolve")) + .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType, item.Capability.Syntax)) + ); + } + else + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleParams")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleResolve")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ) + ; + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handleParams")) + .WithType(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType)), + Parameter(Identifier("handleResolve")) + .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType)) + ); + } + + handler = handler.AddMembers( + ConstructorDeclaration(Identifier($"Delegating{item.JsonRpcAttributes.HandlerName}Handler")) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithParameterList(constructorParams) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.BaseConstructorInitializer, + ArgumentList() + ) + ) + .WithBody( + Block( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_registrationOptionsFactory"), + IdentifierName("registrationOptionsFactory") + ) + ), + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_handleParams"), + IdentifierName("handleParams") + ) + ), + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_handleResolve"), + IdentifierName("handleResolve") + ) + ) + ) + ), + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(responseType))), + Identifier("HandleParams") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(requestType), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_handleParams")) + .WithArgumentList( + ArgumentList( + SeparatedList( + item.Capability is { } + ? new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("Capability")), + Argument(IdentifierName("cancellationToken")) + } + : new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + + handler = handler.AddMembers( + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))), + Identifier("HandleResolve") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(resolveType), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_handleResolve")) + .WithArgumentList( + ArgumentList( + SeparatedList( + item.Capability is { } + ? new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("Capability")), + Argument(IdentifierName("cancellationToken")) + } + : new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + + + return handler; + } + + private ClassDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, RequestItem resolver) + { + TypeSyntax requestType = item.Request.Syntax; + TypeSyntax resolveType = GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ); + TypeSyntax responseType = GenericName(Identifier(item.Response.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ); + + // Special case... because the spec is awesome + if (item.Response.Symbol.Name == "CommandOrCodeActionContainer") + { + responseType = GenericName(Identifier("CodeActionContainer")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + } + + responseType = item.Response.Syntax is NullableTypeSyntax ? NullableType(responseType) : responseType; + + TypeSyntax observerType = null!; + if (item is { PartialItem: { } partialItem }) + { + observerType = GenericName("IObserver").WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))); + } + + if (item is { PartialItems: { } partialItems }) + { + observerType = GenericName("IObserver") + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + GenericName("IEnumerable") + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))) + ) + ) + ); + } + + + var handler = ClassDeclaration($"Delegating{item.JsonRpcAttributes.HandlerName}PartialHandler") + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.SealedKeyword))) + .WithHandlerIdentityConstraint(true) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType( + GenericName(Identifier($"{item.JsonRpcAttributes.HandlerName}PartialHandlerBase")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))) + ) + ) + ) + ); + + var constructorParams = ParameterList(SingletonSeparatedList(Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager")))); + + if (item.RegistrationOptions is { }) + { + if (item.Capability is { }) + { + var type = GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] { + item.RegistrationOptions.Syntax, + item.Capability.Syntax + } + ) + ) + ); + + handler = handler.AddMembers( + FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + MethodDeclaration(item.RegistrationOptions.Syntax, Identifier("CreateRegistrationOptions")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("capability")).WithType(item.Capability.Syntax), + Parameter(Identifier("clientCapabilities")).WithType(IdentifierName("ClientCapabilities")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_registrationOptionsFactory")) + .WithArgumentList( + ArgumentList( + SeparatedList( + SeparatedList( + new[] { + Argument(IdentifierName("capability")), + Argument(IdentifierName("clientCapabilities")) + } + ) + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + constructorParams = constructorParams.AddParameters(Parameter(Identifier("registrationOptionsFactory")).WithType(type)); + } + else + { + var type = GenericName(Identifier("RegistrationOptionsDelegate")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.RegistrationOptions.Syntax))); + + handler = handler.AddMembers( + FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + MethodDeclaration(item.RegistrationOptions.Syntax, Identifier("CreateRegistrationOptions")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_registrationOptionsFactory")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("capability")), + Argument(IdentifierName("clientCapabilities")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("registrationOptionsFactory")) + .WithType(type) + ); + } + } + else + { + // set capability? + } + + if (item.Capability is { }) + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAction(true, requestType, observerType, item.Capability.Syntax)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handle")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType, item.Capability.Syntax)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleResolve")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handle")) + .WithType(DelegateHelpers.CreateAction(true, requestType, observerType, item.Capability.Syntax)), + Parameter(Identifier("handleResolve")) + .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType, item.Capability.Syntax)) + ); + } + else + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAction(true, requestType, observerType)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handle")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))), + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleResolve")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ) + ; + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handle")) + .WithType(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType)), + Parameter(Identifier("handleResolve")) + .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType)) + ); + } + + handler = handler.AddMembers( + ConstructorDeclaration(Identifier($"Delegating{item.JsonRpcAttributes.HandlerName}PartialHandler")) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithParameterList(constructorParams) + .WithInitializer( + ConstructorInitializer( + SyntaxKind.BaseConstructorInitializer, + ArgumentList(SingletonSeparatedList(Argument(IdentifierName("progressManager")))) + ) + ) + .WithBody( + Block( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_registrationOptionsFactory"), + IdentifierName("registrationOptionsFactory") + ) + ), + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_handle"), + IdentifierName("handle") + ) + ), + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_handleResolve"), + IdentifierName("handleResolve") + ) + ) + ) + ), + MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Handle")) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(requestType), + Parameter(Identifier("results")).WithType(observerType), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_handle")) + .WithArgumentList( + ArgumentList( + SeparatedList( + item.Capability is { } + ? new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("results")), + Argument(IdentifierName("Capability")), + Argument(IdentifierName("cancellationToken")) + } + : new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("results")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + handler = handler.AddMembers( + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))), + Identifier("HandleResolve") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("request")).WithType(resolveType), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression(IdentifierName("_handleResolve")) + .WithArgumentList( + ArgumentList( + SeparatedList( + item.Capability is { } + ? new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("Capability")), + Argument(IdentifierName("cancellationToken")) + } + : new[] { + Argument(IdentifierName("request")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + + + return handler; + } + } +} diff --git a/src/JsonRpc.Generators/Strategies/WarnIfResponseRouterIsNotProvidedStrategy.cs b/src/JsonRpc.Generators/Strategies/WarnIfResponseRouterIsNotProvidedStrategy.cs new file mode 100644 index 000000000..cfeae839a --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/WarnIfResponseRouterIsNotProvidedStrategy.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using OmniSharp.Extensions.JsonRpc.Generators.Contexts; + +namespace OmniSharp.Extensions.JsonRpc.Generators.Strategies +{ + internal class WarnIfResponseRouterIsNotProvidedStrategy : IExtensionMethodContextGeneratorStrategy + { + public IEnumerable Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (extensionMethodContext is not { IsProxy: true }) yield break; + + var generateRequestMethods = item.JsonRpcAttributes.GenerateRequestMethods; + if (generateRequestMethods != null && ( + generateRequestMethods.Data.ConstructorArguments.Length == 0 || + generateRequestMethods.Data.ConstructorArguments[0].Kind != TypedConstantKind.Array + && generateRequestMethods.Data.ConstructorArguments[0].Value == null + || generateRequestMethods.Data.ConstructorArguments[0].Kind == TypedConstantKind.Array + && generateRequestMethods.Data.ConstructorArguments[0].Values.Length == 0 ) + && !extensionMethodContext.TypeSymbol.ContainingNamespace.ToDisplayString().StartsWith("OmniSharp.Extensions.DebugAdapter.Protocol")) + { + item.ReportDiagnostic(static type => Diagnostic.Create(GeneratorDiagnostics.NoResponseRouterProvided, type.Identifier.GetLocation(), type.Identifier.Text)); + } + } + } +} diff --git a/src/JsonRpc.Generators/StronglyTypedGenerator.cs b/src/JsonRpc.Generators/StronglyTypedGenerator.cs index 5b53c71af..a24401d97 100644 --- a/src/JsonRpc.Generators/StronglyTypedGenerator.cs +++ b/src/JsonRpc.Generators/StronglyTypedGenerator.cs @@ -1,17 +1,21 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; using SyntaxTrivia = Microsoft.CodeAnalysis.SyntaxTrivia; namespace OmniSharp.Extensions.JsonRpc.Generators { [Generator] - public class StronglyTypedGenerator : ISourceGenerator + public class StronglyTypedGenerator : CachedSourceGenerator { private static string[] RequiredUsings = new[] { "System.Collections.Generic", @@ -20,35 +24,21 @@ public class StronglyTypedGenerator : ISourceGenerator "System.Linq", }; - public void Initialize(GeneratorInitializationContext context) + protected override void Execute(GeneratorExecutionContext context, SyntaxReceiver syntaxReceiver, AddCacheSource addCacheSource, ReportCacheDiagnostic cacheDiagnostic) { - context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); - } - - public void Execute(GeneratorExecutionContext context) - { - if (!( context.SyntaxReceiver is SyntaxReceiver syntaxReceiver )) - { - return; - } - - var options = ( context.Compilation as CSharpCompilation )?.SyntaxTrees[0].Options as CSharpParseOptions; - var compilation = context.Compilation; - - var canBeResolvedSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.ICanBeResolved"); - var canHaveDataSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.ICanHaveData"); - var generateTypedDataAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.GenerateTypedDataAttribute"); - var generateContainerAttributeSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.GenerateContainerAttribute"); - var requestSymbol = compilation.GetTypeByMetadataName("MediatR.IRequest"); + var generateTypedDataAttributeSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Generation.GenerateTypedDataAttribute"); + var generateContainerAttributeSymbol = context.Compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Generation.GenerateContainerAttribute"); foreach (var classToContain in syntaxReceiver.CreateContainers) { var semanticModel = context.Compilation.GetSemanticModel(classToContain.SyntaxTree); var typeSymbol = semanticModel.GetDeclaredSymbol(classToContain); - var hasAttribute = typeSymbol?.GetAttributes().Any(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateContainerAttributeSymbol)); - if (typeSymbol == null || hasAttribute != true) continue; + var attribute = typeSymbol?.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateContainerAttributeSymbol)); + if (typeSymbol == null || attribute is null) continue; + + var containerName = attribute is { ConstructorArguments: { Length: > 0 } arguments } ? arguments[0].Value as string : null; - var container = CreateContainerClass(classToContain) + var container = CreateContainerClass(classToContain, containerName) .AddAttributeLists( AttributeList( SeparatedList( @@ -79,69 +69,83 @@ public void Execute(GeneratorExecutionContext context) } } - context.AddSource( - $"{classToContain.Identifier.Text}Container.cs", - cu.NormalizeWhitespace().SyntaxTree.GetRoot().GetText(Encoding.UTF8) + addCacheSource( + $"{containerName ?? ( classToContain.Identifier.Text + "Container" )}.cs", + classToContain, + cu.NormalizeWhitespace().GetText(Encoding.UTF8) ); } foreach (var canBeResolved in syntaxReceiver.CanBeResolved) { - var semanticModel = context.Compilation.GetSemanticModel(canBeResolved.SyntaxTree); - var typeSymbol = semanticModel.GetDeclaredSymbol(canBeResolved); - if (typeSymbol == null) continue; + var dataInterfaceName = IdentifierName("ICanBeResolved"); + CreateTypedClass(context, canBeResolved, dataInterfaceName, generateTypedDataAttributeSymbol, generateContainerAttributeSymbol, true, addCacheSource, cacheDiagnostic); + } + + foreach (var canBeResolved in syntaxReceiver.CanHaveData) + { + var dataInterfaceName = IdentifierName("ICanHaveData"); + CreateTypedClass(context, canBeResolved, dataInterfaceName, generateTypedDataAttributeSymbol, generateContainerAttributeSymbol, false, addCacheSource, cacheDiagnostic); + } + + static void CreateTypedClass( + GeneratorExecutionContext context, + ClassDeclarationSyntax candidate, + IdentifierNameSyntax dataInterfaceName, + INamedTypeSymbol? generateTypedDataAttributeSymbol, + INamedTypeSymbol? generateContainerAttributeSymbol, + bool includeHandlerIdentity, + AddCacheSource cacheItem, + ReportCacheDiagnostic cacheDiagnostic + ) + { + var semanticModel = context.Compilation.GetSemanticModel(candidate.SyntaxTree); + var typeSymbol = semanticModel.GetDeclaredSymbol(candidate); var attribute = typeSymbol?.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateTypedDataAttributeSymbol)); - var isContainer = typeSymbol?.GetAttributes().Any(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateContainerAttributeSymbol)) == true; - if (attribute == null) continue; + if (typeSymbol == null || attribute is null) return; + var container = typeSymbol.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, generateContainerAttributeSymbol)); - if (!canBeResolved.Modifiers.Any(SyntaxKind.PartialKeyword)) + if (!candidate.Modifiers.Any(SyntaxKind.PartialKeyword)) { - context.ReportDiagnostic(Diagnostic.Create(GeneratorDiagnostics.ClassMustBePartial, canBeResolved.Identifier.GetLocation())); + cacheDiagnostic(candidate, static c => Diagnostic.Create(GeneratorDiagnostics.MustBePartial, c.Identifier.GetLocation(), c.Identifier.Text)); + return; } - var property = canBeResolved.Members.OfType().Single(z => z.Identifier.Text == "Data"); - var dataInterfaceName = IdentifierName("ICanBeResolved"); - var partialClass = canBeResolved + var property = candidate.Members.OfType().Single(z => z.Identifier.Text == "Data"); + var partialClass = candidate .WithAttributeLists(List()) .WithBaseList(null) .WithMembers(List()) - .AddMembers(GetWithDataMethod(canBeResolved, TypeConstraint(NullableType(IdentifierName("HandlerIdentity"))))); + .AddMembers( + GetWithDataMethod(candidate, HandlerIdentityConstraintClause(includeHandlerIdentity, IdentifierName("TData"))), + GetFromMethod(candidate, includeHandlerIdentity) + ); var compilationMembers = new List() { }; + + var convertFromOperator = GetConvertFromOperator(candidate, dataInterfaceName); + var convertToOperator = GetConvertToOperator(candidate, dataInterfaceName); // remove the data property - var typedClass = canBeResolved - .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter("T")))) - .WithMembers(canBeResolved.Members.Replace(property, GetPropertyImpl(property, dataInterfaceName).WithType(IdentifierName("T")))) + var typedClass = candidate + .WithHandlerIdentityConstraint(includeHandlerIdentity) + .WithMembers(candidate.Members.Replace(property, GetPropertyImpl(property, dataInterfaceName).WithType(IdentifierName("T")))) .AddMembers( - GetWithDataMethod(canBeResolved, TypeConstraint(NullableType(IdentifierName("HandlerIdentity")))), + GetWithDataMethod(candidate, HandlerIdentityConstraintClause(includeHandlerIdentity, IdentifierName("TData"))), GetExplicitProperty(property, dataInterfaceName), - GetJDataProperty(), - GetConvertFromOperator(canBeResolved, dataInterfaceName), - GetConvertToOperator(canBeResolved, dataInterfaceName) + GetJDataProperty(dataInterfaceName), + convertFromOperator, + convertToOperator, + GetGenericFromMethod(candidate) ) .WithAttributeLists( List( - canBeResolved.AttributeLists - .Where(z => !z.ToFullString().Contains("Method") && !z.ToFullString().Contains("GenerateTypedData")) + candidate.AttributeLists + .Where(z => !z.ContainsAttribute("Method") && !z.ContainsAttribute("GenerateTypedData")) ) ) .WithBaseList(BaseList(SingletonSeparatedList(SimpleBaseType(dataInterfaceName)))) - .WithConstraintClauses( - SingletonList( - TypeParameterConstraintClause(IdentifierName("T")) - .WithConstraints( - SeparatedList( - new SyntaxNodeOrToken[] { - TypeConstraint(NullableType(IdentifierName("HandlerIdentity"))), - Token(SyntaxKind.CommaToken), - ConstructorConstraint() - } - ) - ) - ) - ) .AddAttributeLists( AttributeList( SeparatedList( @@ -152,27 +156,15 @@ public void Execute(GeneratorExecutionContext context) ) ) ) - .WithLeadingTrivia(canBeResolved.GetLeadingTrivia().Where(z => !z.ToString().Contains("#nullable"))) - .WithTrailingTrivia(canBeResolved.GetTrailingTrivia().Where(z => !z.ToString().Contains("#nullable"))) +// .WithLeadingTrivia(candidate.GetLeadingTrivia().Where(z => !z.ToString().Contains("#nullable"))) +// .WithTrailingTrivia(candidate.GetTrailingTrivia().Where(z => !z.ToString().Contains("#nullable"))) ; - if (isContainer) + if (container is { }) { - var typedContainer = CreateContainerClass(typedClass) - .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter("T")))) - .WithConstraintClauses( - SingletonList( - TypeParameterConstraintClause(IdentifierName("T")) - .WithConstraints( - SeparatedList( - new TypeParameterConstraintSyntax[] { - TypeConstraint(NullableType(IdentifierName("HandlerIdentity"))), - ConstructorConstraint() - } - ) - ) - ) - ); + var containerName = container is { ConstructorArguments: { Length: > 0 } arguments } ? arguments[0].Value as string : null; + var typedContainer = CreateContainerClass(typedClass, containerName) + .WithHandlerIdentityConstraint(includeHandlerIdentity); var typedArgumentList = TypeArgumentList(SingletonSeparatedList(IdentifierName("T"))); typedContainer = typedContainer @@ -205,11 +197,11 @@ public void Execute(GeneratorExecutionContext context) ArgumentList( SingletonSeparatedList( Argument( - SimpleLambdaExpression(Parameter(Identifier("z"))) + SimpleLambdaExpression(Parameter(Identifier("value"))) .WithExpressionBody( CastExpression( - IdentifierName(canBeResolved.Identifier), - IdentifierName("z") + IdentifierName(candidate.Identifier), + IdentifierName("value") ) ) ) @@ -222,6 +214,7 @@ public void Execute(GeneratorExecutionContext context) ) ) ) + .MakeMethodNullable(IdentifierName("container")) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken) ) @@ -231,7 +224,7 @@ public void Execute(GeneratorExecutionContext context) } var cu = CompilationUnit() - .WithUsings(canBeResolved.SyntaxTree.GetCompilationUnitRoot().Usings) + .WithUsings(candidate.SyntaxTree.GetCompilationUnitRoot().Usings) .AddMembers( NamespaceDeclaration(ParseName(typeSymbol.ContainingNamespace.ToDisplayString())) .AddMembers(partialClass, typedClass) @@ -249,14 +242,15 @@ public void Execute(GeneratorExecutionContext context) } } - context.AddSource( - $"{canBeResolved.Identifier.Text}Typed.cs", - cu.NormalizeWhitespace().SyntaxTree.GetRoot().GetText(Encoding.UTF8) + cacheItem( + $"{candidate.Identifier.Text}Typed.cs", + candidate, + cu.NormalizeWhitespace().GetText(Encoding.UTF8) ); } } - private static MethodDeclarationSyntax GetWithDataMethod(ClassDeclarationSyntax syntax, TypeParameterConstraintSyntax constraintSyntax) + private static MethodDeclarationSyntax GetWithDataMethod(ClassDeclarationSyntax syntax, SyntaxList constraintSyntax) { return MethodDeclaration( GenericName(Identifier(syntax.Identifier.Text)) @@ -266,19 +260,15 @@ private static MethodDeclarationSyntax GetWithDataMethod(ClassDeclarationSyntax .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("TData"))))) .WithParameterList(ParameterList(SingletonSeparatedList(Parameter(Identifier("data")).WithType(IdentifierName("TData"))))) - .WithConstraintClauses( - SingletonList( - TypeParameterConstraintClause(IdentifierName("TData")) - .WithConstraints(SeparatedList(new[] { constraintSyntax, ConstructorConstraint() })) - ) - ) + .WithConstraintClauses(List(constraintSyntax)) .WithBody( Block( SingletonList( ReturnStatement( - ObjectCreationExpression(GenericName(Identifier(syntax.Identifier.Text)) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("TData")))) - ) + ObjectCreationExpression( + GenericName(Identifier(syntax.Identifier.Text)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("TData")))) + ) .WithInitializer( InitializerExpression( SyntaxKind.ObjectInitializerExpression, @@ -301,6 +291,46 @@ private static MethodDeclarationSyntax GetWithDataMethod(ClassDeclarationSyntax ); } + private static MethodDeclarationSyntax GetGenericFromMethod(ClassDeclarationSyntax syntax) + { + return MethodDeclaration( + GenericName(Identifier(syntax.Identifier.Text)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))), Identifier("From") + ) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("item")).WithType(IdentifierName(syntax.Identifier.Text)) + ) + ) + ) + .WithExpressionBody(ArrowExpressionClause(IdentifierName("item"))) + .MakeMethodNullable(IdentifierName("item")) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } + + private static MethodDeclarationSyntax GetFromMethod(ClassDeclarationSyntax syntax, bool includeHandlerIdentity) + { + return MethodDeclaration(IdentifierName(syntax.Identifier.Text), Identifier("From")) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithHandlerIdentityConstraint(includeHandlerIdentity) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("item")) + .WithType( + GenericName(Identifier(syntax.Identifier.Text)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))) + ) + ) + ) + ) + .WithExpressionBody(ArrowExpressionClause(IdentifierName("item"))) + .MakeMethodNullable(IdentifierName("item")) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } + private static IEnumerable GetMapping(ClassDeclarationSyntax syntax, IdentifierNameSyntax? paramName) { return syntax.Members.OfType() @@ -367,6 +397,7 @@ private static ConversionOperatorDeclarationSyntax GetConvertToOperator(ClassDec ) ) ) + .MakeMethodNullable(paramName) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); } @@ -444,7 +475,7 @@ private static PropertyDeclarationSyntax GetExplicitProperty(PropertyDeclaration ); } - private static PropertyDeclarationSyntax GetJDataProperty() + private static PropertyDeclarationSyntax GetJDataProperty(IdentifierNameSyntax interfaceName) { return PropertyDeclaration(NullableType(IdentifierName("JToken")), Identifier("JData")) .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword))) @@ -459,7 +490,7 @@ private static PropertyDeclarationSyntax GetJDataProperty() SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression( CastExpression( - IdentifierName("ICanBeResolved"), + interfaceName, ThisExpression() ) ), @@ -477,7 +508,7 @@ private static PropertyDeclarationSyntax GetJDataProperty() SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression( CastExpression( - IdentifierName("ICanBeResolved"), + interfaceName, ThisExpression() ) ), @@ -498,7 +529,7 @@ private static PropertyDeclarationSyntax GetJDataProperty() static PropertyDeclarationSyntax GetPropertyImpl(PropertyDeclarationSyntax syntax, IdentifierNameSyntax dataInterfaceName) { - var canBeResolvedAccess = MemberAccessExpression( + var memberAccess = MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression(CastExpression(dataInterfaceName, ThisExpression())), IdentifierName("Data") @@ -513,7 +544,7 @@ static PropertyDeclarationSyntax GetPropertyImpl(PropertyDeclarationSyntax synta PostfixUnaryExpression( SyntaxKind.SuppressNullableWarningExpression, ConditionalAccessExpression( - canBeResolvedAccess, + memberAccess, InvocationExpression( MemberBindingExpression( GenericName(Identifier("ToObject")) @@ -535,7 +566,7 @@ static PropertyDeclarationSyntax GetPropertyImpl(PropertyDeclarationSyntax synta ArrowExpressionClause( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, - canBeResolvedAccess, + memberAccess, InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, @@ -561,23 +592,29 @@ static PropertyDeclarationSyntax GetPropertyImpl(PropertyDeclarationSyntax synta ); } - private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSyntax syntax) + private static ClassDeclarationSyntax CreateContainerClass(TypeDeclarationSyntax syntax, string? name) { TypeSyntax typeName = IdentifierName(syntax.Identifier.Text); - var classIdentifier = Identifier($"{syntax.Identifier.Text}Container"); - TypeSyntax className = IdentifierName($"{syntax.Identifier.Text}Container"); + var classIdentifier = Identifier(name ?? $"{syntax.Identifier.Text}Container"); + TypeSyntax className = IdentifierName(name ?? $"{syntax.Identifier.Text}Container"); if (syntax.Arity > 0) { typeName = GenericName(syntax.Identifier.Text) .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); - className = GenericName($"{syntax.Identifier.Text}Container") + className = GenericName(name ?? $"{syntax.Identifier.Text}Container") .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); } var typeArgumentList = TypeArgumentList(SingletonSeparatedList(typeName)); + var modifiers = syntax.Modifiers; + if (!modifiers.Any(z => z.IsKind(SyntaxKind.PartialKeyword))) + { + modifiers = modifiers.Add(Token(SyntaxKind.PartialKeyword)); + } + return ClassDeclaration(classIdentifier) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword))) + .WithModifiers(modifiers) .WithBaseList( BaseList( SingletonSeparatedList( @@ -643,6 +680,14 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, ArgumentList(SingletonSeparatedList(Argument(IdentifierName("items"))))) ) .WithBody(Block()), + AddConversionBody( + typeName, + Identifier("IEnumerable"), + MethodDeclaration( + className, + Identifier("From") + ) + ), AddConversionBody( typeName, Identifier("List"), @@ -656,7 +701,7 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta AddConversionBody( typeName, Identifier("List"), - MethodDeclaration(className, Identifier("Create")) + MethodDeclaration(className, Identifier("From")) ) .WithParameterList(ParameterList(SingletonSeparatedList(ArrayParameter(typeName).WithModifiers(TokenList(Token(SyntaxKind.ParamsKeyword)))))), AddConversionBody( @@ -672,7 +717,7 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta Identifier("Collection"), MethodDeclaration( className, - Identifier("Create") + Identifier("From") ) ), AddConversionBody( @@ -688,7 +733,7 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta typeName, Identifier("List"), MethodDeclaration( className, - Identifier("Create") + Identifier("From") ) ), AddConversionBody( @@ -706,7 +751,7 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta Identifier("List"), MethodDeclaration( className, - Identifier("Create") + Identifier("From") ) ) .WithParameterList(ImmutableArrayParameters(typeName)), @@ -724,7 +769,7 @@ private static ClassDeclarationSyntax CreateContainerClass(ClassDeclarationSynta typeName, Identifier("ImmutableList"), MethodDeclaration( className, - Identifier("Create") + Identifier("From") ) ) } @@ -753,7 +798,7 @@ static ParameterListSyntax ImmutableArrayParameters(TypeSyntax typeName) typeName ) ) - ) + ).EnsureNullable() ) ) ); @@ -783,6 +828,8 @@ static ParameterSyntax ArrayParameter(TypeSyntax typeName) static BaseMethodDeclarationSyntax AddConversionBody(TypeSyntax typeName, SyntaxToken collectionName, BaseMethodDeclarationSyntax syntax) { + TypeSyntax objectName = syntax is ConversionOperatorDeclarationSyntax d ? d.Type : syntax is MethodDeclarationSyntax m ? m.ReturnType : null!; + objectName = objectName.EnsureNotNullable(); return syntax .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) .WithParameterList( @@ -799,14 +846,14 @@ static BaseMethodDeclarationSyntax AddConversionBody(TypeSyntax typeName, Syntax typeName ) ) - ) + ).EnsureNullable() ) ) ) ) .WithExpressionBody( ArrowExpressionClause( - ObjectCreationExpression(syntax is ConversionOperatorDeclarationSyntax d ? d.Type : syntax is MethodDeclarationSyntax m ? m.ReturnType : null!) + ObjectCreationExpression(objectName) .WithArgumentList( ArgumentList( SingletonSeparatedList( @@ -818,33 +865,53 @@ static BaseMethodDeclarationSyntax AddConversionBody(TypeSyntax typeName, Syntax ) ) ) + .MakeMethodNullable(IdentifierName("items")) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken) ); } } - /// - /// Created on demand before each generation pass - /// - internal class SyntaxReceiver : ISyntaxReceiver + public StronglyTypedGenerator() : base(() => new SyntaxReceiver(Cache)) + { + + } + public static CacheContainer Cache = new (); + public class SyntaxReceiver : SyntaxReceiverCache { public List CanBeResolved { get; } = new(); public List CanHaveData { get; } = new(); - public List CreateContainers { get; } = new(); + public List CreateContainers { get; } = new(); + + public override string? GetKey(TypeDeclarationSyntax syntax) + { + var hasher = new CacheKeyHasher(); + hasher.Append(syntax.SyntaxTree.FilePath); + hasher.Append(syntax.Identifier.Text); + hasher.Append(syntax.TypeParameterList); + hasher.Append(syntax.AttributeLists); + hasher.Append(syntax.BaseList); + return hasher; + } /// /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation /// - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + public override void OnVisitNode(TypeDeclarationSyntax syntaxNode) { // any field with at least one attribute is a candidate for property generation + + if (syntaxNode is StructDeclarationSyntax structDeclarationSyntax) + { + if (structDeclarationSyntax.AttributeLists.ContainsAttribute("GenerateContainer")) + { + CreateContainers.Add(structDeclarationSyntax); + } + } + if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax) { - if (classDeclarationSyntax.AttributeLists - .SelectMany(z => z.Attributes) - .Any(z => z.Name.ToFullString().Contains("GenerateContainer")) - ) + if (classDeclarationSyntax.AttributeLists.ContainsAttribute("GenerateContainer")) { CreateContainers.Add(classDeclarationSyntax); } @@ -855,18 +922,19 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode) classDeclarationSyntax.Members.OfType().Any(z => z.Identifier.Text == "Data") ) { - if (classDeclarationSyntax.BaseList.Types.Any(z => z.ToString().EndsWith("ICanBeResolved"))) + if (classDeclarationSyntax.BaseList.Types.Any(z => z.Type.GetSyntaxName() == "ICanBeResolved")) { CanBeResolved.Add(classDeclarationSyntax); } - - if (classDeclarationSyntax.BaseList.Types.Any(z => z.ToString().EndsWith("ICanHaveData"))) + else if (classDeclarationSyntax.BaseList.Types.Any(z => z.Type.GetSyntaxName() == "ICanHaveData")) { CanHaveData.Add(classDeclarationSyntax); } } } } + + public SyntaxReceiver(CacheContainer cache) : base(cache) { } } } } diff --git a/src/JsonRpc.Generators/SymbolExtensions.cs b/src/JsonRpc.Generators/SymbolExtensions.cs new file mode 100644 index 000000000..501a6dcc4 --- /dev/null +++ b/src/JsonRpc.Generators/SymbolExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace OmniSharp.Extensions.JsonRpc.Generators +{ + static class SymbolExtensions + { + public static AttributeData? GetAttribute(this INamedTypeSymbol symbol, INamedTypeSymbol? attributeSymbol) + { + if (attributeSymbol is null) return null; + return symbol?.GetAttributes().FirstOrDefault(z => SymbolEqualityComparer.Default.Equals(z.AttributeClass, attributeSymbol)); + } + + public static R? ReturnIfNotNull(this T? value, Func func) + where T : class + { + return value is null ? default : func(value); + } + } +} diff --git a/src/JsonRpc.Testing/JsonRpcTestOptions.cs b/src/JsonRpc.Testing/JsonRpcTestOptions.cs index 16de931e6..13df29487 100644 --- a/src/JsonRpc.Testing/JsonRpcTestOptions.cs +++ b/src/JsonRpc.Testing/JsonRpcTestOptions.cs @@ -26,7 +26,7 @@ public JsonRpcTestOptions(ILoggerFactory clientLoggerFactory, ILoggerFactory ser public ILoggerFactory ServerLoggerFactory { get; internal set; } = NullLoggerFactory.Instance; public TimeSpan WaitTime { get; internal set; } = TimeSpan.FromMilliseconds(50); public TimeSpan Timeout { get; internal set; } = TimeSpan.FromMilliseconds(500); - public TimeSpan CancellationTimeout { get; internal set; } = TimeSpan.FromMinutes(5); + public TimeSpan CancellationTimeout { get; internal set; } = TimeSpan.FromSeconds(50); public PipeOptions DefaultPipeOptions { get; internal set; } = new PipeOptions(); public IEnumerable Assemblies { get; set; } = Enumerable.Empty(); } diff --git a/src/JsonRpc/CancelParams.cs b/src/JsonRpc/CancelParams.cs index bba0faa1d..966dc8dcd 100644 --- a/src/JsonRpc/CancelParams.cs +++ b/src/JsonRpc/CancelParams.cs @@ -3,7 +3,7 @@ namespace OmniSharp.Extensions.JsonRpc { [Method(JsonRpcNames.CancelRequest)] - public class CancelParams : IRequest + public partial class CancelParams : IRequest { /// /// The request id to cancel. diff --git a/src/JsonRpc/Generation/GenerateHandlerAttribute.cs b/src/JsonRpc/Generation/GenerateHandlerAttribute.cs new file mode 100644 index 000000000..4a84e7fc2 --- /dev/null +++ b/src/JsonRpc/Generation/GenerateHandlerAttribute.cs @@ -0,0 +1,25 @@ +using System; +using System.Diagnostics; + +namespace OmniSharp.Extensions.JsonRpc.Generation +{ + /// + /// Generates IXyzHandler and XyzHandlerBase classes for a given request object + /// + /// + /// Efforts will be made to make this available for consumers once source generators land + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class GenerateHandlerAttribute : Attribute + { + public GenerateHandlerAttribute(string? @namespace = null) { } + + public string? Name { get; init; } + + /// + /// Allow the request to be derived and create methods that take a request type argument. + /// + public bool AllowDerivedRequests { get; set; } + } +} diff --git a/src/JsonRpc/Generation/GenerateHandlerMethodsAttribute.cs b/src/JsonRpc/Generation/GenerateHandlerMethodsAttribute.cs index dee2fde23..5ae6f573e 100644 --- a/src/JsonRpc/Generation/GenerateHandlerMethodsAttribute.cs +++ b/src/JsonRpc/Generation/GenerateHandlerMethodsAttribute.cs @@ -18,10 +18,5 @@ public GenerateHandlerMethodsAttribute(params Type[] registryTypes) } public string? MethodName { get; set; } - - /// - /// Allow the request to be derived and create methods that take a request type argument. - /// - public bool AllowDerivedRequests { get; set; } } } diff --git a/src/JsonRpc/HandlerTypeDescriptorProvider.cs b/src/JsonRpc/HandlerTypeDescriptorProvider.cs index 2c889d005..ae35da22f 100644 --- a/src/JsonRpc/HandlerTypeDescriptorProvider.cs +++ b/src/JsonRpc/HandlerTypeDescriptorProvider.cs @@ -64,12 +64,12 @@ public static Type GetHandlerInterface(Type type) } } - internal static Type? UnwrapGenericType(Type genericType, Type type) => + internal static Type? UnwrapGenericType(Type genericType, Type type, int arity = 0) => type.GetTypeInfo() .ImplementedInterfaces .FirstOrDefault(x => x.GetTypeInfo().IsGenericType && x.GetTypeInfo().GetGenericTypeDefinition() == genericType) ?.GetTypeInfo() - ?.GetGenericArguments()[0]; + ?.GetGenericArguments()[arity]; } class HandlerTypeDescriptorProvider : IHandlerTypeDescriptorProvider diff --git a/src/JsonRpc/IJsonRpcHandler.cs b/src/JsonRpc/IJsonRpcHandler.cs index de25fa54f..d52448871 100644 --- a/src/JsonRpc/IJsonRpcHandler.cs +++ b/src/JsonRpc/IJsonRpcHandler.cs @@ -1,9 +1,19 @@ -namespace OmniSharp.Extensions.JsonRpc +using MediatR; + +namespace OmniSharp.Extensions.JsonRpc { /// - /// A simple marker interface to use for storing handlings (which will be cast out later) + /// A simple marker interface to use for storing handling's (which will be cast out later) /// public interface IJsonRpcHandler { } + + /// + /// Marker interface for source generation to properly know that this IRequest is a real request and not a notification + /// + public interface IJsonRpcRequest : IRequest + { + + } } diff --git a/src/JsonRpc/IJsonRpcRequestHandler.cs b/src/JsonRpc/IJsonRpcRequestHandler.cs index fbb5eb751..3a885c86b 100644 --- a/src/JsonRpc/IJsonRpcRequestHandler.cs +++ b/src/JsonRpc/IJsonRpcRequestHandler.cs @@ -3,11 +3,11 @@ namespace OmniSharp.Extensions.JsonRpc { /// - /// + /// /// Client --> --> /// | /// Server <-- <-- - /// + /// /// /// /// @@ -17,11 +17,11 @@ public interface IJsonRpcRequestHandler : IRequestHandle } /// - /// + /// /// Client --> --> /// | /// Server <-- <-- - /// + /// /// /// public interface IJsonRpcRequestHandler : IRequestHandler, IJsonRpcHandler diff --git a/src/JsonRpc/JsonRpcHandlerCollectionExtensions.cs b/src/JsonRpc/JsonRpcHandlerCollectionExtensions.cs index 65695712e..f66ccc2ab 100644 --- a/src/JsonRpc/JsonRpcHandlerCollectionExtensions.cs +++ b/src/JsonRpc/JsonRpcHandlerCollectionExtensions.cs @@ -12,19 +12,19 @@ public static void Populate(this IJsonRpcHandlerCollection collection, IResolver { switch (item) { - case JsonRpcHandlerFactoryDescription factory when !(factory.Method is null): + case JsonRpcHandlerFactoryDescription { Method: { Length: > 0 } } factory: handlersManager.Add(factory.Method, factory.HandlerFactory(resolverContext), factory.Options); continue; case JsonRpcHandlerFactoryDescription factory: handlersManager.Add(factory.HandlerFactory(resolverContext), factory.Options); continue; - case JsonRpcHandlerTypeDescription type when !(type.Method is null): - handlersManager.Add(type.Method, (resolverContext.Resolve(type.HandlerType) as IJsonRpcHandler)!, type.Options); + case JsonRpcHandlerTypeDescription { Method: { Length: > 0 } } type: + handlersManager.Add(type.Method, ( resolverContext.Resolve(type.HandlerType) as IJsonRpcHandler )!, type.Options); continue; case JsonRpcHandlerTypeDescription type: - handlersManager.Add((resolverContext.Resolve(type.HandlerType) as IJsonRpcHandler)!, type.Options); + handlersManager.Add(( resolverContext.Resolve(type.HandlerType) as IJsonRpcHandler )!, type.Options); continue; - case JsonRpcHandlerInstanceDescription instance when !(instance.Method is null): + case JsonRpcHandlerInstanceDescription { Method: { Length: > 0 } } instance: handlersManager.Add(instance.Method, instance.HandlerInstance, instance.Options); continue; case JsonRpcHandlerInstanceDescription instance: diff --git a/src/JsonRpc/NotificationHandler.cs b/src/JsonRpc/NotificationHandler.cs index 256d44e11..364a6ad55 100644 --- a/src/JsonRpc/NotificationHandler.cs +++ b/src/JsonRpc/NotificationHandler.cs @@ -8,19 +8,15 @@ namespace OmniSharp.Extensions.JsonRpc public static class NotificationHandler { public static DelegatingHandlers.Notification For(Action handler) - where TParams : IRequest => - new DelegatingHandlers.Notification(handler); + where TParams : IRequest => new(handler); public static DelegatingHandlers.Notification For(Func handler) - where TParams : IRequest => - new DelegatingHandlers.Notification(handler); + where TParams : IRequest => new(handler); public static DelegatingHandlers.Notification For(Action handler) - where TParams : IRequest => - new DelegatingHandlers.Notification((p, ct) => handler(p)); + where TParams : IRequest => new((p, ct) => handler(p)); public static DelegatingHandlers.Notification For(Func handler) - where TParams : IRequest => - new DelegatingHandlers.Notification((p, ct) => handler(p)); + where TParams : IRequest => new((p, ct) => handler(p)); } } diff --git a/src/JsonRpc/RequestHandler.cs b/src/JsonRpc/RequestHandler.cs index d5a9b6497..66a5d0854 100644 --- a/src/JsonRpc/RequestHandler.cs +++ b/src/JsonRpc/RequestHandler.cs @@ -7,24 +7,16 @@ namespace OmniSharp.Extensions.JsonRpc { public static class RequestHandler { - public static DelegatingHandlers.Request For( - Func> handler - ) - where TParams : IRequest => - new DelegatingHandlers.Request(handler); + public static DelegatingHandlers.Request For(Func> handler) + where TParams : IRequest => new(handler); - public static DelegatingHandlers.Request For( - Func> handler - ) - where TParams : IRequest => - new DelegatingHandlers.Request(handler); + public static DelegatingHandlers.Request For(Func> handler) + where TParams : IRequest => new(handler); public static DelegatingHandlers.Request For(Func handler) - where TParams : IRequest => - new DelegatingHandlers.Request(handler); + where TParams : IRequest => new(handler); public static DelegatingHandlers.Request For(Func handler) - where TParams : IRequest => - new DelegatingHandlers.Request(handler); + where TParams : IRequest => new(handler); } } diff --git a/src/Protocol/AbstractHandlers.cs b/src/Protocol/AbstractHandlers.cs index 1b47f19f5..355a58ce2 100644 --- a/src/Protocol/AbstractHandlers.cs +++ b/src/Protocol/AbstractHandlers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; @@ -15,105 +16,232 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { public static class AbstractHandlers { - public abstract class Request : - IJsonRpcRequestHandler, - IRegistration, ICapability - where TParams : IRequest + public abstract class Base : + IRegistration where TRegistrationOptions : class, new() where TCapability : ICapability { - private readonly TRegistrationOptions _registrationOptions; + protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; protected TCapability Capability { get; private set; } = default!; + protected internal abstract TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities); + + TRegistrationOptions IRegistration.GetRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) + { + // ReSharper disable twice ConditionIsAlwaysTrueOrFalse + if (RegistrationOptions is not null && Capability is not null) return RegistrationOptions; + Capability = capability; + return RegistrationOptions = CreateRegistrationOptions(capability, clientCapabilities); + } + } + + public abstract class BaseCapability : + ICapability + where TCapability : ICapability + { + protected TCapability Capability { get; private set; } = default!; + + void ICapability.SetCapability(TCapability capability) + { + Capability = capability; + } + } - protected Request(TRegistrationOptions registrationOptions) => _registrationOptions = registrationOptions; + public abstract class Base : + IRegistration + where TRegistrationOptions : class, new() + { + protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; + protected abstract TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities); + TRegistrationOptions IRegistration.GetRegistrationOptions(ClientCapabilities clientCapabilities) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (RegistrationOptions is not null) return RegistrationOptions; + return RegistrationOptions = CreateRegistrationOptions(clientCapabilities); + } + } + + public abstract class Request : + IJsonRpcRequestHandler + where TParams : IRequest + { public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => Capability = capability; + public abstract class Request : + Base, + IJsonRpcRequestHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); } - public abstract class PartialResult : - IJsonRpcRequestHandler, - IRegistration, ICapability - where TParams : IPartialItemRequest - where TResponse : class, new() + public abstract class Request : + Base, + IJsonRpcRequestHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class RequestCapability : + BaseCapability, + IJsonRpcRequestHandler + where TParams : IRequest + where TCapability : ICapability + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class PartialResult : + Base, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemRequest + where TResponse : class? where TRegistrationOptions : class, new() where TCapability : ICapability { - private readonly TRegistrationOptions _registrationOptions; private readonly IProgressManager _progressManager; - private readonly Func _factory; - protected TCapability Capability { get; private set; } = default!; + private readonly Func _factory; + + protected PartialResult(IProgressManager progressManager, Func factory) + { + _progressManager = progressManager; + _factory = factory; + } - protected PartialResult( - TRegistrationOptions registrationOptions, - IProgressManager progressManager, - Func factory + async Task IRequestHandler.Handle( + TParams request, + CancellationToken cancellationToken ) { - _registrationOptions = registrationOptions; + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + Handle(request, observer, cancellationToken); + await observer; + return _factory(default(TItem)); + } + + var subject = new AsyncSubject(); + // in the event nothing is emitted... + subject.OnNext(default!); + Handle(request, subject, cancellationToken); + return _factory(await subject); + } + + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); + } + + public abstract class PartialResult : + Base, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemRequest + where TResponse : class? + where TRegistrationOptions : class, new() + { + private readonly IProgressManager _progressManager; + private readonly Func _factory; + + protected PartialResult(IProgressManager progressManager, Func factory) + { _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle( + async Task IRequestHandler.Handle( TParams request, CancellationToken cancellationToken ) { var observer = _progressManager.For(request, cancellationToken); - if (observer == ProgressObserver.Noop) + if (observer != ProgressObserver.Noop) { Handle(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(default); } - var subject = new AsyncSubject(); + var subject = new AsyncSubject(); // in the event nothing is emitted... subject.OnNext(default!); Handle(request, subject, cancellationToken); return _factory(await subject); } - protected abstract void Handle( - TParams request, IObserver results, + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); + } + + public abstract class PartialResultCapability : + BaseCapability, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemRequest + where TResponse : class? + where TCapability : ICapability + { + private readonly IProgressManager _progressManager; + private readonly Func _factory; + + protected PartialResultCapability(IProgressManager progressManager, Func factory) + { + _progressManager = progressManager; + _factory = factory; + } + + async Task IRequestHandler.Handle( + TParams request, CancellationToken cancellationToken - ); + ) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + Handle(request, observer, cancellationToken); + await observer; + return _factory(default); + } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => Capability = capability; + var subject = new AsyncSubject(); + // in the event nothing is emitted... + subject.OnNext(default!); + Handle(request, subject, cancellationToken); + return _factory(await subject); + } + + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); } - public abstract class PartialResults : - IJsonRpcRequestHandler, - IRegistration, ICapability - where TParams : IPartialItemsRequest - where TResponse : IEnumerable?, new() + public abstract class PartialResults : + Base, + IJsonRpcRequestHandler + where TParams : IPartialItemsRequest + where TResponse : IEnumerable? where TRegistrationOptions : class, new() where TCapability : ICapability { - private readonly TRegistrationOptions _registrationOptions; private readonly IProgressManager _progressManager; - private readonly Func, TResponse> _factory; - protected TCapability Capability { get; private set; } = default!; + private readonly Func, TResponse?> _factory; - protected PartialResults(TRegistrationOptions registrationOptions, IProgressManager progressManager, Func, TResponse> factory) + protected PartialResults(IProgressManager progressManager, Func, TResponse?> factory) { - _registrationOptions = registrationOptions; _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver.Noop) { Handle(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(Enumerable.Empty()); } var subject = new Subject>(); @@ -129,33 +257,121 @@ async Task IRequestHandler.Handle(TParams request } protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); - - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => Capability = capability; } - public abstract class Notification : - IJsonRpcRequestHandler, - IRegistration, ICapability - where TParams : IRequest + public abstract class PartialResults : + Base, + IJsonRpcRequestHandler + where TParams : IPartialItemsRequest + where TResponse : IEnumerable? where TRegistrationOptions : class, new() + { + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; + + protected PartialResults(IProgressManager progressManager, Func, TResponse?> factory) + { + _progressManager = progressManager; + _factory = factory; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + Handle(request, observer, cancellationToken); + await observer; + return _factory(Enumerable.Empty()); + } + + var subject = new Subject>(); + var task = subject.Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .ToTask(cancellationToken); + Handle(request, subject, cancellationToken); + return _factory(await task.ConfigureAwait(false)); + } + + protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); + } + public abstract class PartialResultsCapability : + BaseCapability, + IJsonRpcRequestHandler + where TParams : IPartialItemsRequest + where TResponse : IEnumerable? where TCapability : ICapability { - private readonly TRegistrationOptions _registrationOptions; - protected TCapability Capability { get; private set; } = default!; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; - protected Notification(TRegistrationOptions registrationOptions) => _registrationOptions = registrationOptions; + protected PartialResultsCapability(IProgressManager progressManager, Func, TResponse?> factory) + { + _progressManager = progressManager; + _factory = factory; + } - public Task Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { - Handle(request); - return Unit.Task; + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + Handle(request, observer, cancellationToken); + await observer; + return _factory(Enumerable.Empty()); + } + + var subject = new Subject>(); + var task = subject.Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .ToTask(cancellationToken); + Handle(request, subject, cancellationToken); + return _factory(await task.ConfigureAwait(false)); } - protected abstract void Handle(TParams request); + protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); + } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => Capability = capability; + public abstract class Notification : IJsonRpcRequestHandler + where TParams : IRequest + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class Notification : + Base, + IJsonRpcRequestHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class Notification : + Base, + IJsonRpcRequestHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class NotificationCapability : + BaseCapability, + IJsonRpcRequestHandler + where TParams : IRequest + where TCapability : ICapability + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); } } } diff --git a/src/Protocol/Attributes.cs b/src/Protocol/Attributes.cs deleted file mode 100644 index e324f76d0..000000000 --- a/src/Protocol/Attributes.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; - -namespace OmniSharp.Extensions.LanguageServer.Protocol -{ - /// - /// Allows generating a typed counterpart to any model that implements - /// - /// - /// Efforts will be made to make this available for consumers once source generators land - /// - [AttributeUsage(AttributeTargets.Class)] - [Conditional("CodeGeneration")] - public class GenerateTypedDataAttribute : Attribute { } - - /// - /// Allows generating a typed container counterpart to any model that implements - /// - /// - /// Efforts will be made to make this available for consumers once source generators land - /// - [AttributeUsage(AttributeTargets.Class)] - [Conditional("CodeGeneration")] - public class GenerateContainerAttribute : Attribute { } - - /// - /// Generates work done on a registration options object - /// - [AttributeUsage(AttributeTargets.Class)] - [Conditional("CodeGeneration")] - public class WorkDoneProgressAttribute : Attribute { } - - /// - /// Generates text document on a registration options object - /// - [AttributeUsage(AttributeTargets.Class)] - [Conditional("CodeGeneration")] - public class TextDocumentAttribute : Attribute { } - - /// - /// Defines a converter that is used for converting from dynamic to static - /// - [AttributeUsage(AttributeTargets.Class)] -// [Conditional("CodeGeneration")] - public class RegistrationOptionsAttribute : Attribute - { - public string ServerCapabilitiesKey { get; } - - public RegistrationOptionsAttribute(string serverCapabilitiesKey) - { - ServerCapabilitiesKey = serverCapabilitiesKey; - } - } - - /// - /// Defines a converter that is used for converting from dynamic to static - /// - [AttributeUsage(AttributeTargets.Class)] -// [Conditional("CodeGeneration")] - public class RegistrationOptionsConverterAttribute : Attribute - { - public Type ConverterType { get; } - - public RegistrationOptionsConverterAttribute(Type converterType) - { - ConverterType = converterType; - } - } -} diff --git a/src/Protocol/BuiltInAttribute.cs b/src/Protocol/BuiltInAttribute.cs new file mode 100644 index 000000000..58ae766b1 --- /dev/null +++ b/src/Protocol/BuiltInAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + /// + /// Identifies this handler as a "builtin" handler that that will be dropped if a non-built in one is given + /// + [AttributeUsage(AttributeTargets.Class)] + public class BuiltInAttribute : Attribute + { + } +} diff --git a/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs b/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs deleted file mode 100644 index 465b5a4d9..000000000 --- a/src/Protocol/Client/Capabilities/CallHierarchyCapability.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the `textDocument/callHierarchy`. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CallHierarchy))] - public class CallHierarchyCapability : DynamicCapability, ConnectedCapability, - ConnectedCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/CodeActionCapability.cs b/src/Protocol/Client/Capabilities/CodeActionCapability.cs deleted file mode 100644 index d51aa6da7..000000000 --- a/src/Protocol/Client/Capabilities/CodeActionCapability.cs +++ /dev/null @@ -1,51 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeAction))] - public class CodeActionCapability : DynamicCapability, ConnectedCapability - { - /// - /// The client support code action literals as a valid - /// response of the `textDocument/codeAction` request. - /// - /// Since 3.8.0 - /// - [Optional] - public CodeActionLiteralSupportOptions? CodeActionLiteralSupport { get; set; } - - /// - /// Whether code action supports the `isPreferred` property. - /// @since 3.15.0 - /// - [Optional] - public bool IsPreferredSupport { get; set; } - - /// - /// Whether code action supports the `disabled` property. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public bool DisabledSupport { get; set; } - - /// - /// Whether code action supports the `data` property which is - /// preserved between a `textDocument/codeAction` and a `codeAction/resolve` request. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public bool DataSupport { get; set; } - - /// - /// Whether the client supports resolving additional code action - /// properties via a separate `codeAction/resolve` request. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public CodeActionCapabilityResolveSupportOptions? ResolveSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/CodeActionCapabilityResolveSupportOptions.cs b/src/Protocol/Client/Capabilities/CodeActionCapabilityResolveSupportOptions.cs deleted file mode 100644 index 4f097c5ff..000000000 --- a/src/Protocol/Client/Capabilities/CodeActionCapabilityResolveSupportOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Whether the client supports resolving additional code action - /// properties via a separate `codeAction/resolve` request. - /// - /// @since 3.16.0 - proposed state - /// - public class CodeActionCapabilityResolveSupportOptions - { - /// - /// The properties that a client can resolve lazily. - /// - public Container Properties { get; set; } = new Container(); - } -} diff --git a/src/Protocol/Client/Capabilities/CodeActionKindCapabilityOptions.cs b/src/Protocol/Client/Capabilities/CodeActionKindCapabilityOptions.cs deleted file mode 100644 index ab4ec4255..000000000 --- a/src/Protocol/Client/Capabilities/CodeActionKindCapabilityOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class CodeActionKindCapabilityOptions - { - /// - /// The code action kind values the client supports. When this - /// property exists the client also guarantees that it will - /// handle values outside its set gracefully and falls back - /// to a default value when unknown. - /// - public Container ValueSet { get; set; } = null!; - } -} diff --git a/src/Protocol/Client/Capabilities/CodeActionLiteralSupportOptions.cs b/src/Protocol/Client/Capabilities/CodeActionLiteralSupportOptions.cs deleted file mode 100644 index 5c761e0b3..000000000 --- a/src/Protocol/Client/Capabilities/CodeActionLiteralSupportOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class CodeActionLiteralSupportOptions - { - /// - /// The code action kind is support with the following value - /// set. - /// - public CodeActionKindCapabilityOptions CodeActionKind { get; set; } = null!; - } -} diff --git a/src/Protocol/Client/Capabilities/CodeLensCapability.cs b/src/Protocol/Client/Capabilities/CodeLensCapability.cs deleted file mode 100644 index af0f3118f..000000000 --- a/src/Protocol/Client/Capabilities/CodeLensCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeLens))] - public class CodeLensCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/CodeLensWorkspaceClientCapabilities.cs b/src/Protocol/Client/Capabilities/CodeLensWorkspaceClientCapabilities.cs deleted file mode 100644 index cbd582111..000000000 --- a/src/Protocol/Client/Capabilities/CodeLensWorkspaceClientCapabilities.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the code lens requests scoped to the - /// workspace. - /// - /// @since 3.16.0 - proposed state. - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.CodeLens))] - public class CodeLensWorkspaceClientCapabilities - { - /// - /// Whether the client implementation supports a refresh request send from the server - /// to the client. This is useful if a server detects a change which requires a - /// re-calculation of all code lenses. - /// - [Optional] - public bool RefreshSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/ColorProviderCapability.cs b/src/Protocol/Client/Capabilities/ColorProviderCapability.cs deleted file mode 100644 index 8fa0b9354..000000000 --- a/src/Protocol/Client/Capabilities/ColorProviderCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.ColorProvider))] - public class ColorProviderCapability : DynamicCapability, ConnectedCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/CompletionCapability.cs b/src/Protocol/Client/Capabilities/CompletionCapability.cs deleted file mode 100644 index f0829799a..000000000 --- a/src/Protocol/Client/Capabilities/CompletionCapability.cs +++ /dev/null @@ -1,28 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Completion))] - public class CompletionCapability : DynamicCapability, ConnectedCapability - { - /// - /// The client supports the following `CompletionItem` specific - /// capabilities. - /// - [Optional] - public CompletionItemCapabilityOptions? CompletionItem { get; set; } - - /// - /// Specific capabilities for the `CompletionItemKind` in the `textDocument/completion` request. - /// - [Optional] - public CompletionItemKindCapabilityOptions? CompletionItemKind { get; set; } - - /// - /// The client supports to send additional context information for a `textDocument/completion` request. - /// - [Optional] - public bool ContextSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/CompletionItemCapabilityOptions.cs b/src/Protocol/Client/Capabilities/CompletionItemCapabilityOptions.cs deleted file mode 100644 index 0a47b5454..000000000 --- a/src/Protocol/Client/Capabilities/CompletionItemCapabilityOptions.cs +++ /dev/null @@ -1,99 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class CompletionItemCapabilityOptions - { - /// - /// Client supports snippets as insert text. - /// - /// A snippet can define tab stops and placeholders with `$1`, `$2` - /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to - /// the end of the snippet. Placeholders with equal identifiers are linked, - /// that is typing in one will update others too. - /// - [Optional] - public bool SnippetSupport { get; set; } - - /// - /// Client supports commit characters on a completion item. - /// - [Optional] - public bool CommitCharactersSupport { get; set; } - - /// - /// Client supports the follow content formats for the documentation - /// property. The order describes the preferred format of the client. - /// - [Optional] - public Container? DocumentationFormat { get; set; } - - /// - /// Client supports the deprecated property on a completion item. - /// - [Optional] - public bool DeprecatedSupport { get; set; } - - /// - /// Client supports the preselect property on a completion item. - /// - [Optional] - public bool PreselectSupport { get; set; } - - /// - /// Client supports the tag property on a completion item. Clients supporting - /// tags have to handle unknown tags gracefully. Clients especially need to - /// preserve unknown tags when sending a completion item back to the server in - /// a resolve call. - /// - /// @since 3.15.0 - /// - [Optional] - public Supports TagSupport { get; set; } - - /// - /// Client support insert replace edit to control different behavior if a - /// completion item is inserted in the text or should replace text. - /// - /// @since 3.16.0 - Proposed state - /// - [Optional] - public bool InsertReplaceSupport { get; set; } - - /// - /// Client supports to resolve `additionalTextEdits` in the `completionItem/resolve` - /// request. So servers can postpone computing them. - /// - /// @since 3.16.0 - Proposed state - /// - [Optional] - public bool ResolveAdditionalTextEditsSupport { get; set; } - - /// - /// Indicates which properties a client can resolve lazily on a completion - /// item. Before version 3.16.0 only the predefined properties `documentation` - /// and `details` could be resolved lazily. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public CompletionItemCapabilityResolveSupportOptions? ResolveSupport { get; set; } - - /// - /// The client supports the `insertTextMode` property on - /// a completion item to override the whitespace handling mode - /// as defined by the client (see `insertTextMode`). - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public CompletionItemInsertTextModeSupportCapabilityOptions? InsertTextModeSupport { get; set; } - } - - public class CompletionItemInsertTextModeSupportCapabilityOptions - { - public Container ValueSet { get; set; } = null!; - } - -} diff --git a/src/Protocol/Client/Capabilities/CompletionItemCapabilityResolveSupportOptions.cs b/src/Protocol/Client/Capabilities/CompletionItemCapabilityResolveSupportOptions.cs deleted file mode 100644 index 1b38b78df..000000000 --- a/src/Protocol/Client/Capabilities/CompletionItemCapabilityResolveSupportOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Indicates which properties a client can resolve lazily on a completion - /// item. Before version 3.16.0 only the predefined properties `documentation` - /// and `details` could be resolved lazily. - /// - /// @since 3.16.0 - proposed state - /// - public class CompletionItemCapabilityResolveSupportOptions - { - /// - /// The properties that a client can resolve lazily. - /// - public Container Properties { get; set; } = new Container(); - } -} diff --git a/src/Protocol/Client/Capabilities/CompletionItemKindCapabilityOptions.cs b/src/Protocol/Client/Capabilities/CompletionItemKindCapabilityOptions.cs deleted file mode 100644 index 82bef07ae..000000000 --- a/src/Protocol/Client/Capabilities/CompletionItemKindCapabilityOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class CompletionItemKindCapabilityOptions - { - /// - /// The completion item kind values the client supports. When this - /// property exists the client also guarantees that it will - /// handle values outside its set gracefully and falls back - /// to a default value when unknown. - /// - /// If this property is not present the client only supports - /// the completion items kinds from `Text` to `Reference` as defined in - /// the initial version of the protocol. - /// - [Optional] - public Container? ValueSet { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/CompletionItemTagSupportCapabilityOptions.cs b/src/Protocol/Client/Capabilities/CompletionItemTagSupportCapabilityOptions.cs deleted file mode 100644 index b270a4a78..000000000 --- a/src/Protocol/Client/Capabilities/CompletionItemTagSupportCapabilityOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class CompletionItemTagSupportCapabilityOptions - { - /// - /// The tags supported by the client. - /// - public Container ValueSet { get; set; } = null!; - } -} diff --git a/src/Protocol/Client/Capabilities/DeclarationCapability.cs b/src/Protocol/Client/Capabilities/DeclarationCapability.cs deleted file mode 100644 index 97e813135..000000000 --- a/src/Protocol/Client/Capabilities/DeclarationCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Declaration))] - public class DeclarationCapability : LinkSupportCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DefinitionCapability.cs b/src/Protocol/Client/Capabilities/DefinitionCapability.cs deleted file mode 100644 index c15518b61..000000000 --- a/src/Protocol/Client/Capabilities/DefinitionCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Definition))] - public class DefinitionCapability : LinkSupportCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DidChangeConfigurationCapability.cs b/src/Protocol/Client/Capabilities/DidChangeConfigurationCapability.cs deleted file mode 100644 index 79537a3d5..000000000 --- a/src/Protocol/Client/Capabilities/DidChangeConfigurationCapability.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Configuration))] - public class DidChangeConfigurationCapability : DynamicCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DidChangeWatchedFilesCapability.cs b/src/Protocol/Client/Capabilities/DidChangeWatchedFilesCapability.cs deleted file mode 100644 index b5d2d2097..000000000 --- a/src/Protocol/Client/Capabilities/DidChangeWatchedFilesCapability.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.DidChangeWatchedFiles))] - public class DidChangeWatchedFilesCapability : DynamicCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentFormattingCapability.cs b/src/Protocol/Client/Capabilities/DocumentFormattingCapability.cs deleted file mode 100644 index 9f1a61e5c..000000000 --- a/src/Protocol/Client/Capabilities/DocumentFormattingCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Formatting))] - public class DocumentFormattingCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentHighlightCapability.cs b/src/Protocol/Client/Capabilities/DocumentHighlightCapability.cs deleted file mode 100644 index 52cf8bffa..000000000 --- a/src/Protocol/Client/Capabilities/DocumentHighlightCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentHighlight))] - public class DocumentHighlightCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentLinkCapability.cs b/src/Protocol/Client/Capabilities/DocumentLinkCapability.cs deleted file mode 100644 index 5e75c4c43..000000000 --- a/src/Protocol/Client/Capabilities/DocumentLinkCapability.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentLink))] - public class DocumentLinkCapability : DynamicCapability, ConnectedCapability - { - /// - /// Whether the client support the `tooltip` property on `DocumentLink`. - /// - /// @since 3.15.0 - /// - [Optional] - public bool TooltipSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentOnTypeFormattingCapability.cs b/src/Protocol/Client/Capabilities/DocumentOnTypeFormattingCapability.cs deleted file mode 100644 index f35e0fe7d..000000000 --- a/src/Protocol/Client/Capabilities/DocumentOnTypeFormattingCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OnTypeFormatting))] - public class DocumentOnTypeFormattingCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentRangeFormattingCapability.cs b/src/Protocol/Client/Capabilities/DocumentRangeFormattingCapability.cs deleted file mode 100644 index b312283f5..000000000 --- a/src/Protocol/Client/Capabilities/DocumentRangeFormattingCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.RangeFormatting))] - public class DocumentRangeFormattingCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/DocumentSymbolCapability.cs b/src/Protocol/Client/Capabilities/DocumentSymbolCapability.cs deleted file mode 100644 index 698f5d04e..000000000 --- a/src/Protocol/Client/Capabilities/DocumentSymbolCapability.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentSymbol))] - public class DocumentSymbolCapability : DynamicCapability, ConnectedCapability - { - /// - /// Specific capabilities for the `SymbolKind` in the `textDocument/symbol` request. - /// - [Optional] - public SymbolKindCapabilityOptions? SymbolKind { get; set; } - - /// - /// Whether document symbol supports hierarchical `DocumentSymbol`s. - /// - [Optional] - public bool HierarchicalDocumentSymbolSupport { get; set; } - - /// - /// The client supports tags on `SymbolInformation`.Tags are supported on - /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set tot true. - /// Clients supporting tags have to handle unknown tags gracefully. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Optional] - public TagSupportCapabilityOptions? TagSupport { get; set; } - - /// - /// The client supports an additional label presented in the UI when - /// registering a document symbol provider. - /// - /// @since 3.16.0 - /// - [Optional] - public bool LabelSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/ExecuteCommandCapability.cs b/src/Protocol/Client/Capabilities/ExecuteCommandCapability.cs deleted file mode 100644 index 67b64ba79..000000000 --- a/src/Protocol/Client/Capabilities/ExecuteCommandCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.ExecuteCommand))] - public class ExecuteCommandCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/FoldingRangeCapability.cs b/src/Protocol/Client/Capabilities/FoldingRangeCapability.cs deleted file mode 100644 index efb133efc..000000000 --- a/src/Protocol/Client/Capabilities/FoldingRangeCapability.cs +++ /dev/null @@ -1,25 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.FoldingRange))] - public class FoldingRangeCapability : DynamicCapability, ConnectedCapability - { - /// - /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a - /// hint, servers are free to follow the limit. - /// - /// - /// in the LSP spec - /// - [Optional] - public int? RangeLimit { get; set; } - - /// - /// If set, the client signals that it only supports folding complete lines. If set, client will - /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. - /// - public bool LineFoldingOnly { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/HoverCapability.cs b/src/Protocol/Client/Capabilities/HoverCapability.cs deleted file mode 100644 index 3d8c49161..000000000 --- a/src/Protocol/Client/Capabilities/HoverCapability.cs +++ /dev/null @@ -1,16 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Hover))] - public class HoverCapability : DynamicCapability, ConnectedCapability - { - /// - /// Client supports the follow content formats for the content property. The order describes the preferred format of the client. - /// - [Optional] - public Container? ContentFormat { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/ImplementationCapability.cs b/src/Protocol/Client/Capabilities/ImplementationCapability.cs deleted file mode 100644 index e34f0be30..000000000 --- a/src/Protocol/Client/Capabilities/ImplementationCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Implementation))] - public class ImplementationCapability : LinkSupportCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/MonikerCapability.cs b/src/Protocol/Client/Capabilities/MonikerCapability.cs deleted file mode 100644 index bff062bbb..000000000 --- a/src/Protocol/Client/Capabilities/MonikerCapability.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Moniker))] - public class MonikerCapability : DynamicCapability { } -} diff --git a/src/Protocol/Client/Capabilities/OnTypeRenameClientCapabilities.cs b/src/Protocol/Client/Capabilities/OnTypeRenameClientCapabilities.cs deleted file mode 100644 index 6ec612ee9..000000000 --- a/src/Protocol/Client/Capabilities/OnTypeRenameClientCapabilities.cs +++ /dev/null @@ -1,10 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OnTypeRename))] - public class OnTypeRenameClientCapabilities : DynamicCapability, ConnectedCapability - { - - } -} diff --git a/src/Protocol/Client/Capabilities/PublishDiagnosticsCapability.cs b/src/Protocol/Client/Capabilities/PublishDiagnosticsCapability.cs deleted file mode 100644 index 8424c5285..000000000 --- a/src/Protocol/Client/Capabilities/PublishDiagnosticsCapability.cs +++ /dev/null @@ -1,53 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to `textDocument/publishDiagnostics`. - /// - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.PublishDiagnostics))] - public class PublishDiagnosticsCapability : ICapability - { - /// - /// Whether the clients accepts diagnostics with related information. - /// - [Optional] - public bool RelatedInformation { get; set; } - - /// - /// Client supports the tag property to provide meta data about a diagnostic. - /// Clients supporting tags have to handle unknown tags gracefully. - /// - /// @since 3.15.0 - /// - [Optional] - public Supports TagSupport { get; set; } - - /// - /// Whether the client interprets the version property of the - /// `textDocument/publishDiagnostics` notification's parameter. - /// - /// @since 3.15.0 - /// - [Optional] - public bool VersionSupport { get; set; } - - /// - /// Client supports a codeDescription property - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public bool CodeDescriptionSupport { get; set; } - - /// - /// Whether code action supports the `data` property which is - /// preserved between a `textDocument/publishDiagnostics` and - /// `textDocument/codeAction` request. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public bool DataSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/PublishDiagnosticsTagSupportCapabilityOptions.cs b/src/Protocol/Client/Capabilities/PublishDiagnosticsTagSupportCapabilityOptions.cs deleted file mode 100644 index 0a7408bdb..000000000 --- a/src/Protocol/Client/Capabilities/PublishDiagnosticsTagSupportCapabilityOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class PublishDiagnosticsTagSupportCapabilityOptions - { - /// - /// The tags supported by the client. - /// - public Container ValueSet { get; set; } = null!; - } -} diff --git a/src/Protocol/Client/Capabilities/ReferenceCapability.cs b/src/Protocol/Client/Capabilities/ReferenceCapability.cs deleted file mode 100644 index 36d7eefeb..000000000 --- a/src/Protocol/Client/Capabilities/ReferenceCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.References))] - public class ReferenceCapability : DynamicCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/RenameCapability.cs b/src/Protocol/Client/Capabilities/RenameCapability.cs deleted file mode 100644 index 994fba011..000000000 --- a/src/Protocol/Client/Capabilities/RenameCapability.cs +++ /dev/null @@ -1,24 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Rename))] - public class RenameCapability : DynamicCapability, ConnectedCapability - { - /// - /// Client supports testing for validity of rename operations - /// before execution. - /// - [Optional] - public bool PrepareSupport { get; set; } - - /// - /// Client supports the default behavior result (`{ defaultBehavior: boolean }`). - /// - /// @since version 3.16.0 - /// - [Optional] - public bool PrepareSupportDefaultBehavior { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SelectionRangeCapability.cs b/src/Protocol/Client/Capabilities/SelectionRangeCapability.cs deleted file mode 100644 index 66931148d..000000000 --- a/src/Protocol/Client/Capabilities/SelectionRangeCapability.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.SelectionRange))] - public class SelectionRangeCapability : DynamicCapability, ConnectedCapability - { - /// - /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a - /// hint, servers are free to follow the limit. - /// - [Optional] - public int? RangeLimit { get; set; } - - /// - /// If set, the client signals that it only supports folding complete lines. If set, client will - /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. - /// - public bool LineFoldingOnly { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapability.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapability.cs deleted file mode 100644 index 786983c25..000000000 --- a/src/Protocol/Client/Capabilities/SemanticTokensCapability.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the `textDocument/semanticTokens` - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.SemanticTokens))] - public class SemanticTokensCapability : DynamicCapability, ConnectedCapability, - ConnectedCapability, ConnectedCapability - { - /// - /// Which requests the client supports and might send to the server. - /// - public SemanticTokensCapabilityRequests Requests { get; set; } = null!; - - /// - /// The token types that the client supports. - /// - public Container TokenTypes { get; set; } = null!; - - /// - /// The token modifiers that the client supports. - /// - public Container TokenModifiers { get; set; } = null!; - - /// - /// The formats the clients supports. - /// - public Container Formats { get; set; } = null!; - - /// - /// Whether the client supports tokens that can overlap each other. - /// - [Optional] - public bool OverlappingTokenSupport { get; set; } - - /// - /// Whether the client supports tokens that can span multiple lines. - /// - [Optional] - public bool MultilineTokenSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs deleted file mode 100644 index d6de1af4b..000000000 --- a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestFull.cs +++ /dev/null @@ -1,18 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// The client will send the `textDocument/semanticTokens/full` request if - /// the server provides a corresponding handler. - /// - public class SemanticTokensCapabilityRequestFull - { - /// - /// The client will send the `textDocument/semanticTokens/full/delta` request if - /// the server provides a corresponding handler. - /// - [Optional] - public bool Delta { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs deleted file mode 100644 index eec213e54..000000000 --- a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequestRange.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// The client will send the `textDocument/semanticTokens/range` request if - /// the server provides a corresponding handler. - /// - public class SemanticTokensCapabilityRequestRange - { - } -} diff --git a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs b/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs deleted file mode 100644 index e3a22b9f4..000000000 --- a/src/Protocol/Client/Capabilities/SemanticTokensCapabilityRequests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class SemanticTokensCapabilityRequests - { - /// - /// The client will send the `textDocument/semanticTokens/range` request if - /// the server provides a corresponding handler. - /// - [Optional] - public Supports Range { get; set; } - - /// - /// The client will send the `textDocument/semanticTokens/full` request if - /// the server provides a corresponding handler. - /// - [Optional] - public Supports Full { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SemanticTokensWorkspaceCapability.cs b/src/Protocol/Client/Capabilities/SemanticTokensWorkspaceCapability.cs deleted file mode 100644 index 5a91701c3..000000000 --- a/src/Protocol/Client/Capabilities/SemanticTokensWorkspaceCapability.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the semantic token requests scoped to the - /// workspace. - /// - /// @since 3.16.0 - proposed state. - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.SemanticTokens))] - public class SemanticTokensWorkspaceCapability : ICapability - { - /// - /// Whether the client implementation supports a refresh request send from - /// the server to the client. This is useful if a server detects a project - /// wide configuration change which requires a re-calculation of all semantic - /// tokens provided by the server issuing the request. - /// - [Optional] - public bool RefreshSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/ShowDocumentClientCapabilities.cs b/src/Protocol/Client/Capabilities/ShowDocumentClientCapabilities.cs deleted file mode 100644 index 045fce3ec..000000000 --- a/src/Protocol/Client/Capabilities/ShowDocumentClientCapabilities.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the showDocument request - /// - /// @since 3.16.0 - proposed state - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.Window), nameof(WindowClientCapabilities.ShowDocument))] - public class ShowDocumentClientCapabilities - { - /// - /// Capabilities specific to the `MessageActionItem` type. - /// - [Optional] - public bool Support { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/ShowMessageRequestClientCapabilities.cs b/src/Protocol/Client/Capabilities/ShowMessageRequestClientCapabilities.cs deleted file mode 100644 index d2cc42750..000000000 --- a/src/Protocol/Client/Capabilities/ShowMessageRequestClientCapabilities.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Capabilities specific to the showMessage request - /// - /// @since 3.16.0 - proposed state - /// - [Obsolete(Constants.Proposal)] - [CapabilityKey(nameof(ClientCapabilities.Window), nameof(WindowClientCapabilities.ShowMessage))] - public class ShowMessageRequestClientCapabilities - { - /// - /// Capabilities specific to the `MessageActionItem` type. - /// - [Optional] - public ShowMessageRequestMessageActionItemClientCapabilities? MessageActionItem { get; set; } - } -} \ No newline at end of file diff --git a/src/Protocol/Client/Capabilities/ShowMessageRequestMessageActionItemClientCapabilities.cs b/src/Protocol/Client/Capabilities/ShowMessageRequestMessageActionItemClientCapabilities.cs deleted file mode 100644 index e35cdf270..000000000 --- a/src/Protocol/Client/Capabilities/ShowMessageRequestMessageActionItemClientCapabilities.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [Obsolete(Constants.Proposal)] - public class ShowMessageRequestMessageActionItemClientCapabilities - { - /// - /// Whether the client supports additional attribues which - /// are preserved and send back to the server in the - /// request's response. - /// - [Optional] - public bool AdditionalPropertiesSupport { get; set; } - } -} \ No newline at end of file diff --git a/src/Protocol/Client/Capabilities/SignatureHelpCapability.cs b/src/Protocol/Client/Capabilities/SignatureHelpCapability.cs deleted file mode 100644 index d26004fc0..000000000 --- a/src/Protocol/Client/Capabilities/SignatureHelpCapability.cs +++ /dev/null @@ -1,26 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class SignatureHelpCapability : DynamicCapability, ConnectedCapability - { - /// - /// The client supports the following `SignatureInformation` - /// specific properties. - /// - [Optional] - public SignatureInformationCapabilityOptions? SignatureInformation { get; set; } - - /// - /// The client supports to send additional context information for a - /// `textDocument/signatureHelp` request. A client that opts into - /// contextSupport will also support the `retriggerCharacters` on - /// `StaticOptions`. - /// - /// @since 3.15.0 - /// - [Optional] - public bool ContextSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SignatureInformationCapabilityOptions.cs b/src/Protocol/Client/Capabilities/SignatureInformationCapabilityOptions.cs deleted file mode 100644 index abd59f55c..000000000 --- a/src/Protocol/Client/Capabilities/SignatureInformationCapabilityOptions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class SignatureInformationCapabilityOptions - { - /// - /// Client supports the follow content formats for the content property. The order describes the preferred format of the client. - /// - [Optional] - public Container? DocumentationFormat { get; set; } - - [Optional] public SignatureParameterInformationCapabilityOptions? ParameterInformation { get; set; } - - /// - /// The client support the `activeParameter` property on `SignatureInformation` - /// literal. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public bool ActiveParameterSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SignatureParameterInformationCapabilityOptions.cs b/src/Protocol/Client/Capabilities/SignatureParameterInformationCapabilityOptions.cs deleted file mode 100644 index fd36407be..000000000 --- a/src/Protocol/Client/Capabilities/SignatureParameterInformationCapabilityOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - public class SignatureParameterInformationCapabilityOptions - { - /// - /// The client supports processing label offsets instead of a - /// simple label string. - /// - [Optional] - public bool LabelOffsetSupport { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/SynchronizationCapability.cs b/src/Protocol/Client/Capabilities/SynchronizationCapability.cs deleted file mode 100644 index 9d8aa9346..000000000 --- a/src/Protocol/Client/Capabilities/SynchronizationCapability.cs +++ /dev/null @@ -1,35 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Synchronization))] - public class SynchronizationCapability : DynamicCapability, - ConnectedCapability, - ConnectedCapability, - ConnectedCapability, - ConnectedCapability, - ConnectedCapability, - ConnectedCapability - { - /// - /// The client supports sending will save notifications. - /// - [Optional] - public bool WillSave { get; set; } - - /// - /// The client supports sending a will save request and - /// waits for a response providing text edits which will - /// be applied to the document before it is saved. - /// - [Optional] - public bool WillSaveWaitUntil { get; set; } - - /// - /// The client supports did save notifications. - /// - [Optional] - public bool DidSave { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/TypeDefinitionCapability.cs b/src/Protocol/Client/Capabilities/TypeDefinitionCapability.cs deleted file mode 100644 index 77bead6f1..000000000 --- a/src/Protocol/Client/Capabilities/TypeDefinitionCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.TypeDefinition))] - public class TypeDefinitionCapability : LinkSupportCapability, ConnectedCapability - { - } -} diff --git a/src/Protocol/Client/Capabilities/WorkspaceSymbolCapability.cs b/src/Protocol/Client/Capabilities/WorkspaceSymbolCapability.cs deleted file mode 100644 index 3cd9f0326..000000000 --- a/src/Protocol/Client/Capabilities/WorkspaceSymbolCapability.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Symbol))] - public class WorkspaceSymbolCapability : DynamicCapability, ConnectedCapability - { - /// - /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. - /// - [Optional] - public SymbolKindCapabilityOptions? SymbolKind { get; set; } - - /// - /// The client supports tags on `SymbolInformation`.Tags are supported on - /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. - /// Clients supporting tags have to handle unknown tags gracefully. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Optional] - public Supports TagSupport { get; set; } - } -} diff --git a/src/Protocol/Client/ILogTraceHandler.cs b/src/Protocol/Client/ILogTraceHandler.cs deleted file mode 100644 index c7973b4f9..000000000 --- a/src/Protocol/Client/ILogTraceHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client -{ - [Parallel] - [Method(GeneralNames.LogTrace, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] - public interface ILogTraceHandler : IJsonRpcNotificationHandler - { - } - - public abstract class LogTraceHandler : ILogTraceHandler - { - public abstract Task Handle(LogTraceParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Client/IRegisterCapabilityHandler.cs b/src/Protocol/Client/IRegisterCapabilityHandler.cs deleted file mode 100644 index 080929a44..000000000 --- a/src/Protocol/Client/IRegisterCapabilityHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client -{ - [Parallel] - [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] - public interface IRegisterCapabilityHandler : IJsonRpcRequestHandler - { - } - - public abstract class RegisterCapabilityHandler : IRegisterCapabilityHandler - { - public abstract Task Handle(RegistrationParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Client/IUnregisterCapabilityHandler.cs b/src/Protocol/Client/IUnregisterCapabilityHandler.cs deleted file mode 100644 index b905ae39f..000000000 --- a/src/Protocol/Client/IUnregisterCapabilityHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client -{ - [Parallel] - [Method(ClientNames.UnregisterCapability, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] - public interface IUnregisterCapabilityHandler : IJsonRpcRequestHandler - { - } - - public abstract class UnregisterCapabilityHandler : IUnregisterCapabilityHandler - { - public abstract Task Handle(UnregistrationParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Client/WorkDone/LanguageClientWorkDoneManager.cs b/src/Protocol/Client/WorkDone/LanguageClientWorkDoneManager.cs index 83060f05d..edd09fbc2 100644 --- a/src/Protocol/Client/WorkDone/LanguageClientWorkDoneManager.cs +++ b/src/Protocol/Client/WorkDone/LanguageClientWorkDoneManager.cs @@ -13,6 +13,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.WorkDone { + [BuiltIn] internal class LanguageClientWorkDoneManager : IClientWorkDoneManager, IWorkDoneProgressCreateHandler { private readonly IWindowLanguageClient _router; diff --git a/src/Protocol/Document/ICodeActionHandler.cs b/src/Protocol/Document/ICodeActionHandler.cs deleted file mode 100644 index 9226c414b..000000000 --- a/src/Protocol/Document/ICodeActionHandler.cs +++ /dev/null @@ -1,594 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Reactive.Threading.Tasks; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.CodeAction, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICodeActionHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - [Parallel] - [Method(TextDocumentNames.CodeActionResolve, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICodeActionResolveHandler : ICanBeResolvedHandler, ICanBeIdentifiedHandler - { - } - - [Obsolete("This handler is obsolete and is related by CodeActionHandlerBase")] - public abstract class CodeActionHandler : ICodeActionHandler - { - private readonly CodeActionRegistrationOptions _options; - public CodeActionHandler(CodeActionRegistrationOptions registrationOptions) => _options = registrationOptions; - public CodeActionRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(CodeActionParams request, CancellationToken cancellationToken); - public virtual void SetCapability(CodeActionCapability capability) => Capability = capability; - protected CodeActionCapability Capability { get; private set; } = null!; - } - - public abstract class CodeActionHandlerBase : ICodeActionHandler, ICodeActionResolveHandler - { - private readonly CodeActionRegistrationOptions _options; - - public CodeActionHandlerBase(CodeActionRegistrationOptions registrationOptions) - { - _options = registrationOptions; - _options.ResolveProvider = true; - } - - public CodeActionRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(CodeActionParams request, CancellationToken cancellationToken); - public abstract Task Handle(CodeAction request, CancellationToken cancellationToken); - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - public virtual void SetCapability(CodeActionCapability capability) => Capability = capability; - protected CodeActionCapability Capability { get; private set; } = null!; - } - - public abstract class PartialCodeActionHandlerBase : - AbstractHandlers.PartialResults, ICodeActionHandler, ICodeActionResolveHandler - { - protected PartialCodeActionHandlerBase(CodeActionRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - lenses => new CommandOrCodeActionContainer(lenses) - ) - { - } - - public abstract Task Handle(CodeAction request, CancellationToken cancellationToken); - public virtual Guid Id { get; } = Guid.NewGuid(); - } - - public abstract class CodeActionHandlerBase : CodeActionHandlerBase where T : HandlerIdentity?, new() - { - public CodeActionHandlerBase(CodeActionRegistrationOptions registrationOptions) : base(registrationOptions) - { - } - - - public sealed override async Task Handle(CodeActionParams request, CancellationToken cancellationToken) - { - var response = await HandleParams(request, cancellationToken).ConfigureAwait(false); - return response; - } - - public sealed override async Task Handle(CodeAction request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract Task HandleParams(CodeActionParams request, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CodeAction request, CancellationToken cancellationToken); - } - - public abstract class PartialCodeActionHandlerBase : PartialCodeActionHandlerBase where T : HandlerIdentity?, new() - { - protected PartialCodeActionHandlerBase(CodeActionRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, - progressManager - ) - { - } - - protected sealed override void Handle(CodeActionParams request, IObserver> results, CancellationToken cancellationToken) => Handle( - request, - Observer.Create>>( - x => results.OnNext(x.Select(z => new CommandOrCodeAction(z))), - results.OnError, - results.OnCompleted - ), cancellationToken - ); - - public sealed override async Task Handle(CodeAction request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract void Handle(CodeActionParams request, IObserver>> results, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CodeAction request, CancellationToken cancellationToken); - } - - public static partial class CodeActionExtensions - { - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, cap, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeAction, - new LanguageProtocolDelegatingHandlers.Request( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CodeActionCapability, CancellationToken, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, c, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCodeActionHandler( - registrationOptions, - async (@params, capability, token) => await handler(@params, capability, token), - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeAction, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CancellationToken, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCodeActionHandler( - registrationOptions, - async (@params, capability, token) => await handler(@params, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeAction, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Func>> handler, - Func, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingCodeActionHandler( - registrationOptions, - async (@params, capability, token) => await handler(@params), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>, CodeActionCapability, CancellationToken> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>, CodeActionCapability, CancellationToken> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return - registry.AddHandler( - TextDocumentNames.CodeAction, - _ => new CodeActionPartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService() - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>>, CodeActionCapability, CancellationToken> handler, - Func, CodeActionCapability, CancellationToken, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCodeActionHandler( - registrationOptions, - _.GetRequiredService(), - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeAction, - _ => new CodeActionPartialResults( - id, - (@params, observer, capability, arg4) => handler(@params, observer, arg4), - registrationOptions, - _.GetRequiredService() - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>>, CancellationToken> handler, - Func, CancellationToken, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCodeActionHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>> handler, - CodeActionRegistrationOptions? registrationOptions - ) => - OnCodeAction(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>> handler, - Func>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeAction, - _ => new CodeActionPartialResults( - id, - (@params, observer, capability, arg3) => handler(@params, observer), - registrationOptions, - _.GetRequiredService() - ) - ) - .AddHandler( - TextDocumentNames.CodeActionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - sealed class CodeActionPartialResults : - IJsonRpcRequestHandler, - IRegistration, - ICanBeIdentifiedHandler, - ICapability - { - private readonly Action>, CodeActionCapability, CancellationToken> _handler; - private readonly CodeActionRegistrationOptions _registrationOptions; - private readonly IProgressManager _progressManager; - private readonly Guid _id; - private CodeActionCapability? _capability; - Guid ICanBeIdentifiedHandler.Id => _id; - - public CodeActionPartialResults( - Guid id, Action>, CodeActionCapability, CancellationToken> handler, CodeActionRegistrationOptions registrationOptions, IProgressManager progressManager - ) - { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; - _progressManager = progressManager; - } - - async Task IRequestHandler.Handle(CodeActionParams request, CancellationToken cancellationToken) - { - var observer = _progressManager.For(request, cancellationToken); - if (observer != ProgressObserver>.Noop) - { - _handler( - request, - Observer.Create>( - v => observer.OnNext(v.Select(z => new CommandOrCodeAction(z))), - observer.OnError, - observer.OnCompleted - ), - _capability!, - cancellationToken - ); - await observer; - return new CommandOrCodeActionContainer(); - } - - var subject = new Subject>(); - var task = subject.Aggregate( - new List(), (acc, items) => { - acc.AddRange(items); - return acc; - } - ) - .ToTask(cancellationToken); - _handler(request, subject, _capability!, cancellationToken); - var actions = await task.ConfigureAwait(false); - var result = new CommandOrCodeActionContainer(actions.Select(z => new CommandOrCodeAction(z))); - return result; - } - - CodeActionRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - public void SetCapability(CodeActionCapability capability) => _capability = capability; - } - - public static ILanguageServerRegistry OnCodeAction( - this ILanguageServerRegistry registry, - Action>>> handler, - Func, Task>>? resolveHandler, - CodeActionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeActionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingPartialCodeActionHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - private class DelegatingCodeActionHandler : CodeActionHandlerBase where T : HandlerIdentity?, new() - { - private readonly Func> _handleParams; - private readonly Func, CodeActionCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingCodeActionHandler( - CodeActionRegistrationOptions registrationOptions, - Func> handleParams, - Func, CodeActionCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override Task HandleParams(CodeActionParams request, CancellationToken cancellationToken) => - _handleParams(request, Capability, cancellationToken); - - protected override Task> HandleResolve(CodeAction request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); - } - - private class DelegatingPartialCodeActionHandler : PartialCodeActionHandlerBase where T : HandlerIdentity?, new() - { - private readonly Action>>, CodeActionCapability, CancellationToken> _handleParams; - private readonly Func, CodeActionCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingPartialCodeActionHandler( - CodeActionRegistrationOptions registrationOptions, - IProgressManager progressManager, - Action>>, CodeActionCapability, CancellationToken> handleParams, - Func, CodeActionCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions, progressManager) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override void Handle(CodeActionParams request, IObserver>> results, CancellationToken cancellationToken) => - _handleParams(request, results, Capability, cancellationToken); - - protected override Task> HandleResolve(CodeAction request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); - } - } -} diff --git a/src/Protocol/Document/ICodeLensHandler.cs b/src/Protocol/Document/ICodeLensHandler.cs deleted file mode 100644 index 28a47acde..000000000 --- a/src/Protocol/Document/ICodeLensHandler.cs +++ /dev/null @@ -1,524 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.CodeLens, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICodeLensHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - [Parallel] - [Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICodeLensResolveHandler : ICanBeResolvedHandler, ICanBeIdentifiedHandler - { - } - - public abstract class CodeLensHandler : ICodeLensHandler, ICodeLensResolveHandler - { - private readonly CodeLensRegistrationOptions _options; - - public CodeLensHandler(CodeLensRegistrationOptions registrationOptions) - { - _options = registrationOptions; - _options.ResolveProvider = true; - } - - public CodeLensRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(CodeLensParams request, CancellationToken cancellationToken); - public abstract Task Handle(CodeLens request, CancellationToken cancellationToken); - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - public virtual void SetCapability(CodeLensCapability capability) => Capability = capability; - protected CodeLensCapability Capability { get; private set; } = null!; - } - - public abstract class PartialCodeLensHandlerBase : - AbstractHandlers.PartialResults, ICodeLensHandler, ICodeLensResolveHandler - { - protected PartialCodeLensHandlerBase(CodeLensRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - lenses => new CodeLensContainer(lenses) - ) - { - } - - public abstract Task Handle(CodeLens request, CancellationToken cancellationToken); - public virtual Guid Id { get; } = Guid.NewGuid(); - } - - public abstract class CodeLensHandlerBase : CodeLensHandler where T : HandlerIdentity?, new() - { - public CodeLensHandlerBase(CodeLensRegistrationOptions registrationOptions) : base(registrationOptions) - { - } - - - public sealed override async Task Handle(CodeLensParams request, CancellationToken cancellationToken) - { - var response = await HandleParams(request, cancellationToken).ConfigureAwait(false); - return response; - } - - public sealed override async Task Handle(CodeLens request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract Task> HandleParams(CodeLensParams request, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CodeLens request, CancellationToken cancellationToken); - } - - public abstract class PartialCodeLensHandlerBase : PartialCodeLensHandlerBase where T : HandlerIdentity?, new() - { - protected PartialCodeLensHandlerBase(CodeLensRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, - progressManager - ) - { - } - - protected sealed override void Handle(CodeLensParams request, IObserver> results, CancellationToken cancellationToken) => Handle( - request, - Observer.Create>>( - x => results.OnNext(x.Select(z => (CodeLens) z)), - results.OnError, - results.OnCompleted - ), cancellationToken - ); - - public sealed override async Task Handle(CodeLens request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract void Handle(CodeLensParams request, IObserver>> results, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CodeLens request, CancellationToken cancellationToken); - } - - public static partial class CodeLensExtensions - { - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, cap, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeLens, - new LanguageProtocolDelegatingHandlers.Request( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CodeLensCapability, CancellationToken, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, c, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCodeLensHandler( - registrationOptions, - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeLens, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CancellationToken, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCodeLensHandler( - registrationOptions, - (@params, capability, token) => handler(@params, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeLens, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Func>> handler, - Func, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingCodeLensHandler( - registrationOptions, - (@params, capability, token) => handler(@params), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>, CodeLensCapability, CancellationToken> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>, CodeLensCapability, CancellationToken> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return - registry.AddHandler( - TextDocumentNames.CodeLens, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CodeLensContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>>, CodeLensCapability, CancellationToken> handler, - Func, CodeLensCapability, CancellationToken, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCodeLensHandler( - registrationOptions, - _.GetRequiredService(), - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeLens, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CodeLensContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>>, CancellationToken> handler, - Func, CancellationToken, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCodeLensHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>> handler, - CodeLensRegistrationOptions? registrationOptions - ) => - OnCodeLens(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>> handler, - Func>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.CodeLens, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CodeLensContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.CodeLensResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCodeLens( - this ILanguageServerRegistry registry, - Action>>> handler, - Func, Task>>? resolveHandler, - CodeLensRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CodeLensRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingPartialCodeLensHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - private class DelegatingCodeLensHandler : CodeLensHandlerBase where T : HandlerIdentity?, new() - { - private readonly Func>> _handleParams; - private readonly Func, CodeLensCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingCodeLensHandler( - CodeLensRegistrationOptions registrationOptions, - Func>> handleParams, - Func, CodeLensCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override Task> HandleParams(CodeLensParams request, CancellationToken cancellationToken) => - _handleParams(request, Capability, cancellationToken); - - protected override Task> HandleResolve(CodeLens request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); - } - - private class DelegatingPartialCodeLensHandler : PartialCodeLensHandlerBase where T : HandlerIdentity?, new() - { - private readonly Action>>, CodeLensCapability, CancellationToken> _handleParams; - private readonly Func, CodeLensCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingPartialCodeLensHandler( - CodeLensRegistrationOptions registrationOptions, - IProgressManager progressManager, - Action>>, CodeLensCapability, CancellationToken> handleParams, - Func, CodeLensCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions, progressManager) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override void Handle(CodeLensParams request, IObserver>> results, CancellationToken cancellationToken) => - _handleParams(request, results, Capability, cancellationToken); - - protected override Task> HandleResolve(CodeLens request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); - } - } -} diff --git a/src/Protocol/Document/IColorPresentationHandler.cs b/src/Protocol/Document/IColorPresentationHandler.cs deleted file mode 100644 index a046833cf..000000000 --- a/src/Protocol/Document/IColorPresentationHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.ColorPresentation, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IColorPresentationHandler : IJsonRpcRequestHandler>, IRegistration, - ICapability - { - } - - public abstract class ColorPresentationHandler : IColorPresentationHandler - { - private readonly DocumentColorRegistrationOptions _options; - public ColorPresentationHandler(DocumentColorRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentColorRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task> Handle(ColorPresentationParams request, CancellationToken cancellationToken); - public virtual void SetCapability(ColorProviderCapability capability) => Capability = capability; - protected ColorProviderCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/ICompletionHandler.cs b/src/Protocol/Document/ICompletionHandler.cs deleted file mode 100644 index 4297467a8..000000000 --- a/src/Protocol/Document/ICompletionHandler.cs +++ /dev/null @@ -1,526 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Completion, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICompletionHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - [Parallel] - [Method(TextDocumentNames.CompletionResolve, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICompletionResolveHandler : ICanBeResolvedHandler - { - } - - public abstract class CompletionHandler : ICompletionHandler, ICompletionResolveHandler, ICanBeIdentifiedHandler - { - private readonly CompletionRegistrationOptions _options; - - public CompletionHandler(CompletionRegistrationOptions registrationOptions) - { - _options = registrationOptions; - _options.ResolveProvider = true; - } - - public CompletionRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(CompletionParams request, CancellationToken cancellationToken); - public abstract Task Handle(CompletionItem request, CancellationToken cancellationToken); - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - public virtual void SetCapability(CompletionCapability capability) => Capability = capability; - protected CompletionCapability Capability { get; private set; } = null!; - } - - public abstract class PartialCompletionHandlerBase : - AbstractHandlers.PartialResults, ICompletionHandler, - ICompletionResolveHandler - { - protected PartialCompletionHandlerBase(CompletionRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - lenses => new CompletionList(lenses) - ) - { - } - - public abstract Task Handle(CompletionItem request, CancellationToken cancellationToken); - public virtual Guid Id { get; } = Guid.NewGuid(); - } - - public abstract class CompletionHandlerBase : CompletionHandler where T : HandlerIdentity?, new() - { - public CompletionHandlerBase(CompletionRegistrationOptions registrationOptions) : base(registrationOptions) - { - } - - public sealed override async Task Handle(CompletionParams request, CancellationToken cancellationToken) - { - var response = await HandleParams(request, cancellationToken).ConfigureAwait(false); - return response; - } - - public sealed override async Task Handle(CompletionItem request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract Task> HandleParams(CompletionParams request, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CompletionItem request, CancellationToken cancellationToken); - } - - public abstract class PartialCompletionHandlerBase : PartialCompletionHandlerBase where T : HandlerIdentity?, new() - { - protected PartialCompletionHandlerBase(CompletionRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, - progressManager - ) - { - } - - protected sealed override void Handle(CompletionParams request, IObserver> results, CancellationToken cancellationToken) => Handle( - request, - Observer.Create>>( - x => results.OnNext(x.Select(z => (CompletionItem) z)), - results.OnError, - results.OnCompleted - ), cancellationToken - ); - - public sealed override async Task Handle(CompletionItem request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract void Handle(CompletionParams request, IObserver>> results, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(CompletionItem request, CancellationToken cancellationToken); - } - - public static partial class CompletionExtensions - { - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, cap, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.Completion, - new LanguageProtocolDelegatingHandlers.Request( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CompletionCapability, CancellationToken, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, c, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCompletionHandler( - registrationOptions, - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.Completion, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CancellationToken, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingCompletionHandler( - registrationOptions, - (@params, capability, token) => handler(@params, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.Completion, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Func>> handler, - Func, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingCompletionHandler( - registrationOptions, - (@params, capability, token) => handler(@params), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>, CompletionCapability, CancellationToken> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>, CompletionCapability, CancellationToken> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return - registry.AddHandler( - TextDocumentNames.Completion, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CompletionList(x) - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>>, CompletionCapability, CancellationToken> handler, - Func, CompletionCapability, CancellationToken, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCompletionHandler( - registrationOptions, - _.GetRequiredService(), - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.Completion, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CompletionList(x) - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>>, CancellationToken> handler, - Func, CancellationToken, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialCompletionHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>> handler, - CompletionRegistrationOptions? registrationOptions - ) => - OnCompletion(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>> handler, - Func>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.Completion, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new CompletionList(x) - ) - ) - .AddHandler( - TextDocumentNames.CompletionResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnCompletion( - this ILanguageServerRegistry registry, - Action>>> handler, - Func, Task>>? resolveHandler, - CompletionRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CompletionRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingPartialCompletionHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - private class DelegatingCompletionHandler : CompletionHandlerBase where T : HandlerIdentity?, new() - { - private readonly Func>> _handleParams; - private readonly Func, CompletionCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingCompletionHandler( - CompletionRegistrationOptions registrationOptions, - Func>> handleParams, - Func, CompletionCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override Task> HandleParams(CompletionParams request, CancellationToken cancellationToken) => - _handleParams(request, Capability, cancellationToken); - - protected override Task> HandleResolve(CompletionItem request, CancellationToken cancellationToken) => - _handleResolve(request, Capability, cancellationToken); - } - - private class DelegatingPartialCompletionHandler : PartialCompletionHandlerBase where T : HandlerIdentity?, new() - { - private readonly Action>>, CompletionCapability, CancellationToken> _handleParams; - private readonly Func, CompletionCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingPartialCompletionHandler( - CompletionRegistrationOptions registrationOptions, - IProgressManager progressManager, - Action>>, CompletionCapability, CancellationToken> handleParams, - Func, CompletionCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions, progressManager) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override void Handle(CompletionParams request, IObserver>> results, CancellationToken cancellationToken) => - _handleParams(request, results, Capability, cancellationToken); - - protected override Task> HandleResolve(CompletionItem request, CancellationToken cancellationToken) => - _handleResolve(request, Capability, cancellationToken); - } - } -} diff --git a/src/Protocol/Document/IDeclarationHandler.cs b/src/Protocol/Document/IDeclarationHandler.cs deleted file mode 100644 index 9427dc2ea..000000000 --- a/src/Protocol/Document/IDeclarationHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Declaration, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDeclarationHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class DeclarationHandler : IDeclarationHandler - { - private readonly DeclarationRegistrationOptions _options; - public DeclarationHandler(DeclarationRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DeclarationRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DeclarationParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DeclarationCapability capability) => Capability = capability; - protected DeclarationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDefinitionHandler.cs b/src/Protocol/Document/IDefinitionHandler.cs deleted file mode 100644 index 19c19dc3f..000000000 --- a/src/Protocol/Document/IDefinitionHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Definition, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class DefinitionHandler : IDefinitionHandler - { - private readonly DefinitionRegistrationOptions _options; - - public DefinitionHandler(DefinitionRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DefinitionRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DefinitionParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DefinitionCapability capability) => Capability = capability; - protected DefinitionCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDidChangeTextDocumentHandler.cs b/src/Protocol/Document/IDidChangeTextDocumentHandler.cs deleted file mode 100644 index ea1da50da..000000000 --- a/src/Protocol/Document/IDidChangeTextDocumentHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Serial] - [Method(TextDocumentNames.DidChange, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDidChangeTextDocumentHandler : IJsonRpcNotificationHandler, - IRegistration, ICapability - { - } - - public abstract class DidChangeTextDocumentHandler : IDidChangeTextDocumentHandler - { - private readonly TextDocumentChangeRegistrationOptions _options; - public DidChangeTextDocumentHandler(TextDocumentChangeRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentChangeRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDidCloseTextDocumentHandler.cs b/src/Protocol/Document/IDidCloseTextDocumentHandler.cs deleted file mode 100644 index a84d2571f..000000000 --- a/src/Protocol/Document/IDidCloseTextDocumentHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DidClose, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDidCloseTextDocumentHandler : IJsonRpcNotificationHandler, IRegistration, - ICapability - { - } - - public abstract class DidCloseTextDocumentHandler : IDidCloseTextDocumentHandler - { - private readonly TextDocumentRegistrationOptions _options; - public DidCloseTextDocumentHandler(TextDocumentRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDidOpenTextDocumentHandler.cs b/src/Protocol/Document/IDidOpenTextDocumentHandler.cs deleted file mode 100644 index 047d481c2..000000000 --- a/src/Protocol/Document/IDidOpenTextDocumentHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Serial] - [Method(TextDocumentNames.DidOpen, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDidOpenTextDocumentHandler : IJsonRpcNotificationHandler, IRegistration, - ICapability - { - } - - public abstract class DidOpenTextDocumentHandler : IDidOpenTextDocumentHandler - { - private readonly TextDocumentRegistrationOptions _options; - - public DidOpenTextDocumentHandler(TextDocumentRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDidSaveTextDocumentHandler.cs b/src/Protocol/Document/IDidSaveTextDocumentHandler.cs deleted file mode 100644 index 5ecc0b1b3..000000000 --- a/src/Protocol/Document/IDidSaveTextDocumentHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Serial] - [Method(TextDocumentNames.DidSave, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDidSaveTextDocumentHandler : IJsonRpcNotificationHandler, IRegistration, - ICapability - { - } - - public abstract class DidSaveTextDocumentHandler : IDidSaveTextDocumentHandler - { - private readonly TextDocumentSaveRegistrationOptions _options; - public DidSaveTextDocumentHandler(TextDocumentSaveRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentSaveRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentColorHandler.cs b/src/Protocol/Document/IDocumentColorHandler.cs deleted file mode 100644 index fe574121f..000000000 --- a/src/Protocol/Document/IDocumentColorHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DocumentColor, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentColorHandler : IJsonRpcRequestHandler>, IRegistration, - ICapability - { - } - - public abstract class DocumentColorHandler : IDocumentColorHandler - { - private readonly DocumentColorRegistrationOptions _options; - public DocumentColorHandler(DocumentColorRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentColorRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task> Handle(DocumentColorParams request, CancellationToken cancellationToken); - public virtual void SetCapability(ColorProviderCapability capability) => Capability = capability; - protected ColorProviderCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentFormattingHandler.cs b/src/Protocol/Document/IDocumentFormattingHandler.cs deleted file mode 100644 index 017841caf..000000000 --- a/src/Protocol/Document/IDocumentFormattingHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DocumentFormatting, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentFormattingHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class DocumentFormattingHandler : IDocumentFormattingHandler - { - private readonly DocumentFormattingRegistrationOptions _options; - public DocumentFormattingHandler(DocumentFormattingRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentFormattingRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentFormattingParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DocumentFormattingCapability capability) => Capability = capability; - protected DocumentFormattingCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentHighlightHandler.cs b/src/Protocol/Document/IDocumentHighlightHandler.cs deleted file mode 100644 index ca6e29623..000000000 --- a/src/Protocol/Document/IDocumentHighlightHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DocumentHighlight, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentHighlightHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class DocumentHighlightHandler : IDocumentHighlightHandler - { - private readonly DocumentHighlightRegistrationOptions _options; - public DocumentHighlightHandler(DocumentHighlightRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentHighlightRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentHighlightParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DocumentHighlightCapability capability) => Capability = capability; - protected DocumentHighlightCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentLinkHandler.cs b/src/Protocol/Document/IDocumentLinkHandler.cs deleted file mode 100644 index b2c58e422..000000000 --- a/src/Protocol/Document/IDocumentLinkHandler.cs +++ /dev/null @@ -1,528 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DocumentLink, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentLinkHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - [Parallel] - [Method(TextDocumentNames.DocumentLinkResolve, Direction.ClientToServer)] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentLinkResolveHandler : ICanBeResolvedHandler, ICanBeIdentifiedHandler - { - } - - public abstract class DocumentLinkHandler : IDocumentLinkHandler, IDocumentLinkResolveHandler - { - private readonly DocumentLinkRegistrationOptions _options; - - public DocumentLinkHandler(DocumentLinkRegistrationOptions registrationOptions) - { - _options = registrationOptions; - _options.ResolveProvider = true; - } - - public DocumentLinkRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentLinkParams request, CancellationToken cancellationToken); - public abstract Task Handle(DocumentLink request, CancellationToken cancellationToken); - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - public virtual void SetCapability(DocumentLinkCapability capability) => Capability = capability; - protected DocumentLinkCapability Capability { get; private set; } = null!; - } - - public abstract class PartialDocumentLinkHandlerBase : - AbstractHandlers.PartialResults, IDocumentLinkHandler, - IDocumentLinkResolveHandler - { - protected PartialDocumentLinkHandlerBase(DocumentLinkRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - lenses => new DocumentLinkContainer(lenses) - ) - { - } - - public abstract Task Handle(DocumentLink request, CancellationToken cancellationToken); - public virtual Guid Id { get; } = Guid.NewGuid(); - } - - public abstract class DocumentLinkHandlerBase : DocumentLinkHandler where T : HandlerIdentity?, new() - { - public DocumentLinkHandlerBase(DocumentLinkRegistrationOptions registrationOptions) : base(registrationOptions) - { - } - - - public sealed override async Task Handle(DocumentLinkParams request, CancellationToken cancellationToken) - { - var response = await HandleParams(request, cancellationToken).ConfigureAwait(false); - return response; - } - - public sealed override async Task Handle(DocumentLink request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract Task> HandleParams(DocumentLinkParams request, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(DocumentLink request, CancellationToken cancellationToken); - } - - public abstract class PartialDocumentLinkHandlerBase : PartialDocumentLinkHandlerBase where T : HandlerIdentity?, new() - { - protected PartialDocumentLinkHandlerBase(DocumentLinkRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, - progressManager - ) - { - } - - protected sealed override void Handle(DocumentLinkParams request, IObserver> results, CancellationToken cancellationToken) => Handle( - request, - Observer.Create>>( - x => results.OnNext(x.Select(z => (DocumentLink) z)), - results.OnError, - results.OnCompleted - ), cancellationToken - ); - - public sealed override async Task Handle(DocumentLink request, CancellationToken cancellationToken) - { - var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); - return response; - } - - protected abstract void Handle(DocumentLinkParams request, IObserver>> results, CancellationToken cancellationToken); - protected abstract Task> HandleResolve(DocumentLink request, CancellationToken cancellationToken); - } - - public static partial class DocumentLinkExtensions - { - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, cap, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.DocumentLink, - new LanguageProtocolDelegatingHandlers.Request( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func>> handler, - Func, DocumentLinkCapability, CancellationToken, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, c, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingDocumentLinkHandler( - registrationOptions, - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.DocumentLink, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func>> handler, - Func, CancellationToken, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (link, token) => Task.FromResult(link); - - return registry.AddHandler( - _ => new DelegatingDocumentLinkHandler( - registrationOptions, - (@params, capability, token) => handler(@params, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.DocumentLink, - new LanguageProtocolDelegatingHandlers.RequestRegistration( - id, - handler, - registrationOptions - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Func>> handler, - Func, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingDocumentLinkHandler( - registrationOptions, - (@params, capability, token) => handler(@params), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>, DocumentLinkCapability, CancellationToken> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>, DocumentLinkCapability, CancellationToken> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return - registry.AddHandler( - TextDocumentNames.DocumentLink, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new DocumentLinkContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>>, DocumentLinkCapability, CancellationToken> handler, - Func, DocumentLinkCapability, CancellationToken, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, capability, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialDocumentLinkHandler( - registrationOptions, - _.GetRequiredService(), - handler, - resolveHandler - ) - ); - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.DocumentLink, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new DocumentLinkContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>>, CancellationToken> handler, - Func, CancellationToken, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= (lens, token) => Task.FromResult(lens); - - return registry.AddHandler( - _ => new DelegatingPartialDocumentLinkHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer, token), - (lens, capability, token) => resolveHandler(lens, token) - ) - ); - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>> handler, - DocumentLinkRegistrationOptions? registrationOptions - ) => - OnDocumentLink(registry, handler, null, registrationOptions); - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>> handler, - Func>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - var id = Guid.NewGuid(); - - return registry.AddHandler( - TextDocumentNames.DocumentLink, - _ => new LanguageProtocolDelegatingHandlers.PartialResults( - id, - handler, - registrationOptions, - _.GetRequiredService(), - x => new DocumentLinkContainer(x) - ) - ) - .AddHandler( - TextDocumentNames.DocumentLinkResolve, - new LanguageProtocolDelegatingHandlers.CanBeResolved( - id, - resolveHandler, - registrationOptions - ) - ) - ; - } - - public static ILanguageServerRegistry OnDocumentLink( - this ILanguageServerRegistry registry, - Action>>> handler, - Func, Task>>? resolveHandler, - DocumentLinkRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new DocumentLinkRegistrationOptions(); - registrationOptions.ResolveProvider = true; - resolveHandler ??= Task.FromResult; - - return registry.AddHandler( - _ => new DelegatingPartialDocumentLinkHandler( - registrationOptions, - _.GetRequiredService(), - (@params, observer, capability, token) => handler(@params, observer), - (lens, capability, token) => resolveHandler(lens) - ) - ); - } - - private class DelegatingDocumentLinkHandler : DocumentLinkHandlerBase where T : HandlerIdentity?, new() - { - private readonly Func>> _handleParams; - private readonly Func, DocumentLinkCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingDocumentLinkHandler( - DocumentLinkRegistrationOptions registrationOptions, - Func>> handleParams, - Func, DocumentLinkCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override Task> HandleParams(DocumentLinkParams request, CancellationToken cancellationToken) => - _handleParams(request, Capability, cancellationToken); - - protected override Task> HandleResolve(DocumentLink request, CancellationToken cancellationToken) => - _handleResolve(request, Capability, cancellationToken); - } - - private class DelegatingPartialDocumentLinkHandler : PartialDocumentLinkHandlerBase where T : HandlerIdentity?, new() - { - private readonly Action>>, DocumentLinkCapability, CancellationToken> _handleParams; - private readonly Func, DocumentLinkCapability, CancellationToken, Task>> _handleResolve; - - public DelegatingPartialDocumentLinkHandler( - DocumentLinkRegistrationOptions registrationOptions, - IProgressManager progressManager, - Action>>, DocumentLinkCapability, CancellationToken> handleParams, - Func, DocumentLinkCapability, CancellationToken, Task>> handleResolve - ) : base(registrationOptions, progressManager) - { - _handleParams = handleParams; - _handleResolve = handleResolve; - } - - protected override void Handle(DocumentLinkParams request, IObserver>> results, CancellationToken cancellationToken) => - _handleParams(request, results, Capability, cancellationToken); - - protected override Task> HandleResolve(DocumentLink request, CancellationToken cancellationToken) => - _handleResolve(request, Capability, cancellationToken); - } - } -} diff --git a/src/Protocol/Document/IDocumentOnTypeFormattingHandler.cs b/src/Protocol/Document/IDocumentOnTypeFormattingHandler.cs deleted file mode 100644 index 07c106e1a..000000000 --- a/src/Protocol/Document/IDocumentOnTypeFormattingHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.OnTypeFormatting, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentOnTypeFormattingHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - public abstract class DocumentOnTypeFormattingHandler : IDocumentOnTypeFormattingHandler - { - private readonly DocumentOnTypeFormattingRegistrationOptions _options; - public DocumentOnTypeFormattingHandler(DocumentOnTypeFormattingRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentOnTypeFormattingRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentOnTypeFormattingParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DocumentOnTypeFormattingCapability capability) => Capability = capability; - protected DocumentOnTypeFormattingCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentRangeFormattingHandler.cs b/src/Protocol/Document/IDocumentRangeFormattingHandler.cs deleted file mode 100644 index 057b4e246..000000000 --- a/src/Protocol/Document/IDocumentRangeFormattingHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.RangeFormatting, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentRangeFormattingHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - public abstract class DocumentRangeFormattingHandler : IDocumentRangeFormattingHandler - { - private readonly DocumentRangeFormattingRegistrationOptions _options; - public DocumentRangeFormattingHandler(DocumentRangeFormattingRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentRangeFormattingRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentRangeFormattingParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DocumentRangeFormattingCapability capability) => Capability = capability; - protected DocumentRangeFormattingCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IDocumentSymbolHandler.cs b/src/Protocol/Document/IDocumentSymbolHandler.cs deleted file mode 100644 index 9749c497e..000000000 --- a/src/Protocol/Document/IDocumentSymbolHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.DocumentSymbol, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IDocumentSymbolHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - public abstract class DocumentSymbolHandler : IDocumentSymbolHandler - { - private readonly DocumentSymbolRegistrationOptions _options; - public DocumentSymbolHandler(DocumentSymbolRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DocumentSymbolRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DocumentSymbolParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DocumentSymbolCapability capability) => Capability = capability; - protected DocumentSymbolCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IFoldingRangeHandler.cs b/src/Protocol/Document/IFoldingRangeHandler.cs deleted file mode 100644 index 229e9941d..000000000 --- a/src/Protocol/Document/IFoldingRangeHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.FoldingRange, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IFoldingRangeHandler : IJsonRpcRequestHandler?>, - IRegistration, ICapability - { - } - - public abstract class FoldingRangeHandler : IFoldingRangeHandler - { - private readonly FoldingRangeRegistrationOptions _options; - - public FoldingRangeHandler(FoldingRangeRegistrationOptions registrationOptions) => _options = registrationOptions; - - public FoldingRangeRegistrationOptions GetRegistrationOptions() => _options; - - public abstract Task?> Handle( - FoldingRangeRequestParam request, - CancellationToken cancellationToken - ); - - public virtual void SetCapability(FoldingRangeCapability capability) => Capability = capability; - protected FoldingRangeCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IHoverHandler.cs b/src/Protocol/Document/IHoverHandler.cs deleted file mode 100644 index ec1339f7d..000000000 --- a/src/Protocol/Document/IHoverHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Hover, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IHoverHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - public abstract class HoverHandler : IHoverHandler - { - private readonly HoverRegistrationOptions _options; - public HoverHandler(HoverRegistrationOptions registrationOptions) => _options = registrationOptions; - - public HoverRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(HoverParams request, CancellationToken cancellationToken); - public virtual void SetCapability(HoverCapability capability) => Capability = capability; - protected HoverCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IImplementationHandler.cs b/src/Protocol/Document/IImplementationHandler.cs deleted file mode 100644 index 9aa1fba75..000000000 --- a/src/Protocol/Document/IImplementationHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Implementation, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IImplementationHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - public abstract class ImplementationHandler : AbstractHandlers.Request, IImplementationHandler - { - protected ImplementationHandler(ImplementationRegistrationOptions registrationOptions) : base( - registrationOptions - ) - { - } - } -} diff --git a/src/Protocol/Document/IOnTypeRenameHandler.cs b/src/Protocol/Document/IOnTypeRenameHandler.cs deleted file mode 100644 index 929d53b95..000000000 --- a/src/Protocol/Document/IOnTypeRenameHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.OnTypeRename, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IOnTypeRenameHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - public abstract class OnTypeRenameHandler : IOnTypeRenameHandler - { - private readonly OnTypeRenameRegistrationOptions _options; - public OnTypeRenameHandler(OnTypeRenameRegistrationOptions registrationOptions) => _options = registrationOptions; - - public OnTypeRenameRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(OnTypeRenameParams request, CancellationToken cancellationToken); - public virtual void SetCapability(OnTypeRenameClientCapabilities capability) => Capability = capability; - protected OnTypeRenameClientCapabilities Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IPrepareRenameHandler.cs b/src/Protocol/Document/IPrepareRenameHandler.cs deleted file mode 100644 index dec61240b..000000000 --- a/src/Protocol/Document/IPrepareRenameHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.PrepareRename, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IPrepareRenameHandler : IJsonRpcRequestHandler, IRegistration, - ICapability, IDoesNotParticipateInRegistration - { - } - - public abstract class PrepareRenameHandler : IPrepareRenameHandler - { - private readonly TextDocumentRegistrationOptions _options; - public PrepareRenameHandler(TextDocumentRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(PrepareRenameParams request, CancellationToken cancellationToken); - public virtual void SetCapability(RenameCapability capability) => Capability = capability; - protected RenameCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IPublishDiagnosticsHandler.cs b/src/Protocol/Document/IPublishDiagnosticsHandler.cs deleted file mode 100644 index c33501bb7..000000000 --- a/src/Protocol/Document/IPublishDiagnosticsHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.PublishDiagnostics, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageServer), typeof(ILanguageServer))] - public interface IPublishDiagnosticsHandler : IJsonRpcNotificationHandler - { - } - - public abstract class PublishDiagnosticsHandler : IPublishDiagnosticsHandler - { - public abstract Task Handle(PublishDiagnosticsParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Document/IReferencesHandler.cs b/src/Protocol/Document/IReferencesHandler.cs deleted file mode 100644 index d0a919100..000000000 --- a/src/Protocol/Document/IReferencesHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.References, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IReferencesHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - public abstract class ReferencesHandler : IReferencesHandler - { - private readonly ReferenceRegistrationOptions _options; - public ReferencesHandler(ReferenceRegistrationOptions registrationOptions) => _options = registrationOptions; - - public ReferenceRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(ReferenceParams request, CancellationToken cancellationToken); - public virtual void SetCapability(ReferenceCapability capability) => Capability = capability; - protected ReferenceCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IRenameHandler.cs b/src/Protocol/Document/IRenameHandler.cs deleted file mode 100644 index 88a85b6d8..000000000 --- a/src/Protocol/Document/IRenameHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.Rename, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IRenameHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - public abstract class RenameHandler : IRenameHandler - { - private readonly RenameRegistrationOptions _options; - public RenameHandler(RenameRegistrationOptions registrationOptions) => _options = registrationOptions; - - public RenameRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(RenameParams request, CancellationToken cancellationToken); - public virtual void SetCapability(RenameCapability capability) => Capability = capability; - protected RenameCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/ISelectionRangeHandler.cs b/src/Protocol/Document/ISelectionRangeHandler.cs deleted file mode 100644 index 0a0b55d30..000000000 --- a/src/Protocol/Document/ISelectionRangeHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.SelectionRange, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ISelectionRangeHandler : IJsonRpcRequestHandler?>, - IRegistration, ICapability - { - } - - public abstract class SelectionRangeHandler : ISelectionRangeHandler - { - private readonly SelectionRangeRegistrationOptions _options; - - public SelectionRangeHandler(SelectionRangeRegistrationOptions registrationOptions) => _options = registrationOptions; - - public SelectionRangeRegistrationOptions GetRegistrationOptions() => _options; - - public abstract Task?> Handle( - SelectionRangeParams request, - CancellationToken cancellationToken - ); - - public virtual void SetCapability(SelectionRangeCapability capability) => Capability = capability; - protected SelectionRangeCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/ISignatureHelpHandler.cs b/src/Protocol/Document/ISignatureHelpHandler.cs deleted file mode 100644 index a5a2a6acc..000000000 --- a/src/Protocol/Document/ISignatureHelpHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.SignatureHelp, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ISignatureHelpHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class SignatureHelpHandler : ISignatureHelpHandler - { - private readonly SignatureHelpRegistrationOptions _options; - public SignatureHelpHandler(SignatureHelpRegistrationOptions registrationOptions) => _options = registrationOptions; - - public SignatureHelpRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(SignatureHelpParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SignatureHelpCapability capability) => Capability = capability; - protected SignatureHelpCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/ITextDocumentIdentifier.cs b/src/Protocol/Document/ITextDocumentIdentifier.cs index 907c903f7..76da70168 100644 --- a/src/Protocol/Document/ITextDocumentIdentifier.cs +++ b/src/Protocol/Document/ITextDocumentIdentifier.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reactive.Disposables; +// ReSharper disable once CheckNamespace namespace OmniSharp.Extensions.LanguageServer.Protocol.Document { public interface ITextDocumentIdentifier diff --git a/src/Protocol/Document/ITextDocumentSyncHandler.cs b/src/Protocol/Document/ITextDocumentSyncHandler.cs deleted file mode 100644 index 94c0b77fc..000000000 --- a/src/Protocol/Document/ITextDocumentSyncHandler.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - public interface ITextDocumentSyncHandler : IDidChangeTextDocumentHandler, IDidOpenTextDocumentHandler, - IDidCloseTextDocumentHandler, IDidSaveTextDocumentHandler, ITextDocumentIdentifier - { - } - - public abstract class TextDocumentSyncHandler : ITextDocumentSyncHandler - { - private readonly TextDocumentSaveRegistrationOptions _options; - private readonly TextDocumentChangeRegistrationOptions _changeOptions; - - public TextDocumentSyncHandler(TextDocumentSyncKind kind, TextDocumentSaveRegistrationOptions registrationOptions) - { - _options = registrationOptions; - _changeOptions = new TextDocumentChangeRegistrationOptions { - DocumentSelector = registrationOptions.DocumentSelector, - SyncKind = kind - }; - } - - TextDocumentRegistrationOptions IRegistration.GetRegistrationOptions() => _options; - TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions() => _options; - TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions() => _changeOptions; - - public abstract TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri); - public abstract Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken); - public abstract Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken); - public abstract Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken); - public abstract Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } - - public static class TextDocumentSyncExtensions - { - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - onOpenHandler, onCloseHandler, onChangeHandler, - onSaveHandler, getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - onOpenHandler, onCloseHandler, onChangeHandler, - onSaveHandler, getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - (r, c, ct) => onOpenHandler(r, c), - (r, c, ct) => onCloseHandler(r, c), - (r, c, ct) => onChangeHandler(r, c), - (r, c, ct) => onSaveHandler(r, c), - getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - (r, c, ct) => onOpenHandler(r, ct), - (r, c, ct) => onCloseHandler(r, ct), - (r, c, ct) => onChangeHandler(r, ct), - (r, c, ct) => onSaveHandler(r, ct), - getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - (r, c, ct) => onOpenHandler(r, ct), - (r, c, ct) => onCloseHandler(r, ct), - (r, c, ct) => onChangeHandler(r, ct), - (r, c, ct) => onSaveHandler(r, ct), - getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - (r, c, ct) => onOpenHandler(r), - (r, c, ct) => onCloseHandler(r), - (r, c, ct) => onChangeHandler(r), - (r, c, ct) => onSaveHandler(r), - getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - public static ILanguageServerRegistry OnTextDocumentSync( - this ILanguageServerRegistry registry, - TextDocumentSyncKind kind, - Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - TextDocumentSaveRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new TextDocumentSaveRegistrationOptions(); - return registry.AddHandlers( - new DelegatingHandler( - (r, c, ct) => onOpenHandler(r), - (r, c, ct) => onCloseHandler(r), - (r, c, ct) => onChangeHandler(r), - (r, c, ct) => onSaveHandler(r), - getTextDocumentAttributes, registrationOptions, kind - ) - ); - } - - private class DelegatingHandler : TextDocumentSyncHandler - { - private readonly Func _onOpenHandler; - private readonly Func _onCloseHandler; - private readonly Func _onChangeHandler; - private readonly Func _onSaveHandler; - private readonly Func _getTextDocumentAttributes; - private SynchronizationCapability _capability = null!; - - public DelegatingHandler( - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, - Func getTextDocumentAttributes, - TextDocumentSaveRegistrationOptions registrationOptions, - TextDocumentSyncKind kind - ) : base(kind, registrationOptions) - { - _onOpenHandler = onOpenHandler; - _onSaveHandler = onSaveHandler; - _onChangeHandler = onChangeHandler; - _onCloseHandler = onCloseHandler; - _getTextDocumentAttributes = getTextDocumentAttributes; - } - - public DelegatingHandler( - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - Func getTextDocumentAttributes, - TextDocumentSaveRegistrationOptions registrationOptions, - TextDocumentSyncKind kind - ) : this( - (r, c, ct) => { onOpenHandler(r, c, ct); return Task.CompletedTask; }, - (r, c, ct) => { onCloseHandler(r, c, ct); return Task.CompletedTask; }, - (r, c, ct) => { onChangeHandler(r, c, ct); return Task.CompletedTask; }, - (r, c, ct) => { onSaveHandler(r, c, ct); return Task.CompletedTask; }, - getTextDocumentAttributes, - registrationOptions, - kind - ) - { - } - - public override async Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken) - { - await _onOpenHandler.Invoke(request, _capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - public override async Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken) - { - await _onChangeHandler.Invoke(request, _capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - public override async Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken) - { - await _onSaveHandler.Invoke(request, _capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - public override async Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken) - { - await _onCloseHandler.Invoke(request, _capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - public override TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri) => _getTextDocumentAttributes.Invoke(uri); - - public override void SetCapability(SynchronizationCapability capability) => _capability = capability; - } - } -} diff --git a/src/Protocol/Document/ITypeDefinitionHandler.cs b/src/Protocol/Document/ITypeDefinitionHandler.cs deleted file mode 100644 index 914ec5ef5..000000000 --- a/src/Protocol/Document/ITypeDefinitionHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.TypeDefinition, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ITypeDefinitionHandler : IJsonRpcRequestHandler, IRegistration, - ICapability - { - } - - public abstract class TypeDefinitionHandler : ITypeDefinitionHandler - { - private readonly TypeDefinitionRegistrationOptions _options; - public TypeDefinitionHandler(TypeDefinitionRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TypeDefinitionRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(TypeDefinitionParams request, CancellationToken cancellationToken); - public virtual void SetCapability(TypeDefinitionCapability capability) => Capability = capability; - protected TypeDefinitionCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IWillSaveTextDocumentHandler.cs b/src/Protocol/Document/IWillSaveTextDocumentHandler.cs deleted file mode 100644 index 894689f85..000000000 --- a/src/Protocol/Document/IWillSaveTextDocumentHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.WillSave, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IWillSaveTextDocumentHandler : IJsonRpcNotificationHandler, IRegistration, - ICapability - { - } - - public abstract class WillSaveTextDocumentHandler : IWillSaveTextDocumentHandler - { - private readonly TextDocumentRegistrationOptions _options; - public WillSaveTextDocumentHandler(TextDocumentRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(WillSaveTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/IWillSaveWaitUntilTextDocumentHandler.cs b/src/Protocol/Document/IWillSaveWaitUntilTextDocumentHandler.cs deleted file mode 100644 index a1c6a7e3c..000000000 --- a/src/Protocol/Document/IWillSaveWaitUntilTextDocumentHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document -{ - [Parallel] - [Method(TextDocumentNames.WillSaveWaitUntil, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IWillSaveWaitUntilTextDocumentHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - public abstract class WillSaveWaitUntilTextDocumentHandler : IWillSaveWaitUntilTextDocumentHandler - { - private readonly TextDocumentRegistrationOptions _options; - public WillSaveWaitUntilTextDocumentHandler(TextDocumentRegistrationOptions registrationOptions) => _options = registrationOptions; - - public TextDocumentRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(WillSaveWaitUntilTextDocumentParams request, CancellationToken cancellationToken); - public virtual void SetCapability(SynchronizationCapability capability) => Capability = capability; - protected SynchronizationCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Document/Proposals/ICallHierarchyHandler.cs b/src/Protocol/Document/Proposals/ICallHierarchyHandler.cs deleted file mode 100644 index 826fbc8c8..000000000 --- a/src/Protocol/Document/Proposals/ICallHierarchyHandler.cs +++ /dev/null @@ -1,744 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.PrepareCallHierarchy, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICallHierarchyPrepareHandler : - IJsonRpcRequestHandler?>, - IRegistration, ICapability - { - } - - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.CallHierarchyIncoming, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICallHierarchyIncomingHandler : IJsonRpcRequestHandler?>, - IRegistration, ICapability, ICanBeIdentifiedHandler - { - } - - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.CallHierarchyOutgoing, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface ICallHierarchyOutgoingHandler : IJsonRpcRequestHandler?>, - IRegistration, ICapability, ICanBeIdentifiedHandler - { - } - - [Obsolete(Constants.Proposal)] - public abstract class CallHierarchyHandlerBase : ICallHierarchyPrepareHandler, ICallHierarchyIncomingHandler, - ICallHierarchyOutgoingHandler - { - private readonly CallHierarchyRegistrationOptions _options; - public CallHierarchyHandlerBase(CallHierarchyRegistrationOptions registrationOptions) => _options = registrationOptions; - public CallHierarchyRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task?> Handle(CallHierarchyPrepareParams request, CancellationToken cancellationToken); - public abstract Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken); - public abstract Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken); - public virtual void SetCapability(CallHierarchyCapability capability) => Capability = capability; - protected CallHierarchyCapability Capability { get; private set; } = null!; - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - } - - [Obsolete(Constants.Proposal)] - public abstract class PartialCallHierarchyHandlerBase : - AbstractHandlers.PartialResults?, CallHierarchyItem, CallHierarchyCapability, CallHierarchyRegistrationOptions>, - ICallHierarchyPrepareHandler, ICallHierarchyIncomingHandler, ICallHierarchyOutgoingHandler - { - private readonly ICallHierarchyIncomingHandler _incoming; - private readonly ICallHierarchyOutgoingHandler _outgoing; - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.NewGuid(); - - protected PartialCallHierarchyHandlerBase(CallHierarchyRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - lenses => new Container(lenses) - ) - { - _incoming = new PartialIncoming(registrationOptions, progressManager, this); - _outgoing = new PartialOutgoing(registrationOptions, progressManager, this); - } - - public Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken) => - _incoming.Handle(request, cancellationToken); - - public Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken) => - _outgoing.Handle(request, cancellationToken); - - protected abstract void Handle(CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken); - protected abstract void Handle(CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken); - - class PartialIncoming : - AbstractHandlers.PartialResults?, CallHierarchyIncomingCall, CallHierarchyCapability, - CallHierarchyRegistrationOptions - >, ICallHierarchyIncomingHandler - { - private readonly PartialCallHierarchyHandlerBase _self; - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.Empty; - - public PartialIncoming( - CallHierarchyRegistrationOptions registrationOptions, - IProgressManager progressManager, PartialCallHierarchyHandlerBase self - ) : base(registrationOptions, progressManager, x => new Container(x)) - { - _self = self; - } - - protected override void Handle( - CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => _self.Handle(request, results, cancellationToken); - } - - class PartialOutgoing : - AbstractHandlers.PartialResults?, CallHierarchyOutgoingCall, CallHierarchyCapability, - CallHierarchyRegistrationOptions - >, ICallHierarchyOutgoingHandler - { - private readonly PartialCallHierarchyHandlerBase _self; - Guid ICanBeIdentifiedHandler.Id { get; } = Guid.Empty; - - public PartialOutgoing(CallHierarchyRegistrationOptions registrationOptions, IProgressManager progressManager, PartialCallHierarchyHandlerBase self) : base( - registrationOptions, progressManager, x => new Container(x) - ) - { - _self = self; - } - - protected override void Handle( - CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => _self.Handle(request, results, cancellationToken); - } - } - - - public abstract class CallHierarchyHandlerBase : CallHierarchyHandlerBase where T : HandlerIdentity?, new() - { - public CallHierarchyHandlerBase(CallHierarchyRegistrationOptions registrationOptions) : base(registrationOptions) - { - } - - public sealed override async Task?> Handle(CallHierarchyPrepareParams request, CancellationToken cancellationToken) - { - var response = await HandlePrepare(request, cancellationToken); - return new Container(response.Select(z => (CallHierarchyItem) z)); - } - - public sealed override Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken) - { - return HandleIncomingCalls( - new CallHierarchyIncomingCallsParams() { - Item = request.Item, - PartialResultToken = request.PartialResultToken, - WorkDoneToken = request.WorkDoneToken - }, - cancellationToken - ); - } - - public sealed override Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken) - { - return HandleOutgoingCalls( - new CallHierarchyOutgoingCallsParams() { - Item = request.Item, - PartialResultToken = request.PartialResultToken, - WorkDoneToken = request.WorkDoneToken - }, - cancellationToken - ); - } - - protected abstract Task>?> HandlePrepare(CallHierarchyPrepareParams request, CancellationToken cancellationToken); - protected abstract Task?> HandleIncomingCalls(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken); - protected abstract Task?> HandleOutgoingCalls(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken); - } - - public abstract class PartialCallHierarchyHandlerBase : PartialCallHierarchyHandlerBase where T : HandlerIdentity?, new() - { - protected PartialCallHierarchyHandlerBase(CallHierarchyRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, - progressManager - ) - { - } - - protected sealed override void Handle(CallHierarchyPrepareParams request, IObserver> results, CancellationToken cancellationToken) => Handle( - request, - Observer.Create>>( - x => results.OnNext(x.Select(z => (CallHierarchyItem) z)), - results.OnError, - results.OnCompleted - ), cancellationToken - ); - - protected abstract void Handle(CallHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken); - - protected sealed override void Handle( - CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => Handle( - new CallHierarchyIncomingCallsParams() { - Item = request.Item, - PartialResultToken = request.PartialResultToken, - WorkDoneToken = request.WorkDoneToken - }, - results, - cancellationToken - ); - - protected abstract void Handle(CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken); - - protected sealed override void Handle( - CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => Handle( - new CallHierarchyOutgoingCallsParams() { - Item = request.Item, - PartialResultToken = request.PartialResultToken, - WorkDoneToken = request.WorkDoneToken - }, - results, - cancellationToken - ); - - protected abstract void Handle(CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken); - } - - [Obsolete(Constants.Proposal)] - public static partial class CallHierarchyExtensions - { - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func?>> handler, - Func?>> incomingHandler, - Func?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, incomingHandler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, outgoingHandler, registrationOptions) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func>?>> handler, - Func, CallHierarchyCapability, CancellationToken, Task?>> incomingHandler, - Func, CallHierarchyCapability, CancellationToken, Task?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - new DelegatingCallHierarchyHandler( - registrationOptions, - handler, - incomingHandler, - outgoingHandler - ) - ); - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func?>> handler, - Func?>> incomingHandler, - Func?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, incomingHandler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - new LanguageProtocolDelegatingHandlers.Request?, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, outgoingHandler, registrationOptions) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func>?>> handler, - Func, CallHierarchyCapability, Task?>> incomingHandler, - Func, CallHierarchyCapability, Task?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - new DelegatingCallHierarchyHandler( - registrationOptions, - (request, capability, arg3) => handler(request, capability), - (request, capability, arg3) => incomingHandler(request, capability), - (request, capability, arg3) => outgoingHandler(request, capability) - ) - ); - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func?>> handler, - Func?>> incomingHandler, - Func?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return - registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, incomingHandler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, outgoingHandler, registrationOptions) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func>?>> handler, - Func, CancellationToken, Task?>> incomingHandler, - Func, CancellationToken, Task?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - new DelegatingCallHierarchyHandler( - registrationOptions, - (request, capability, arg3) => handler(request, arg3), - (request, capability, arg3) => incomingHandler(request, arg3), - (request, capability, arg3) => outgoingHandler(request, arg3) - ) - ); - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func?>> handler, - Func?>> incomingHandler, - Func?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return - registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, incomingHandler, registrationOptions) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - new LanguageProtocolDelegatingHandlers.RequestRegistration?, - CallHierarchyRegistrationOptions>(id, outgoingHandler, registrationOptions) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Func>?>> handler, - Func, Task?>> incomingHandler, - Func, Task?>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - new DelegatingCallHierarchyHandler( - registrationOptions, - (request, capability, arg3) => handler(request), - (request, capability, arg3) => incomingHandler(request), - (request, capability, arg3) => outgoingHandler(request) - ) - ); - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>, CallHierarchyCapability, CancellationToken> handler, - Action>, CallHierarchyCapability, CancellationToken> incomingHandler, - Action>, CallHierarchyCapability, CancellationToken> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyItem, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions, _.GetRequiredService(), x => new Container(x)) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyIncomingCall, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>( - id, incomingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyOutgoingCall, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>( - id, outgoingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>>, CallHierarchyCapability, CancellationToken> handler, - Action, IObserver>, CallHierarchyCapability, CancellationToken> incomingHandler, - Action, IObserver>, CallHierarchyCapability, CancellationToken> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - _ => new DelegatingPartialCallHierarchyHandler( - registrationOptions, - _.GetRequiredService(), - handler, - incomingHandler, - outgoingHandler - ) - ); - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>, CallHierarchyCapability> handler, - Action>, CallHierarchyCapability> incomingHandler, - Action>, CallHierarchyCapability> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return - registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyItem, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions, _.GetRequiredService(), x => new Container(x)) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyIncomingCall, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>( - id, incomingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyOutgoingCall, - CallHierarchyCapability, - CallHierarchyRegistrationOptions>( - id, outgoingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>>, CallHierarchyCapability> handler, - Action, IObserver>, CallHierarchyCapability> incomingHandler, - Action, IObserver>, CallHierarchyCapability> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - _ => new DelegatingPartialCallHierarchyHandler( - registrationOptions, - _.GetRequiredService(), - (request, observer, arg3, arg4) => handler(request, observer, arg3), - (request, observer, arg3, arg4) => incomingHandler(request, observer, arg3), - (request, observer, arg3, arg4) => outgoingHandler(request, observer, arg3) - ) - ); - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>, CancellationToken> handler, - Action>, CancellationToken> incomingHandler, - Action>, CancellationToken> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return - registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyItem, - CallHierarchyRegistrationOptions>(id, handler, registrationOptions, _.GetRequiredService(), x => new Container(x)) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyIncomingCall, - CallHierarchyRegistrationOptions>( - id, incomingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyOutgoingCall, - CallHierarchyRegistrationOptions>( - id, outgoingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>>, CancellationToken> handler, - Action, IObserver>, CancellationToken> incomingHandler, - Action, IObserver>, CancellationToken> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - _ => new DelegatingPartialCallHierarchyHandler( - registrationOptions, - _.GetRequiredService(), - (request, observer, arg3, arg4) => handler(request, observer, arg4), - (request, observer, arg3, arg4) => incomingHandler(request, observer, arg4), - (request, observer, arg3, arg4) => outgoingHandler(request, observer, arg4) - ) - ); - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>> handler, - Action>> incomingHandler, - Action>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - var id = Guid.NewGuid(); - return - registry.AddHandler( - TextDocumentNames.PrepareCallHierarchy, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyItem, - CallHierarchyRegistrationOptions>(handler, registrationOptions, _.GetRequiredService(), x => new Container(x)) - ) - .AddHandler( - TextDocumentNames.CallHierarchyIncoming, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyIncomingCall, - CallHierarchyRegistrationOptions>( - incomingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - .AddHandler( - TextDocumentNames.CallHierarchyOutgoing, - _ => new LanguageProtocolDelegatingHandlers.PartialResults?, CallHierarchyOutgoingCall, - CallHierarchyRegistrationOptions>( - outgoingHandler, registrationOptions, - _.GetRequiredService(), x => new Container(x) - ) - ) - ; - } - - public static ILanguageServerRegistry OnCallHierarchy( - this ILanguageServerRegistry registry, - Action>>> handler, - Action, IObserver>> incomingHandler, - Action, IObserver>> outgoingHandler, - CallHierarchyRegistrationOptions? registrationOptions - ) where T : HandlerIdentity?, new() - { - registrationOptions ??= new CallHierarchyRegistrationOptions(); - return registry.AddHandler( - _ => new DelegatingPartialCallHierarchyHandler( - registrationOptions, - _.GetRequiredService(), - (request, observer, arg3, arg4) => handler(request, observer), - (request, observer, arg3, arg4) => incomingHandler(request, observer), - (request, observer, arg3, arg4) => outgoingHandler(request, observer) - ) - ); - } - - private class DelegatingCallHierarchyHandler : CallHierarchyHandlerBase where T : HandlerIdentity?, new() - { - private readonly Func>?>> _handlePrepare; - - private readonly Func, CallHierarchyCapability, CancellationToken, Task?>> - _handleIncomingCalls; - - private readonly Func, CallHierarchyCapability, CancellationToken, Task?>> - _handleOutgoingCalls; - - public DelegatingCallHierarchyHandler( - CallHierarchyRegistrationOptions registrationOptions, - Func>?>> handlePrepare, - Func, CallHierarchyCapability, CancellationToken, Task?>> handleIncomingCalls, - Func, CallHierarchyCapability, CancellationToken, Task?>> handleOutgoingCalls - ) : base(registrationOptions) - { - _handlePrepare = handlePrepare; - _handleIncomingCalls = handleIncomingCalls; - _handleOutgoingCalls = handleOutgoingCalls; - } - - protected override Task>?> HandlePrepare(CallHierarchyPrepareParams request, CancellationToken cancellationToken) => - _handlePrepare(request, Capability, cancellationToken); - - protected override Task?> HandleIncomingCalls(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken) => - _handleIncomingCalls(request, Capability, cancellationToken); - - protected override Task?> HandleOutgoingCalls(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken) => - _handleOutgoingCalls(request, Capability, cancellationToken); - } - - private class DelegatingPartialCallHierarchyHandler : PartialCallHierarchyHandlerBase where T : HandlerIdentity?, new() - { - private readonly Action>>, CallHierarchyCapability, CancellationToken> _handleParams; - - private readonly Action, IObserver>, CallHierarchyCapability, CancellationToken> - _handleIncoming; - - private readonly Action, IObserver>, CallHierarchyCapability, CancellationToken> - _handleOutgoing; - - public DelegatingPartialCallHierarchyHandler( - CallHierarchyRegistrationOptions registrationOptions, - IProgressManager progressManager, - Action>>, CallHierarchyCapability, CancellationToken> handleParams, - Action, IObserver>, CallHierarchyCapability, CancellationToken> handleIncoming, - Action, IObserver>, CallHierarchyCapability, CancellationToken> handleOutgoing - ) : base(registrationOptions, progressManager) - { - _handleParams = handleParams; - _handleIncoming = handleIncoming; - _handleOutgoing = handleOutgoing; - } - - protected override void Handle(CallHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken) => - _handleParams(request, results, Capability, cancellationToken); - - protected override void Handle( - CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => _handleIncoming(request, results, Capability, cancellationToken); - - protected override void Handle( - CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken - ) => _handleOutgoing(request, results, Capability, cancellationToken); - } - } -} diff --git a/src/Protocol/Document/Proposals/IMonikerHandler.cs b/src/Protocol/Document/Proposals/IMonikerHandler.cs deleted file mode 100644 index e1fda460d..000000000 --- a/src/Protocol/Document/Proposals/IMonikerHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.Moniker, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IMonikerHandler : - IJsonRpcRequestHandler?>, - IRegistration, - ICapability - { - } - - [Obsolete(Constants.Proposal)] - public abstract class MonikerHandlerBase : IMonikerHandler - { - private readonly MonikerRegistrationOptions _options; - - protected MonikerHandlerBase(MonikerRegistrationOptions registrationOptions) - { - _options = registrationOptions; - } - - public MonikerRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task?> Handle(MonikerParams request, CancellationToken cancellationToken); - public virtual void SetCapability(MonikerCapability capability) => Capability = capability; - protected MonikerCapability Capability { get; private set; } = null!; - } - - [Obsolete(Constants.Proposal)] - public abstract class PartialMonikerHandlerBase : - AbstractHandlers.PartialResults?, Moniker, MonikerCapability, MonikerRegistrationOptions>, IMonikerHandler - { - protected PartialMonikerHandlerBase(MonikerRegistrationOptions registrationOptions, IProgressManager progressManager) : base( - registrationOptions, progressManager, - items => new Container(items) - ) - { - } - - public virtual Guid Id { get; } = Guid.NewGuid(); - } -} diff --git a/src/Protocol/Document/Proposals/ISemanticTokensHandler.cs b/src/Protocol/Document/Proposals/ISemanticTokensHandler.cs deleted file mode 100644 index 484a72dd7..000000000 --- a/src/Protocol/Document/Proposals/ISemanticTokensHandler.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.SemanticTokensFull, Direction.ClientToServer)] - [GenerateHandlerMethods] - public interface ISemanticTokensHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)] - [GenerateHandlerMethods] - public interface ISemanticTokensDeltaHandler : - IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(TextDocumentNames.SemanticTokensRange, Direction.ClientToServer)] - [GenerateHandlerMethods] - public interface ISemanticTokensRangeHandler : IJsonRpcRequestHandler, - IRegistration, ICapability - { - } - - [Obsolete(Constants.Proposal)] - public abstract class SemanticTokensHandlerBase : ISemanticTokensHandler, ISemanticTokensDeltaHandler, - ISemanticTokensRangeHandler - { - private readonly SemanticTokensRegistrationOptions _options; - - public SemanticTokensHandlerBase(SemanticTokensRegistrationOptions registrationOptions) => _options = registrationOptions; - - public SemanticTokensRegistrationOptions GetRegistrationOptions() => _options; - - public virtual async Task Handle(SemanticTokensParams request, CancellationToken cancellationToken) - { - var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); - var builder = document.Create(); - await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); - return builder.Commit().GetSemanticTokens(); - } - - public virtual async Task Handle(SemanticTokensDeltaParams request, CancellationToken cancellationToken) - { - var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); - var builder = document.Edit(request); - await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); - return builder.Commit().GetSemanticTokensEdits(); - } - - public virtual async Task Handle(SemanticTokensRangeParams request, CancellationToken cancellationToken) - { - var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); - var builder = document.Create(); - await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); - return builder.Commit().GetSemanticTokens(request.Range); - } - - public virtual void SetCapability(SemanticTokensCapability capability) => Capability = capability; - protected SemanticTokensCapability Capability { get; private set; } = null!; - protected abstract Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, CancellationToken cancellationToken); - protected abstract Task GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken); - } - - public static partial class SemanticTokensExtensions - { - public static ILanguageServerRegistry OnSemanticTokens( - this ILanguageServerRegistry registry, - Func tokenize, - Func> getSemanticTokensDocument, - SemanticTokensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new SemanticTokensRegistrationOptions { - Full = new SemanticTokensCapabilityRequestFull() - }; - registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); - if (registrationOptions.Full?.IsValue == true) - { - registrationOptions.Full.Value.Delta = true; - } - - return registry.AddHandlers( - new DelegatingHandlerBase(tokenize, getSemanticTokensDocument, registrationOptions) - ); - } - - public static ILanguageServerRegistry OnSemanticTokens( - this ILanguageServerRegistry registry, - Func tokenize, - Func> getSemanticTokensDocument, - SemanticTokensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new SemanticTokensRegistrationOptions { - Full = new SemanticTokensCapabilityRequestFull() - }; - registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); - if (registrationOptions.Full?.IsValue == true) - { - registrationOptions.Full.Value.Delta = true; - } - - return registry.AddHandlers( - new DelegatingHandlerBase( - (a, t, c, ct) => tokenize(a, t, ct), - (a, c, ct) => getSemanticTokensDocument(a, ct), - registrationOptions - ) - ); - } - - public static ILanguageServerRegistry OnSemanticTokens( - this ILanguageServerRegistry registry, - Func tokenize, - Func> getSemanticTokensDocument, - SemanticTokensRegistrationOptions? registrationOptions - ) - { - registrationOptions ??= new SemanticTokensRegistrationOptions { - Full = new SemanticTokensCapabilityRequestFull() - }; - registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); - if (registrationOptions.Full?.IsValue == true) - { - registrationOptions.Full.Value.Delta = true; - } - - return registry.AddHandlers( - new DelegatingHandlerBase( - (a, t, c, ct) => tokenize(a, t), - (a, c, ct) => getSemanticTokensDocument(a), - registrationOptions - ) - ); - } - - private class DelegatingHandlerBase : SemanticTokensHandlerBase - { - private readonly Func _tokenize; - private readonly Func> _getSemanticTokensDocument; - - private SemanticTokensCapability _capability = null!; - - public DelegatingHandlerBase( - Func tokenize, - Func> getSemanticTokensDocument, - SemanticTokensRegistrationOptions registrationOptions - ) : base(registrationOptions) - { - _tokenize = tokenize; - _getSemanticTokensDocument = getSemanticTokensDocument; - } - - protected override Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, CancellationToken cancellationToken) - => _tokenize(builder, identifier, _capability, cancellationToken); - - protected override Task GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken) - => _getSemanticTokensDocument(@params, _capability, cancellationToken); - - public override void SetCapability(SemanticTokensCapability capability) => _capability = capability; - } - - public static IRequestProgressObservable RequestSemanticTokens( - this ITextDocumentLanguageClient mediator, - SemanticTokensParams @params, CancellationToken cancellationToken = default - ) => - mediator.ProgressManager.MonitorUntil( - @params, (partial, result) => new SemanticTokens { - Data = partial.Data, - ResultId = result?.ResultId - }, cancellationToken - ); - - public static IRequestProgressObservable RequestSemanticTokensDelta( - this ITextDocumentLanguageClient mediator, SemanticTokensDeltaParams @params, CancellationToken cancellationToken = default - ) => - mediator.ProgressManager.MonitorUntil( - @params, (partial, result) => { - if (partial.IsDelta) - { - return new SemanticTokensFullOrDelta( - new SemanticTokensDelta { - Edits = partial.Delta!.Edits, - ResultId = result?.Delta?.ResultId ?? result?.Full?.ResultId - } - ); - } - - if (partial.IsFull) - { - return new SemanticTokensFullOrDelta( - new SemanticTokens { - Data = partial.Full!.Data, - ResultId = result?.Full?.ResultId ?? result?.Delta?.ResultId - } - ); - } - - return new SemanticTokensFullOrDelta(new SemanticTokens()); - }, cancellationToken - ); - - public static IRequestProgressObservable RequestSemanticTokensRange( - this ITextDocumentLanguageClient mediator, - SemanticTokensRangeParams @params, CancellationToken cancellationToken = default - ) => - mediator.ProgressManager.MonitorUntil( - @params, (partial, result) => new SemanticTokens { - Data = partial.Data, - ResultId = result?.ResultId - }, cancellationToken - ); - } -} diff --git a/src/Protocol/Features/Client/LogTraceFeature.cs b/src/Protocol/Features/Client/LogTraceFeature.cs new file mode 100644 index 000000000..4ad507874 --- /dev/null +++ b/src/Protocol/Features/Client/LogTraceFeature.cs @@ -0,0 +1,30 @@ +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(GeneralNames.LogTrace, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer))] + public class LogTraceParams : IRequest + { + /// + /// The message to be logged. + /// + public string Message { get; set; } = null!; + + /// + /// Additional information that can be computed if the `trace` configuration is set to `'verbose'` + /// + [Optional] + public string? Verbose { get; set; } + } + } +} diff --git a/src/Protocol/Features/Client/RegistrationFeature.cs b/src/Protocol/Features/Client/RegistrationFeature.cs new file mode 100644 index 000000000..feb26aef6 --- /dev/null +++ b/src/Protocol/Features/Client/RegistrationFeature.cs @@ -0,0 +1,217 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client", Name = "RegisterCapability"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) + ] + public class RegistrationParams : IJsonRpcRequest + { + public RegistrationContainer Registrations { get; set; } = null!; + } + + [Parallel] + [Method(ClientNames.UnregisterCapability, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Client", Name = "UnregisterCapability"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) + ] + public partial class UnregistrationParams : IJsonRpcRequest + { + public UnregistrationContainer? Unregisterations { get; set; } + + // Placeholder for v4 support + [JsonIgnore] + public UnregistrationContainer? Unregistrations + { + get => Unregisterations; + set => Unregisterations = value; + } + } + + /// + /// General paramters to to regsiter for a capability. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] + public partial class Registration + { + /// + /// The id used to register the request. The id can be used to deregister + /// the request again. + /// + public string Id { get; set; } = null!; + + /// + /// The method / capability to register for. + /// + public string Method { get; set; } = null!; + + /// + /// Options necessary for the registration. + /// + [Optional] + public object? RegisterOptions { get; set; } + + private string DebuggerDisplay => $"[{Id}] {( RegisterOptions is ITextDocumentRegistrationOptions td ? $"{td.DocumentSelector}" : string.Empty )} {Method}"; + + /// + public override string ToString() => DebuggerDisplay; + + public static Unregistration ToUnregistration(Registration registration) => new Unregistration() { + Id = registration.Id, + Method = registration.Method, + }; + + public class TextDocumentComparer : IEqualityComparer + { + public bool Equals(Registration? x, Registration? y) + { + if (ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, null)) return false; + if (ReferenceEquals(y, null)) return false; + if (x.GetType() != y.GetType()) return false; + if (x.RegisterOptions is ITextDocumentRegistrationOptions xTdro && y.RegisterOptions is ITextDocumentRegistrationOptions yTdro) + { + // Id doesn't matter if they target the same text document + // this is arbitrary but should be good in most cases. + return ( x.Id == y.Id || xTdro.DocumentSelector == yTdro.DocumentSelector ) && x.Method == y.Method; + } + + return x.Id == y.Id && x.Method == y.Method; + } + + public int GetHashCode(Registration? obj) + { + unchecked + { + if (obj!.RegisterOptions is ITextDocumentRegistrationOptions tdro) + { + var hashCode = obj.Method.GetHashCode(); + return ( hashCode * 397 ) ^ ( tdro.DocumentSelector != null ? tdro.DocumentSelector.GetHashCode() : 0 ); + } + else + { + var hashCode = obj!.Id.GetHashCode(); + hashCode = ( hashCode * 397 ) ^ obj.Method.GetHashCode(); + return ( hashCode * 397 ) ^ ( obj.RegisterOptions != null ? obj.RegisterOptions.GetHashCode() : 0 ); + } + } + } + } + } + + /// + /// General parameters to unregister a request or notification. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] + public partial class Unregistration + { + /// + /// The id used to unregister the request or notification. Usually an id + /// provided during the register request. + /// + public string Id { get; set; } = null!; + + /// + /// The method to unregister for. + /// + public string Method { get; set; } = null!; + + public static implicit operator Unregistration(Registration registration) => + new Unregistration { + Id = registration.Id, + Method = registration.Method + }; + + private string DebuggerDisplay => $"[{Id}] {Method}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + public partial class UnregistrationContainer + { + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static UnregistrationContainer? From(IEnumerable? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator UnregistrationContainer?(Registration[] items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static UnregistrationContainer? From(params Registration[] items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator UnregistrationContainer?(Collection? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static UnregistrationContainer? From(Collection? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator UnregistrationContainer?(List? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static UnregistrationContainer? From(List? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator UnregistrationContainer?(ImmutableList? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static UnregistrationContainer? From(ImmutableList? items) => items switch { + not null => new UnregistrationContainer(items.Select(Registration.ToUnregistration)), + _ => null + }; + } + } + + namespace Client + { + } +} diff --git a/src/Protocol/Features/Document/CodeActionFeature.cs b/src/Protocol/Features/Document/CodeActionFeature.cs new file mode 100644 index 000000000..d32338eef --- /dev/null +++ b/src/Protocol/Features/Document/CodeActionFeature.cs @@ -0,0 +1,522 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Reactive; +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; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + /// + /// Params for the CodeActionRequest + /// + [Parallel] + [Method(TextDocumentNames.CodeAction, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CodeActionRegistrationOptions)), Capability(typeof(CodeActionCapability)), Resolver(typeof(CodeAction))] + public partial class CodeActionParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams + { + /// + /// The document in which the command was invoked. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The range for which the command was invoked. + /// + public Range Range { get; set; } = null!; + + /// + /// Context carrying additional information. + /// + public CodeActionContext Context { get; set; } = null!; + } + + /// + /// Contains additional diagnostic information about the context in which + /// a code action is run. + /// + public class CodeActionContext + { + /// + /// An array of diagnostics known on the client side overlapping the range provided to the + /// `textDocument/codeAction` request. They are provied so that the server knows which + /// errors are currently presented to the user for the given range. There is no guarantee + /// that these accurately reflect the error state of the resource. The primary parameter + /// to compute code actions is the provided range. + /// + public Container Diagnostics { get; set; } = null!; + + /// + /// Requested kind of actions to return. + /// + /// Actions not of this kind are filtered out by the client before being shown. So servers + /// can omit computing them. + /// + [Optional] + public Container? Only { get; set; } + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.CodeActionResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CodeActionResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateTypedData, + GenerateContainer + ] + [RegistrationOptions(typeof(CodeActionRegistrationOptions)), Capability(typeof(CodeActionCapability))] + public partial class CodeAction : ICanBeResolved, IRequest + { + /// + /// A short, human-readable, title for this code action. + /// + public string Title { get; set; } = null!; + + /// + /// The kind of the code action. + /// + /// Used to filter code actions. + /// + [Optional] + public CodeActionKind Kind { get; set; } + + /// + /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted + /// by keybindings. + /// + /// A quick fix should be marked preferred if it properly addresses the underlying error. + /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take. + /// + /// @since 3.15.0 + /// + [Optional] + public bool IsPreferred { get; set; } + + /// + /// The diagnostics that this code action resolves. + /// + [Optional] + public Container? Diagnostics { get; set; } + + /// + /// The workspace edit this code action performs. + /// + [Optional] + public WorkspaceEdit? Edit { get; set; } + + /// + /// A command this code action executes. If a code action + /// provides an edit and a command, first the edit is + /// executed and then the command. + /// + [Optional] + public Command? Command { get; set; } + + /// + /// Marks that the code action cannot currently be applied. + /// + /// Clients should follow the following guidelines regarding disabled code actions: + /// + /// - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) + /// code action menu. + /// + /// - Disabled actions are shown as faded out in the code action menu when the user request a more specific type + /// of code action, such as refactorings. + /// + /// - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) + /// that auto applies a code action and only a disabled code actions are returned, the client should show the user an + /// error message with `reason` in the editor. + /// + /// @since 3.16.0 + /// + [Optional] + public CodeActionDisabled? Disabled { get; set; } + + /// + /// A data entry field that is preserved on a document link between a + /// DocumentLinkRequest and a DocumentLinkResolveRequest. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"[{Kind}] {Title}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + /// + /// Marks that the code action cannot currently be applied. + /// + /// Clients should follow the following guidelines regarding disabled code actions: + /// + /// - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) + /// code action menu. + /// + /// - Disabled actions are shown as faded out in the code action menu when the user request a more specific type + /// of code action, such as refactorings. + /// + /// - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) + /// that auto applies a code action and only a disabled code actions are returned, the client should show the user an + /// error message with `reason` in the editor. + /// + /// @since 3.16.0 + /// + public class CodeActionDisabled + { + /// + /// Human readable description of why the code action is currently disabled. + /// + /// This is displayed in the code actions UI. + /// + public string Reason { get; set; } = null!; + } + + [JsonConverter(typeof(CommandOrCodeActionConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] + public class CommandOrCodeAction : ICanBeResolved // This to ensure that code actions get updated as expected + { + private CodeAction? _codeAction; + private Command? _command; + + public CommandOrCodeAction(CodeAction value) + { + _codeAction = value; + _command = default; + } + + public CommandOrCodeAction(Command value) + { + _codeAction = default; + _command = value; + } + + public bool IsCommand => _command != null; + + public Command? Command + { + get => _command; + set { + _command = value; + _codeAction = null; + } + } + + public bool IsCodeAction => _codeAction != null; + + public CodeAction? CodeAction + { + get => _codeAction; + set { + _command = default; + _codeAction = value; + } + } + + public object? RawValue + { + get { + if (IsCommand) return Command!; + if (IsCodeAction) return CodeAction!; + return default; + } + } + + public static CommandOrCodeAction From(Command value) => new(value); + public static implicit operator CommandOrCodeAction(Command value) => new(value); + + public static CommandOrCodeAction From(CodeAction value) => new(value); + public static implicit operator CommandOrCodeAction(CodeAction value) => new(value); + public static CommandOrCodeAction From(CodeAction value) where T : HandlerIdentity? => new(value); + + private string DebuggerDisplay => $"{( IsCommand ? $"command: {Command}" : IsCodeAction ? $"code action: {CodeAction}" : "..." )}"; + + /// + public override string ToString() => DebuggerDisplay; + + JToken? ICanBeResolved.Data + { + get => _codeAction?.Data; + set { + if (_codeAction == null) return; + _codeAction.Data = value; + } + } + } + + public partial class CodeActionContainer + { + public static implicit operator CommandOrCodeActionContainer(CodeActionContainer container) => new(container.Select(CommandOrCodeAction.From)); + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeActionProvider))] + [RegistrationOptionsConverter(typeof(CodeActionRegistrationOptionsConverter))] + public partial class CodeActionRegistrationOptions : IWorkDoneProgressOptions, ITextDocumentRegistrationOptions + { + /// + /// CodeActionKinds that this server may return. + /// + /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + /// may list out every specific kind they provide. + /// + [Optional] + public Container? CodeActionKinds { get; set; } = new(); + + /// + /// The server provides support to resolve additional + /// information for a code action. + /// + /// @since 3.16.0 + /// + public bool ResolveProvider { get; set; } + + class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public CodeActionRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CodeActionProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(CodeActionRegistrationOptions source) + { + return new() { + CodeActionKinds = source.CodeActionKinds, + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICodeActionResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } + } + + /// + /// A set of predefined code action kinds + /// + [DebuggerDisplay("{" + nameof(_value) + "}")] + [JsonConverter(typeof(EnumLikeStringConverter))] + public readonly struct CodeActionKind : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(CodeActionKind) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + } + ); + + public static IEnumerable Defaults => _defaults.Value; + + /// + /// Base kind for quickfix actions: '' + /// + public static readonly CodeActionKind Empty = new CodeActionKind(""); + + /// + /// Base kind for quickfix actions: 'quickfix' + /// + public static readonly CodeActionKind QuickFix = new CodeActionKind("quickfix"); + + /// + /// Base kind for refactoring actions: 'refactor' + /// + public static readonly CodeActionKind Refactor = new CodeActionKind("refactor"); + + /// + /// Base kind for refactoring extraction actions: 'refactor.extract' + /// + /// Example extract actions: + /// + /// - Extract method + /// - Extract function + /// - Extract variable + /// - Extract interface from class + /// - ... + /// + public static readonly CodeActionKind RefactorExtract = new CodeActionKind("refactor.extract"); + + /// + /// Base kind for refactoring inline actions: 'refactor.inline' + /// + /// Example inline actions: + /// + /// - Inline function + /// - Inline variable + /// - Inline constant + /// - ... + /// + public static readonly CodeActionKind RefactorInline = new CodeActionKind("refactor.inline"); + + /// + /// Base kind for refactoring rewrite actions: 'refactor.rewrite' + /// + /// Example rewrite actions: + /// + /// - Convert JavaScript function to class + /// - Add or remove parameter + /// - Encapsulate field + /// - Make method static + /// - Move method to base class + /// - ... + /// + public static readonly CodeActionKind RefactorRewrite = new CodeActionKind("refactor.rewrite"); + + /// + /// Base kind for source actions: `source` + /// + /// Source code actions apply to the entire file. + /// + public static readonly CodeActionKind Source = new CodeActionKind("source"); + + /// + /// Base kind for an organize imports source action: `source.organizeImports` + /// + public static readonly CodeActionKind SourceOrganizeImports = new CodeActionKind("source.organizeImports"); + + private readonly string? _value; + + public CodeActionKind(string kind) => _value = kind; + + public static implicit operator CodeActionKind(string kind) => new CodeActionKind(kind); + + public static implicit operator string(CodeActionKind kind) => kind._value ?? string.Empty; + + /// + public override string ToString() => _value ?? string.Empty; + + public bool Equals(CodeActionKind other) => _value == other._value; + + public override bool Equals(object obj) => obj is CodeActionKind other && Equals(other); + + public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; + + public static bool operator ==(CodeActionKind left, CodeActionKind right) => left.Equals(right); + + public static bool operator !=(CodeActionKind left, CodeActionKind right) => !left.Equals(right); + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeAction))] + public partial class CodeActionCapability : DynamicCapability, ConnectedCapability + { + /// + /// The client support code action literals as a valid + /// response of the `textDocument/codeAction` request. + /// + /// Since 3.8.0 + /// + [Optional] + public CodeActionLiteralSupportOptions? CodeActionLiteralSupport { get; set; } + + /// + /// Whether code action supports the `isPreferred` property. + /// @since 3.15.0 + /// + [Optional] + public bool IsPreferredSupport { get; set; } + + /// + /// Whether code action supports the `disabled` property. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public bool DisabledSupport { get; set; } + + /// + /// Whether code action supports the `data` property which is + /// preserved between a `textDocument/codeAction` and a `codeAction/resolve` request. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public bool DataSupport { get; set; } + + /// + /// Whether the client supports resolving additional code action + /// properties via a separate `codeAction/resolve` request. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public CodeActionCapabilityResolveSupportOptions? ResolveSupport { get; set; } + } + + public class CodeActionLiteralSupportOptions + { + /// + /// The code action kind is support with the following value + /// set. + /// + public CodeActionKindCapabilityOptions CodeActionKind { get; set; } = null!; + } + + public class CodeActionKindCapabilityOptions + { + /// + /// The code action kind values the client supports. When this + /// property exists the client also guarantees that it will + /// handle values outside its set gracefully and falls back + /// to a default value when unknown. + /// + public Container ValueSet { get; set; } = null!; + } + + /// + /// Whether the client supports resolving additional code action + /// properties via a separate `codeAction/resolve` request. + /// + /// @since 3.16.0 - proposed state + /// + public class CodeActionCapabilityResolveSupportOptions + { + /// + /// The properties that a client can resolve lazily. + /// + public Container Properties { get; set; } = new Container(); + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/CodeLensFeature.cs b/src/Protocol/Features/Document/CodeLensFeature.cs new file mode 100644 index 000000000..f29293f40 --- /dev/null +++ b/src/Protocol/Features/Document/CodeLensFeature.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using DryIoc; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.CodeLens, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CodeLensRegistrationOptions)), Capability(typeof(CodeLensCapability)), Resolver(typeof(CodeLens))] + public partial class CodeLensParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, IPartialItemsRequest + { + /// + /// The document to request code lens for. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + /// + /// A code lens represents a command that should be shown along with + /// source text, like the number of references, a way to run tests, etc. + /// + /// A code lens is _unresolved_ when no command is associated to it. For performance + /// reasons the creation of a code lens and resolving should be done in two stages. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CodeLensResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateTypedData, + GenerateContainer + ] + [RegistrationOptions(typeof(CodeLensRegistrationOptions)), Capability(typeof(CodeLensCapability))] + public partial class CodeLens : IRequest, ICanBeResolved + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; set; } = null!; + + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command { get; set; } + + /// + /// A data entry field that is preserved on a code lens item between + /// a code lens and a code lens resolve request. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"{Range}{( Command != null ? $" {Command}" : "" )}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeLensProvider))] + [RegistrationOptionsConverter(typeof(CodeLensRegistrationOptionsConverter))] + public partial class CodeLensRegistrationOptions : IWorkDoneProgressOptions, ITextDocumentRegistrationOptions + { + /// + /// Code lens has a resolve provider as well. + /// + [Optional] + public bool ResolveProvider { get; set; } + + private class CodeLensRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public CodeLensRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CodeLensProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(CodeLensRegistrationOptions source) + { + return new() { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICodeLensResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress + }; + } + } + } + } + + namespace Models.Proposals + { + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(CodeLensWorkspaceClientCapabilities))] + public partial class CodeLensRefreshParams : IRequest + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeLens))] + public partial class CodeLensCapability : DynamicCapability, ConnectedCapability + { + } + + /// + /// Capabilities specific to the code lens requests scoped to the + /// workspace. + /// + /// @since 3.16.0 - proposed state. + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.Workspace), nameof(WorkspaceClientCapabilities.CodeLens))] + public class CodeLensWorkspaceClientCapabilities : ICapability + { + /// + /// Whether the client implementation supports a refresh request send from the server + /// to the client. This is useful if a server detects a change which requires a + /// re-calculation of all code lenses. + /// + [Optional] + public bool RefreshSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/ColorFeature.cs b/src/Protocol/Features/Document/ColorFeature.cs new file mode 100644 index 000000000..a1286ea7d --- /dev/null +++ b/src/Protocol/Features/Document/ColorFeature.cs @@ -0,0 +1,156 @@ +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.ColorPresentation, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentColorRegistrationOptions)), Capability(typeof(ColorProviderCapability))] + public partial class ColorPresentationParams : IRequest> + { + /// + /// The document to provide document links for. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The actual color value for this color range. + /// + public DocumentColor Color { get; set; } = null!; + + /// + /// The range in the document where this color appers. + /// + public Range Range { get; set; } = null!; + } + + [Parallel] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentColorRegistrationOptions)), Capability(typeof(ColorProviderCapability))] + public partial class ColorPresentation + { + /// + /// The label of this color presentation. It will be shown on the color + /// picker header. By default this is also the text that is inserted when selecting + /// this color presentation. + /// + public string Label { get; set; } = null!; + + /// + /// An [edit](#TextEdit) which is applied to a document when selecting + /// this presentation for the color. When `falsy` the [label](#ColorPresentation.label) + /// is used. + /// + [Optional] + public TextEdit? TextEdit { get; set; } + + /// + /// An optional array of additional [text edits](#TextEdit) that are applied when + /// selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. + /// + [Optional] + public TextEditContainer? AdditionalTextEdits { get; set; } + } + + [Parallel] + [Method(TextDocumentNames.DocumentColor, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentColorRegistrationOptions)), Capability(typeof(ColorProviderCapability))] + public partial class DocumentColorParams : IPartialItemsRequest, ColorInformation>, IWorkDoneProgressParams + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + public partial class ColorInformation + { + /// + /// The range in the document where this color appers. + /// + public Range Range { get; set; } = null!; + + /// + /// The actual color value for this color range. + /// + public DocumentColor Color { get; set; } = null!; + } + + /// + /// Represents a color in RGBA space. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class DocumentColor + { + /// + /// The red component of this color in the range [0-1]. + /// + public double Red { get; set; } + + /// + /// The green component of this color in the range [0-1]. + /// + public double Green { get; set; } + + /// + /// The blue component of this color in the range [0-1]. + /// + public double Blue { get; set; } + + /// + /// The alpha component of this color in the range [0-1]. + /// + public double Alpha { get; set; } + + private string DebuggerDisplay => $"R:{Red} G:{Green} B:{Blue} A:{Alpha}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.ColorProvider))] + public partial class DocumentColorRegistrationOptions : IWorkDoneProgressOptions, ITextDocumentRegistrationOptions, IStaticRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.ColorProvider))] + public partial class ColorProviderCapability : DynamicCapability, ConnectedCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/CompletionFeature.cs b/src/Protocol/Features/Document/CompletionFeature.cs new file mode 100644 index 000000000..0b7d34240 --- /dev/null +++ b/src/Protocol/Features/Document/CompletionFeature.cs @@ -0,0 +1,599 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using DryIoc; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Completion, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CompletionRegistrationOptions)), Capability(typeof(CompletionCapability)), Resolver(typeof(CompletionItem))] + public partial class CompletionParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + /// + /// The completion context. This is only available it the client specifies to send + /// this using `Capability.textDocument.completion.contextSupport === true` + /// + [Optional] + public CompletionContext? Context { get; set; } + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.CompletionResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CompletionResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateContainer("CompletionList"), + GenerateTypedData + ] + [RegistrationOptions(typeof(CompletionRegistrationOptions)), Capability(typeof(CompletionCapability))] + public partial class CompletionItem : ICanBeResolved, IRequest + { + /// + /// The label of this completion item. By default + /// also the text that is inserted when selecting + /// this completion. + /// + public string Label { get; set; } = null!; + + /// + /// The kind of this completion item. Based of the kind + /// an icon is chosen by the editor. + /// + [Optional] + public CompletionItemKind Kind { get; set; } + + /// + /// Tags for this completion item. + /// + /// @since 3.15.0 + /// + [Optional] + public Container? Tags { get; set; } + + /// + /// A human-readable string with additional information + /// about this item, like type or symbol information. + /// + [Optional] + public string? Detail { get; set; } + + /// + /// A human-readable string that represents a doc-comment. + /// + [Optional] + public StringOrMarkupContent? Documentation { get; set; } + + /// + /// Indicates if this item is deprecated. + /// + [Optional] + public bool Deprecated { get; set; } + + /// + /// Select this item when showing. + /// + /// *Note* that only one completion item can be selected and that the + /// tool / client decides which item that is. The rule is that the *first* + /// item of those that match best is selected. + /// + [Optional] + public bool Preselect { get; set; } + + /// + /// A string that shoud be used when comparing this item + /// with other items. When `falsy` the label is used. + /// + [Optional] + public string? SortText { get; set; } + + /// + /// A string that should be used when filtering a set of + /// completion items. When `falsy` the label is used. + /// + + [Optional] + public string? FilterText { get; set; } + + /// + /// A string that should be inserted a document when selecting + /// this completion. When `falsy` the label is used. + /// + + [Optional] + public string? InsertText { get; set; } + + /// + /// The format of the insert text. The format applies to both the `insertText` property + /// and the `newText` property of a provided `textEdit`. + /// + [Optional] + public InsertTextFormat InsertTextFormat { get; set; } + + /// + /// How whitespace and indentation is handled during completion + /// item insertion. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public InsertTextMode InsertTextMode { get; set; } + + /// + /// An edit which is applied to a document when selecting this completion. When an edit is provided the value of + /// `insertText` is ignored. + /// + /// *Note:* The range of the edit must be a single line range and it must contain the position at which completion + /// has been requested. + /// + /// Most editors support two different operation when accepting a completion + /// item. One is to insert a completion text and the other is to replace an + /// existing text with a competion text. Since this can usually not + /// predetermend by a server it can report both ranges. Clients need to + /// signal support for `InsertReplaceEdits` via the + /// `textDocument.completion.insertReplaceSupport` client capability + /// property. + /// + /// *Note 1:* The text edit's range as well as both ranges from a insert + /// replace edit must be a [single line] and they must contain the position + /// at which completion has been requested. + /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range + /// must be a prefix of the edit's replace range, that means it must be + /// contained and starting at the same position. + /// + /// @since 3.16.0 additional type `InsertReplaceEdit` - proposed state + /// + /// + /// TODO: Update this to union + /// + [Optional] + public TextEdit? TextEdit { get; set; } + + /// + /// An optional array of additional text edits that are applied when + /// selecting this completion. Edits must not overlap with the main edit + /// nor with themselves. + /// + [Optional] + public TextEditContainer? AdditionalTextEdits { get; set; } + + /// + /// An optional set of characters that when pressed while this completion is active will accept it first and + /// then type that character. *Note* that all commit characters should have `length=1` and that superfluous + /// characters will be ignored. + /// + [Optional] + public Container? CommitCharacters { get; set; } + + /// + /// An optional command that is executed/// after* inserting this completion./// Note* that + /// additional modifications to the current document should be described with the + /// additionalTextEdits-property. + /// + [Optional] + public Command? Command { get; set; } + + /// + /// An data entry field that is preserved on a completion item between + /// a completion and a completion resolve request. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"[{Kind}] {Label}{( Tags?.Any() == true ? $" tags: {string.Join(", ", Tags.Select(z => z.ToString()))}" : "" )}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.CompletionProvider))] + [RegistrationOptionsConverter(typeof(CompletionRegistrationOptionsConverter))] + public partial class CompletionRegistrationOptions : IWorkDoneProgressOptions, ITextDocumentRegistrationOptions + { + /// + /// The server provides support to resolve additional + /// information for a completion item. + /// + [Optional] + public bool ResolveProvider { get; set; } + + /// + /// Most tools trigger completion request automatically without explicitly requesting + /// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + /// starts to type an identifier. For example if the user types `c` in a JavaScript file + /// code complete will automatically pop up present `console` besides others as a + /// completion item. Characters that make up identifiers don't need to be listed here. + /// + /// If code complete should automatically be trigger on characters not being valid inside + /// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + /// + [Optional] + public Container? TriggerCharacters { get; set; } + + /// + /// The list of all possible characters that commit a completion. This field can be used + /// if clients don't support individual commmit characters per completion item. See + /// `Capability.textDocument.completion.completionItem.commitCharactersSupport` + /// + /// @since 3.2.0 + /// + [Optional] + public Container? AllCommitCharacters { get; set; } + + class CompletionRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public CompletionRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CompletionProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(CompletionRegistrationOptions source) + { + return new() { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICompletionResolveHandler)), + AllCommitCharacters = source.AllCommitCharacters, + TriggerCharacters = source.TriggerCharacters, + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } + } + + /// + /// Represents a collection of [completion items](#CompletionItem) to be presented + /// in the editor. + /// + [JsonConverter(typeof(CompletionListConverter))] + public partial class CompletionList + { + public CompletionList(bool isIncomplete) : this(Enumerable.Empty(), isIncomplete) + { + IsIncomplete = isIncomplete; + } + + public CompletionList(IEnumerable items, bool isIncomplete) : base(items) + { + IsIncomplete = isIncomplete; + } + + /// + /// This list it not complete. Further typing should result in recomputing + /// this list. + /// + public bool IsIncomplete { get; } + + /// + /// The completion items. + /// + public IEnumerable Items => this; + + public static CompletionList? From(CompletionList? list) where T : HandlerIdentity?, new() + => list switch { + not null => new(list.Items.Select(CompletionItem.From)!, list.IsIncomplete), + _ => null + }; + } + + public partial class CompletionList + { + public CompletionList(bool isIncomplete) : this(isIncomplete, Enumerable.Empty>()) + { + IsIncomplete = isIncomplete; + } + + public CompletionList(bool isIncomplete, IEnumerable> items) : base(items) + { + IsIncomplete = isIncomplete; + } + + public CompletionList(bool isIncomplete, params CompletionItem[] items) : base(items) + { + IsIncomplete = isIncomplete; + } + + /// + /// This list it not complete. Further typing should result in recomputing + /// this list. + /// + public bool IsIncomplete { get; } + + /// + /// The completion items. + /// + public IEnumerable> Items => this; + + public static CompletionList? Create(CompletionList? list) + => list switch { + not null => + new(list.IsIncomplete, list.Items.Select(CompletionItem.From)!), + _ => null + }; + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Completion))] + public partial class CompletionCapability : DynamicCapability, ConnectedCapability + { + /// + /// The client supports the following `CompletionItem` specific + /// capabilities. + /// + [Optional] + public CompletionItemCapabilityOptions? CompletionItem { get; set; } + + /// + /// Specific capabilities for the `CompletionItemKind` in the `textDocument/completion` request. + /// + [Optional] + public CompletionItemKindCapabilityOptions? CompletionItemKind { get; set; } + + /// + /// The client supports to send additional context information for a `textDocument/completion` request. + /// + [Optional] + public bool ContextSupport { get; set; } + } + + public class CompletionContext + { + /// + /// How the completion was triggered. + /// + public CompletionTriggerKind TriggerKind { get; set; } + + /// + /// Most tools trigger completion request automatically without explicitly requesting + /// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + /// starts to type an identifier. For example if the user types `c` in a JavaScript file + /// code complete will automatically pop up present `console` besides others as a + /// completion item. Characters that make up identifiers don't need to be listed here. + /// + /// If code complete should automatically be trigger on characters not being valid inside + /// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + /// + [Optional] + public string? TriggerCharacter { get; set; } + } + + public class CompletionItemCapabilityOptions + { + /// + /// Client supports snippets as insert text. + /// + /// A snippet can define tab stops and placeholders with `$1`, `$2` + /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to + /// the end of the snippet. Placeholders with equal identifiers are linked, + /// that is typing in one will update others too. + /// + [Optional] + public bool SnippetSupport { get; set; } + + /// + /// Client supports commit characters on a completion item. + /// + [Optional] + public bool CommitCharactersSupport { get; set; } + + /// + /// Client supports the follow content formats for the documentation + /// property. The order describes the preferred format of the client. + /// + [Optional] + public Container? DocumentationFormat { get; set; } + + /// + /// Client supports the deprecated property on a completion item. + /// + [Optional] + public bool DeprecatedSupport { get; set; } + + /// + /// Client supports the preselect property on a completion item. + /// + [Optional] + public bool PreselectSupport { get; set; } + + /// + /// Client supports the tag property on a completion item. Clients supporting + /// tags have to handle unknown tags gracefully. Clients especially need to + /// preserve unknown tags when sending a completion item back to the server in + /// a resolve call. + /// + /// @since 3.15.0 + /// + [Optional] + public Supports TagSupport { get; set; } + + /// + /// Client support insert replace edit to control different behavior if a + /// completion item is inserted in the text or should replace text. + /// + /// @since 3.16.0 - Proposed state + /// + [Optional] + public bool InsertReplaceSupport { get; set; } + + /// + /// Client supports to resolve `additionalTextEdits` in the `completionItem/resolve` + /// request. So servers can postpone computing them. + /// + /// @since 3.16.0 - Proposed state + /// + [Optional] + public bool ResolveAdditionalTextEditsSupport { get; set; } + + /// + /// Indicates which properties a client can resolve lazily on a completion + /// item. Before version 3.16.0 only the predefined properties `documentation` + /// and `details` could be resolved lazily. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public CompletionItemCapabilityResolveSupportOptions? ResolveSupport { get; set; } + + /// + /// The client supports the `insertTextMode` property on + /// a completion item to override the whitespace handling mode + /// as defined by the client (see `insertTextMode`). + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public CompletionItemInsertTextModeSupportCapabilityOptions? InsertTextModeSupport { get; set; } + } + + public class CompletionItemInsertTextModeSupportCapabilityOptions + { + public Container ValueSet { get; set; } = null!; + } + + /// + /// Indicates which properties a client can resolve lazily on a completion + /// item. Before version 3.16.0 only the predefined properties `documentation` + /// and `details` could be resolved lazily. + /// + /// @since 3.16.0 - proposed state + /// + public class CompletionItemCapabilityResolveSupportOptions + { + /// + /// The properties that a client can resolve lazily. + /// + public Container Properties { get; set; } = new Container(); + } + + public class CompletionItemKindCapabilityOptions + { + /// + /// The completion item kind values the client supports. When this + /// property exists the client also guarantees that it will + /// handle values outside its set gracefully and falls back + /// to a default value when unknown. + /// + /// If this property is not present the client only supports + /// the completion items kinds from `Text` to `Reference` as defined in + /// the initial version of the protocol. + /// + [Optional] + public Container? ValueSet { get; set; } + } + + /// + /// Completion item tags are extra annotations that tweak the rendering of a completion + /// item. + /// + /// @since 3.15.0 + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum CompletionItemTag + { + /// + /// Render a completion as obsolete, usually using a strike-out. + /// + Deprecated = 1 + } + + /// + /// The kind of a completion entry. + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum CompletionItemKind + { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25, + } + + [JsonConverter(typeof(NumberEnumConverter))] + public enum CompletionTriggerKind + { + /// + /// Completion was triggered by typing an identifier (24x7 code complete), manual invocation (e.g Ctrl+Space) or via API. + /// + Invoked = 1, + + /// + /// Completion was triggered by a trigger character specified by the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + /// + TriggerCharacter = 2, + + /// + /// Completion was re-triggered as the current completion list is incomplete. + /// + TriggerForIncompleteCompletions = 3, + } + + public class CompletionItemTagSupportCapabilityOptions + { + /// + /// The tags supported by the client. + /// + public Container ValueSet { get; set; } = null!; + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DeclarationFeature.cs b/src/Protocol/Features/Document/DeclarationFeature.cs new file mode 100644 index 000000000..be5a6dce5 --- /dev/null +++ b/src/Protocol/Features/Document/DeclarationFeature.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Declaration, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DeclarationRegistrationOptions)), Capability(typeof(DeclarationCapability))] + public partial class DeclarationParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest { } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DeclarationProvider))] + public partial class DeclarationRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Declaration))] + public partial class DeclarationCapability : LinkSupportCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DefinitionFeature.cs b/src/Protocol/Features/Document/DefinitionFeature.cs new file mode 100644 index 000000000..97c0a0466 --- /dev/null +++ b/src/Protocol/Features/Document/DefinitionFeature.cs @@ -0,0 +1,47 @@ +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Definition, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DefinitionRegistrationOptions)), Capability(typeof(DefinitionCapability))] + public partial class DefinitionParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DefinitionProvider))] + public partial class DefinitionRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Definition))] + public partial class DefinitionCapability : LinkSupportCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentFormattingFeature.cs b/src/Protocol/Features/Document/DocumentFormattingFeature.cs new file mode 100644 index 000000000..a2eda6974 --- /dev/null +++ b/src/Protocol/Features/Document/DocumentFormattingFeature.cs @@ -0,0 +1,55 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.DocumentFormatting, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentFormattingRegistrationOptions)), Capability(typeof(DocumentFormattingCapability))] + public partial class DocumentFormattingParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams + { + /// + /// The document to format. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The format options. + /// + public FormattingOptions Options { get; set; } = null!; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentFormattingProvider))] + public partial class DocumentFormattingRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Formatting))] + public partial class DocumentFormattingCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentHighlightFeature.cs b/src/Protocol/Features/Document/DocumentHighlightFeature.cs new file mode 100644 index 000000000..98ab28b67 --- /dev/null +++ b/src/Protocol/Features/Document/DocumentHighlightFeature.cs @@ -0,0 +1,91 @@ +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.DocumentHighlight, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentHighlightRegistrationOptions)), Capability(typeof(DocumentHighlightCapability))] + public partial class DocumentHighlightParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + } + + /// + /// A document highlight is a range inside a text document which deserves + /// special attention. Usually a document highlight is visualized by changing + /// the background color of its range. + /// + /// + [GenerateContainer] + public partial class DocumentHighlight + { + /// + /// The range this highlight applies to. + /// + public Range Range { get; set; } = null!; + + /// + /// The highlight kind, default is DocumentHighlightKind.Text. + /// + public DocumentHighlightKind Kind { get; set; } + } + + /// + /// A document highlight kind. + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum DocumentHighlightKind + { + /// + /// A textual occurrence. + /// + Text = 1, + + /// + /// Read-access of a symbol, like reading a variable. + /// + Read = 2, + + /// + /// Write-access of a symbol, like writing to a variable. + /// + Write = 3, + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentHighlightProvider))] + public partial class DocumentHighlightRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentHighlight))] + public partial class DocumentHighlightCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentLinkFeature.cs b/src/Protocol/Features/Document/DocumentLinkFeature.cs new file mode 100644 index 000000000..0d4a8fd3b --- /dev/null +++ b/src/Protocol/Features/Document/DocumentLinkFeature.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using DryIoc; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.DocumentLink, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentLinkRegistrationOptions)), Capability(typeof(DocumentLinkCapability)), Resolver(typeof(DocumentLink))] + public partial class DocumentLinkParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams + { + /// + /// The document to provide document links for. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + /// + /// A document link is a range in a text document that links to an internal or external resource, like another + /// text document or a web site. + /// + [Parallel] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Method(TextDocumentNames.DocumentLinkResolve, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "DocumentLinkResolve"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), + GenerateTypedData, + GenerateContainer + ] + [RegistrationOptions(typeof(DocumentLinkRegistrationOptions)), Capability(typeof(DocumentLinkCapability))] + public partial class DocumentLink : ICanBeResolved, IRequest + { + /// + /// The range this link applies to. + /// + public Range Range { get; set; } = null!; + + /// + /// The uri this link points to. If missing a resolve request is sent later. + /// + [Optional] + public DocumentUri? Target { get; set; } + + /// + /// A data entry field that is preserved on a document link between a + /// DocumentLinkRequest and a DocumentLinkResolveRequest. + /// + [Optional] + public JToken? Data { get; set; } + + /// + /// The tooltip text when you hover over this link. + /// + /// If a tooltip is provided, is will be displayed in a string that includes instructions on how to + /// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, + /// user settings, and localization. + /// + /// @since 3.15.0 + /// + [Optional] + public string? Tooltip { get; set; } + + private string DebuggerDisplay => $"{Range}{( Target is not null ? $" {Target}" : "" )}{( string.IsNullOrWhiteSpace(Tooltip) ? $" {Tooltip}" : "" )}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentLinkProvider))] + [RegistrationOptionsConverter(typeof(DocumentLinkRegistrationOptionsConverter))] + public partial class DocumentLinkRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// Document links have a resolve provider as well. + /// + [Optional] + public bool ResolveProvider { get; set; } + + class DocumentLinkRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public DocumentLinkRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.DocumentLinkProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(DocumentLinkRegistrationOptions source) => new() { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IDocumentLinkResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentLink))] + public partial class DocumentLinkCapability : DynamicCapability, ConnectedCapability + { + /// + /// Whether the client support the `tooltip` property on `DocumentLink`. + /// + /// @since 3.15.0 + /// + [Optional] + public bool TooltipSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs b/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs new file mode 100644 index 000000000..4743460b5 --- /dev/null +++ b/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs @@ -0,0 +1,79 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.OnTypeFormatting, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(OnTypeRenameRegistrationOptions)), Capability(typeof(DocumentOnTypeFormattingCapability))] + public partial class DocumentOnTypeFormattingParams : ITextDocumentIdentifierParams, IRequest + { + /// + /// The document to format. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The position at which this request was sent. + /// + public Position Position { get; set; } = null!; + + /// + /// The character that has been typed. + /// + [JsonProperty("ch")] + public string Character { get; set; } = null!; + + /// + /// The format options. + /// + public FormattingOptions Options { get; set; } = null!; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentOnTypeFormattingProvider))] + public partial class DocumentOnTypeFormattingRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// A character on which formatting should be triggered, like `}`. + /// + public string FirstTriggerCharacter { get; set; } = null!; + + /// + /// More trigger characters. + /// + [Optional] + public Container? MoreTriggerCharacter { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OnTypeFormatting))] + public partial class DocumentOnTypeFormattingCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentRangeFormattingFeature.cs b/src/Protocol/Features/Document/DocumentRangeFormattingFeature.cs new file mode 100644 index 000000000..b44791c49 --- /dev/null +++ b/src/Protocol/Features/Document/DocumentRangeFormattingFeature.cs @@ -0,0 +1,62 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.RangeFormatting, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentRangeFormattingRegistrationOptions)), Capability(typeof(DocumentRangeFormattingCapability))] + public partial class DocumentRangeFormattingParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams + { + /// + /// The document to format. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The range to format + /// + public Range Range { get; set; } = null!; + + /// + /// The format options + /// + public FormattingOptions Options { get; set; } = null!; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentRangeFormattingProvider))] + public partial class DocumentRangeFormattingRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.RangeFormatting))] + public partial class DocumentRangeFormattingCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentSymbolFeature.cs b/src/Protocol/Features/Document/DocumentSymbolFeature.cs new file mode 100644 index 000000000..b38d15ffa --- /dev/null +++ b/src/Protocol/Features/Document/DocumentSymbolFeature.cs @@ -0,0 +1,198 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.DocumentSymbol, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(DocumentSymbolRegistrationOptions)), Capability(typeof(DocumentSymbolCapability))] + public partial class DocumentSymbolParams : ITextDocumentIdentifierParams, + IPartialItemsRequest, + IWorkDoneProgressParams + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + [JsonConverter(typeof(SymbolInformationOrDocumentSymbolConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] + public class SymbolInformationOrDocumentSymbol + { + public SymbolInformationOrDocumentSymbol(DocumentSymbol documentSymbol) + { + DocumentSymbol = documentSymbol; + SymbolInformation = default; + } + + public SymbolInformationOrDocumentSymbol(SymbolInformation symbolInformation) + { + DocumentSymbol = default; + SymbolInformation = symbolInformation; + } + + public bool IsDocumentSymbolInformation => SymbolInformation != null; + public SymbolInformation? SymbolInformation { get; } + + public bool IsDocumentSymbol => DocumentSymbol != null; + public DocumentSymbol? DocumentSymbol { get; } + + public static SymbolInformationOrDocumentSymbol Create(SymbolInformation value) => value; + + public static SymbolInformationOrDocumentSymbol Create(DocumentSymbol value) => value; + + public static implicit operator SymbolInformationOrDocumentSymbol(SymbolInformation value) => new SymbolInformationOrDocumentSymbol(value); + + public static implicit operator SymbolInformationOrDocumentSymbol(DocumentSymbol value) => new SymbolInformationOrDocumentSymbol(value); + + private string DebuggerDisplay => IsDocumentSymbol ? DocumentSymbol!.ToString() : IsDocumentSymbolInformation ? SymbolInformation!.ToString() : string.Empty; + + /// + public override string ToString() => DebuggerDisplay; + } + + /// + /// Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be + /// hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range, + /// e.g. the range of an identifier. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class DocumentSymbol + { + /// + /// The name of this symbol. + /// + public string Name { get; set; } = null!; + + /// + /// More detail for this symbol, e.g the signature of a function. If not provided the + /// name is used. + /// + [Optional] + public string? Detail { get; set; } + + /// + /// The kind of this symbol. + /// + public SymbolKind Kind { get; set; } + + /// + /// Tags for this document symbol. + /// + /// @since 3.16.0 - Proposed state + /// + [Obsolete(Constants.Proposal)] + [Optional] + public Container? Tags { get; set; } + + /// + /// Indicates if this symbol is deprecated. + /// + [Optional] + public bool Deprecated { get; set; } + + /// + /// The range enclosing this symbol not including leading/trailing whitespace but everything else + /// like comments. This information is typically used to determine if the the clients cursor is + /// inside the symbol to reveal in the symbol in the UI. + /// + public Range Range { get; set; } = null!; + + /// + /// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. + /// Must be contained by the the `range`. + /// + public Range SelectionRange { get; set; } = null!; + + /// + /// Children of this symbol, e.g. properties of a class. + /// + [Optional] + public Container? Children { get; set; } + + private string DebuggerDisplay => $"[{Kind}] {Name} {{ range: {Range}, selection: {SelectionRange}, detail: {Detail ?? string.Empty} }}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DocumentSymbolProvider))] + public partial class DocumentSymbolRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// A human-readable string that is shown when multiple outlines trees + /// are shown for the same document. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public string? Label { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.DocumentSymbol))] + public partial class DocumentSymbolCapability : DynamicCapability, ConnectedCapability + { + /// + /// Specific capabilities for the `SymbolKind` in the `textDocument/symbol` request. + /// + [Optional] + public SymbolKindCapabilityOptions? SymbolKind { get; set; } + + /// + /// Whether document symbol supports hierarchical `DocumentSymbol`s. + /// + [Optional] + public bool HierarchicalDocumentSymbolSupport { get; set; } + + /// + /// The client supports tags on `SymbolInformation`.Tags are supported on + /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set tot true. + /// Clients supporting tags have to handle unknown tags gracefully. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Optional] + public TagSupportCapabilityOptions? TagSupport { get; set; } + + /// + /// The client supports an additional label presented in the UI when + /// registering a document symbol provider. + /// + /// @since 3.16.0 + /// + [Optional] + public bool LabelSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/FoldingRangeFeature.cs b/src/Protocol/Features/Document/FoldingRangeFeature.cs new file mode 100644 index 000000000..171345dde --- /dev/null +++ b/src/Protocol/Features/Document/FoldingRangeFeature.cs @@ -0,0 +1,151 @@ +using System.Diagnostics; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.FoldingRange, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "FoldingRange"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(FoldingRangeRegistrationOptions)), Capability(typeof(FoldingRangeCapability))] + public partial class FoldingRangeRequestParam : ITextDocumentIdentifierParams, IPartialItemsRequest?, FoldingRange>, IWorkDoneProgressParams + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + /// + /// Represents a folding range. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial class FoldingRange + { + /// + /// The zero-based line number from where the folded range starts. + /// + /// + /// TODO: UPDATE THIS next version + /// in the LSP spec + /// + public long StartLine { get; set; } + + /// + /// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. + /// + /// + /// TODO: UPDATE THIS next version + /// in the LSP spec + /// + [Optional] + public long? StartCharacter { get; set; } + + /// + /// The zero-based line number where the folded range ends. + /// + /// + /// TODO: UPDATE THIS next version + /// in the LSP spec + /// + public long EndLine { get; set; } + + /// + /// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. + /// + /// + /// TODO: UPDATE THIS next version + /// in the LSP spec + /// + [Optional] + public long? EndCharacter { get; set; } + + /// + /// Describes the kind of the folding range such as `comment' or 'region'. The kind + /// is used to categorize folding ranges and used by commands like 'Fold all comments'. See + /// [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. + /// + [Optional] + public FoldingRangeKind? Kind { get; set; } + + private string DebuggerDisplay => + $"[start: (line: {StartLine}{( StartCharacter.HasValue ? $", char: {StartCharacter}" : string.Empty )}), end: (line: {EndLine}, char: {( EndCharacter.HasValue ? $", char: {EndCharacter}" : string.Empty )})]"; + + /// + public override string ToString() => DebuggerDisplay; + } + + /// + /// Enum of known range kinds + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum FoldingRangeKind + { + /// + /// Folding range for a comment + /// + [EnumMember(Value = "comment")] Comment, + + /// + /// Folding range for a imports or includes + /// + [EnumMember(Value = "imports")] Imports, + + /// + /// Folding range for a region (e.g. `#region`) + /// + [EnumMember(Value = "region")] Region + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.FoldingRangeProvider))] + public partial class FoldingRangeRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.FoldingRange))] + public partial class FoldingRangeCapability : DynamicCapability, ConnectedCapability + { + /// + /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a + /// hint, servers are free to follow the limit. + /// + /// + /// in the LSP spec + /// + [Optional] + public int? RangeLimit { get; set; } + + /// + /// If set, the client signals that it only supports folding complete lines. If set, client will + /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. + /// + public bool LineFoldingOnly { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/HoverFeature.cs b/src/Protocol/Features/Document/HoverFeature.cs new file mode 100644 index 000000000..8be552863 --- /dev/null +++ b/src/Protocol/Features/Document/HoverFeature.cs @@ -0,0 +1,76 @@ +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Hover, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(HoverRegistrationOptions)), Capability(typeof(HoverCapability))] + public partial class HoverParams : TextDocumentPositionParams, IWorkDoneProgressParams, IRequest + { + } + + /// + /// The result of a hover request. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial class Hover + { + /// + /// The hover's content + /// + public MarkedStringsOrMarkupContent Contents { get; set; } = null!; + + /// + /// An optional range is a range inside a text document + /// that is used to visualize a hover, e.g. by changing the background color. + /// + [Optional] + public Range? Range { get; set; } + + private string DebuggerDisplay => $"{Contents}{( Range is not null ? $" {Range}" : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.HoverProvider))] + public partial class HoverRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Hover))] + public partial class HoverCapability : DynamicCapability, ConnectedCapability + { + /// + /// Client supports the follow content formats for the content property. The order describes the preferred format of the client. + /// + [Optional] + public Container? ContentFormat { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/ImplementationFeature.cs b/src/Protocol/Features/Document/ImplementationFeature.cs new file mode 100644 index 000000000..739f5cf54 --- /dev/null +++ b/src/Protocol/Features/Document/ImplementationFeature.cs @@ -0,0 +1,42 @@ +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Implementation, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(ImplementationRegistrationOptions)), Capability(typeof(ImplementationCapability))] + public partial class ImplementationParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest { } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.ImplementationProvider))] + public partial class ImplementationRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions { } + + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Implementation))] + public partial class ImplementationCapability : LinkSupportCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/OnTypeRenameFeature.cs b/src/Protocol/Features/Document/OnTypeRenameFeature.cs new file mode 100644 index 000000000..fcd72d3f3 --- /dev/null +++ b/src/Protocol/Features/Document/OnTypeRenameFeature.cs @@ -0,0 +1,67 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Obsolete(Constants.Proposal)] + [Method(TextDocumentNames.OnTypeRename, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(OnTypeRenameRegistrationOptions)), Capability(typeof(OnTypeRenameClientCapabilities))] + public partial class OnTypeRenameParams : TextDocumentPositionParams, IWorkDoneProgressParams, IRequest + { + } + + [Obsolete(Constants.Proposal)] + public partial class OnTypeRenameRanges + { + /// + /// A list of ranges that can be renamed together. The ranges must have + /// identical length and contain identical text content. The ranges cannot overlap. + /// + public Container Ranges { get; set; } = null!; + + /// + /// An optional word pattern (regular expression) that describes valid contents for + /// the given ranges. If no pattern is provided, the client configuration's word + /// pattern will be used. + /// + [Optional] + public string? WordPattern { get; set; } + } + + [Obsolete(Constants.Proposal)] + [GenerateRegistrationOptions(nameof(ServerCapabilities.OnTypeRenameProvider))] + public partial class OnTypeRenameRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + + } + + namespace Client.Capabilities + { + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OnTypeRename))] + public partial class OnTypeRenameClientCapabilities : DynamicCapability, ConnectedCapability { } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/Proposals/CallHierarchyFeature.cs b/src/Protocol/Features/Document/Proposals/CallHierarchyFeature.cs new file mode 100644 index 000000000..6a2a37628 --- /dev/null +++ b/src/Protocol/Features/Document/Proposals/CallHierarchyFeature.cs @@ -0,0 +1,961 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reactive; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models.Proposals + { + /// + /// The parameter of a `textDocument/prepareCallHierarchy` request. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.PrepareCallHierarchy, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CallHierarchyRegistrationOptions)), Capability(typeof(CallHierarchyCapability))] + public partial class CallHierarchyPrepareParams : TextDocumentPositionParams, IWorkDoneProgressParams, + IPartialItemsRequest?, CallHierarchyItem> + { + } + + /// + /// Represents programming constructs like functions or constructors in the context + /// of call hierarchy. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateTypedData] + public partial class CallHierarchyItem : ICanBeResolved + { + /// + /// The name of this item. + /// + public string Name { get; set; } = null!; + + /// + /// The kind of this item. + /// + public SymbolKind Kind { get; set; } + + /// + /// Tags for this item. + /// + [Optional] + public Container? Tags { get; set; } + + /// + /// More detail for this item, e.g. the signature of a function. + /// + [Optional] + public string? Detail { get; set; } + + /// + /// The resource identifier of this item. + /// + public DocumentUri Uri { get; set; } = null!; + + /// + /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. + /// + public Range Range { get; set; } = null!; + + /// + /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. + /// Must be contained by the [`range`](#CallHierarchyItem.range). + /// + public Range SelectionRange { get; set; } = null!; + + /// + /// A data entry field that is preserved between a call hierarchy prepare and + /// incoming calls or outgoing calls requests. + /// + [Optional] + public JToken? Data { get; set; } + + private string DebuggerDisplay => + $"[{Kind.ToString()}] " + + $"{Name} " + + $"@ {Uri} " + + $"{Range}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [Obsolete(Constants.Proposal)] + public abstract class CallHierarchyBaseCallParams : ICanBeResolved + { + public CallHierarchyItem Item { get; set; } = null!; + + JToken? ICanBeResolved.Data + { + get => ( (ICanBeResolved) Item )?.Data; + set { + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (Item != null) ( (ICanBeResolved) Item ).Data = value; + } + } + } + + [Obsolete(Constants.Proposal)] + public abstract class CallHierarchyBaseCallParams : ICanBeResolved + where T : HandlerIdentity?, new() + { + public CallHierarchyItem Item { get; set; } = null!; + + JToken? ICanBeResolved.Data + { + get => ( (ICanBeResolved) Item )?.Data; + set { + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (Item != null) ( (ICanBeResolved) Item ).Data = value; + } + } + } + + /// + /// The parameter of a `callHierarchy/incomingCalls` request. + /// + /// @since 3.16.0 + /// + [Parallel] + [Obsolete(Constants.Proposal)] + [Method(TextDocumentNames.CallHierarchyIncoming, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals", Name = "CallHierarchyIncoming"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CallHierarchyRegistrationOptions)), Capability(typeof(CallHierarchyCapability))] + public partial class CallHierarchyIncomingCallsParams : CallHierarchyBaseCallParams, IWorkDoneProgressParams, + IPartialItemsRequest?, CallHierarchyIncomingCall> + { + } + + /// + /// The parameter of a `callHierarchy/incomingCalls` request. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Method(TextDocumentNames.CallHierarchyIncoming, Direction.ClientToServer)] + public partial class CallHierarchyIncomingCallsParams : CallHierarchyBaseCallParams, IWorkDoneProgressParams, + IPartialItemsRequest?, CallHierarchyIncomingCall> + where T : HandlerIdentity?, new() + { + } + + /// + /// Represents an incoming call, e.g. a caller of a method or constructor. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public partial class CallHierarchyIncomingCall + { + /// + /// The item that makes the call. + /// + public CallHierarchyItem From { get; set; } = null!; + + /// + /// The range at which at which the calls appears. This is relative to the caller + /// denoted by [`this.from`](#CallHierarchyIncomingCall.from). + /// + public Container FromRanges { get; set; } = null!; + } + + /// + /// The parameter of a `callHierarchy/outgoingCalls` request. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.CallHierarchyOutgoing, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals", Name = "CallHierarchyOutgoing"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(CallHierarchyRegistrationOptions)), Capability(typeof(CallHierarchyCapability))] + public partial class CallHierarchyOutgoingCallsParams : CallHierarchyBaseCallParams, IWorkDoneProgressParams, + IPartialItemsRequest?, CallHierarchyOutgoingCall> + + { + public static CallHierarchyOutgoingCallsParams Create(CallHierarchyOutgoingCallsParams item) + where T : HandlerIdentity?, new() + { + return new CallHierarchyOutgoingCallsParams() { + Item = item.Item, + PartialResultToken = item.PartialResultToken, + WorkDoneToken = item.PartialResultToken + }; + } + } + + /// + /// The parameter of a `callHierarchy/outgoingCalls` request. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Method(TextDocumentNames.CallHierarchyOutgoing, Direction.ClientToServer)] + public partial class CallHierarchyOutgoingCallsParams : CallHierarchyBaseCallParams, IWorkDoneProgressParams, + IPartialItemsRequest?, CallHierarchyOutgoingCall> + where T : HandlerIdentity?, new() + { + public static CallHierarchyOutgoingCallsParams Create(CallHierarchyOutgoingCallsParams item) + { + return new CallHierarchyOutgoingCallsParams() { + Item = item.Item, + PartialResultToken = item.PartialResultToken, + WorkDoneToken = item.PartialResultToken + }; + } + + public static implicit operator CallHierarchyOutgoingCallsParams(CallHierarchyOutgoingCallsParams item) => Create(item); + public static implicit operator CallHierarchyOutgoingCallsParams(CallHierarchyOutgoingCallsParams item) => CallHierarchyOutgoingCallsParams.Create(item); + } + + /// + /// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public partial class CallHierarchyOutgoingCall + { + /// + /// The item that is called. + /// + public CallHierarchyItem To { get; set; } = null!; + + /// + /// The range at which this item is called. This is the range relative to the caller, e.g the item + /// passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls) + /// and not [`this.to`](#CallHierarchyOutgoingCall.to). + /// + public Container FromRanges { get; set; } = null!; + } + + /// + /// Call hierarchy options used during static or dynamic registration. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [GenerateRegistrationOptions(nameof(ServerCapabilities.CallHierarchyProvider))] + public partial class CallHierarchyRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to the `textDocument/callHierarchy`. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CallHierarchy))] + public partial class CallHierarchyCapability : DynamicCapability, ConnectedCapability, + ConnectedCapability, ConnectedCapability + { + } + } + + namespace Document.Proposals + { + [Obsolete(Constants.Proposal)] + public abstract class CallHierarchyHandlerBase : AbstractHandlers.Base, ICallHierarchyPrepareHandler, + ICallHierarchyIncomingHandler, + ICallHierarchyOutgoingHandler + { + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + protected CallHierarchyHandlerBase(Guid id) + { + _id = id; + } + + protected CallHierarchyHandlerBase() : this(Guid.NewGuid()) + { + } + + public abstract Task?> Handle(CallHierarchyPrepareParams request, CancellationToken cancellationToken); + public abstract Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken); + public abstract Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken); + } + + [Obsolete(Constants.Proposal)] + public abstract class PartialCallHierarchyHandlerBase : AbstractHandlers.PartialResults?, CallHierarchyItem, + CallHierarchyRegistrationOptions, CallHierarchyCapability>, + ICallHierarchyPrepareHandler, ICallHierarchyIncomingHandler, ICallHierarchyOutgoingHandler + { + private readonly ICallHierarchyIncomingHandler _incoming; + private readonly ICallHierarchyOutgoingHandler _outgoing; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + protected PartialCallHierarchyHandlerBase(Guid id, IProgressManager progressManager) : base(progressManager, Container.From) + { + _id = id; + _incoming = new PartialIncoming(id, progressManager, this); + _outgoing = new PartialOutgoing(id, progressManager, this); + } + + protected PartialCallHierarchyHandlerBase(IProgressManager progressManager) : this(Guid.NewGuid(), progressManager) + { + } + + public Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken) => + _incoming.Handle(request, cancellationToken); + + public Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken) => + _outgoing.Handle(request, cancellationToken); + + protected abstract void Handle( + CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken + ); + + protected abstract void Handle( + CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken + ); + + private class PartialIncoming : AbstractHandlers.PartialResults< + CallHierarchyIncomingCallsParams, + Container?, + CallHierarchyIncomingCall, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >, ICallHierarchyIncomingHandler + { + private readonly PartialCallHierarchyHandlerBase _self; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialIncoming(Guid id, IProgressManager progressManager, PartialCallHierarchyHandlerBase self) : + base(progressManager, Container.From) + { + _id = id; + _self = self; + } + + protected override void Handle( + CallHierarchyIncomingCallsParams request, + IObserver> results, + CancellationToken cancellationToken + ) => _self.Handle(request, results, cancellationToken); + + protected internal override CallHierarchyRegistrationOptions CreateRegistrationOptions(CallHierarchyCapability capability, ClientCapabilities clientCapabilities) => + ( (IRegistration) _self ).GetRegistrationOptions(capability, clientCapabilities); + } + + class PartialOutgoing : + AbstractHandlers.PartialResults?, CallHierarchyOutgoingCall, CallHierarchyRegistrationOptions + , CallHierarchyCapability>, ICallHierarchyOutgoingHandler + { + private readonly PartialCallHierarchyHandlerBase _self; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialOutgoing(Guid id, IProgressManager progressManager, PartialCallHierarchyHandlerBase self) : + base(progressManager, Container.From) + + { + _id = id; + _self = self; + } + + protected override void Handle( + CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken + ) => _self.Handle(request, results, cancellationToken); + + protected internal override CallHierarchyRegistrationOptions CreateRegistrationOptions(CallHierarchyCapability capability, ClientCapabilities clientCapabilities) => + ( (IRegistration) _self ).GetRegistrationOptions(capability, clientCapabilities); + } + } + + [Obsolete(Constants.Proposal)] + public abstract class CallHierarchyHandlerBase : CallHierarchyHandlerBase where T : HandlerIdentity?, new() + { + protected CallHierarchyHandlerBase(Guid id) : base(id) + { + } + + protected CallHierarchyHandlerBase() : this(Guid.NewGuid()) + { + } + + public sealed override async Task?> Handle(CallHierarchyPrepareParams request, CancellationToken cancellationToken) + { + var response = await HandlePrepare(request, cancellationToken); + return Container.From(response?.Select(CallHierarchyItem.From)!); + } + + public sealed override Task?> Handle(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken) + { + return HandleIncomingCalls( + new CallHierarchyIncomingCallsParams() { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + cancellationToken + ); + } + + public sealed override Task?> Handle(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken) + { + return HandleOutgoingCalls( + new CallHierarchyOutgoingCallsParams() { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + cancellationToken + ); + } + + protected abstract Task>?> HandlePrepare(CallHierarchyPrepareParams request, CancellationToken cancellationToken); + protected abstract Task?> HandleIncomingCalls(CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken); + protected abstract Task?> HandleOutgoingCalls(CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken); + } + + [Obsolete(Constants.Proposal)] + public abstract class PartialCallHierarchyHandlerBase : PartialCallHierarchyHandlerBase where T : HandlerIdentity?, new() + { + protected PartialCallHierarchyHandlerBase(IProgressManager progressManager) : base(progressManager) + { + } + + protected sealed override void Handle(CallHierarchyPrepareParams request, IObserver> results, CancellationToken cancellationToken) => + Handle( + request, + Observer.Create>>( + x => results.OnNext(x.Select(z => (CallHierarchyItem) z)), + results.OnError, + results.OnCompleted + ), cancellationToken + ); + + protected abstract void Handle(CallHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken); + + protected sealed override void Handle( + CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken + ) => Handle( + new CallHierarchyIncomingCallsParams() { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + results, + cancellationToken + ); + + protected abstract void Handle( + CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken + ); + + protected sealed override void Handle( + CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken + ) => Handle( + new CallHierarchyOutgoingCallsParams { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + results, + cancellationToken + ); + + protected abstract void Handle( + CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken + ); + } + + [Obsolete(Constants.Proposal)] + public static partial class CallHierarchyExtensions + { + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func?>> handler, + Func?>> incomingHandler, + Func?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry + .AddHandler( + TextDocumentNames.PrepareCallHierarchy, + new LanguageProtocolDelegatingHandlers.Request< + CallHierarchyPrepareParams, + Container?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyIncoming, + new LanguageProtocolDelegatingHandlers.Request< + CallHierarchyIncomingCallsParams, + Container?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(incomingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyOutgoing, + new LanguageProtocolDelegatingHandlers.Request< + CallHierarchyOutgoingCallsParams, + Container?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + ; + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, CallHierarchyCapability, CancellationToken, Task?>> incomingHandler, + Func, CallHierarchyCapability, CancellationToken, Task?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + new DelegatingCallHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(incomingHandler), + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func?>> handler, + Func?>> incomingHandler, + Func?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry + .AddHandler( + TextDocumentNames.PrepareCallHierarchy, + new LanguageProtocolDelegatingHandlers.Request< + CallHierarchyPrepareParams, + Container?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyIncoming, + new LanguageProtocolDelegatingHandlers.Request< + CallHierarchyIncomingCallsParams, + Container?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(incomingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyOutgoing, + new LanguageProtocolDelegatingHandlers.Request?, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + ; + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, CallHierarchyCapability, Task?>> incomingHandler, + Func, CallHierarchyCapability, Task?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + new DelegatingCallHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(incomingHandler), + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, CancellationToken, Task?>> incomingHandler, + Func, CancellationToken, Task?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + new DelegatingCallHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(incomingHandler), + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, Task?>> incomingHandler, + Func, Task?>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + new DelegatingCallHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(incomingHandler), + HandlerAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>, CallHierarchyCapability, CancellationToken> handler, + Action>, CallHierarchyCapability, CancellationToken> incomingHandler, + Action>, CallHierarchyCapability, CancellationToken> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry.AddHandler( + TextDocumentNames.PrepareCallHierarchy, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyPrepareParams, + Container?, CallHierarchyItem, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyIncoming, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyIncomingCallsParams, + Container?, CallHierarchyIncomingCall, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(incomingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyOutgoing, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyOutgoingCallsParams, + Container?, CallHierarchyOutgoingCall, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + ; + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>>, CallHierarchyCapability, CancellationToken> handler, + Action, IObserver>, CallHierarchyCapability, CancellationToken> incomingHandler, + Action, IObserver>, CallHierarchyCapability, CancellationToken> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + _ => + new DelegatingPartialCallHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(incomingHandler), + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>, CallHierarchyCapability> handler, + Action>, CallHierarchyCapability> incomingHandler, + Action>, CallHierarchyCapability> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return + registry.AddHandler( + TextDocumentNames.PrepareCallHierarchy, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyPrepareParams, + Container?, CallHierarchyItem, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyIncoming, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyIncomingCallsParams, + Container?, CallHierarchyIncomingCall, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(incomingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.CallHierarchyOutgoing, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + CallHierarchyOutgoingCallsParams, + Container?, CallHierarchyOutgoingCall, + CallHierarchyRegistrationOptions, + CallHierarchyCapability + >( + id, + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + ; + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>>, CallHierarchyCapability> handler, + Action, IObserver>, CallHierarchyCapability> incomingHandler, + Action, IObserver>, CallHierarchyCapability> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + _ => new DelegatingPartialCallHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(incomingHandler), + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>>, CancellationToken> handler, + Action, IObserver>, CancellationToken> incomingHandler, + Action, IObserver>, CancellationToken> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + _ => new DelegatingPartialCallHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(incomingHandler), + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnCallHierarchy( + this ILanguageServerRegistry registry, + Action>>> handler, + Action, IObserver>> incomingHandler, + Action, IObserver>> outgoingHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : HandlerIdentity?, new() + { + return registry.AddHandler( + _ => new DelegatingPartialCallHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(incomingHandler), + PartialAdapter.Adapt(outgoingHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + private class DelegatingCallHierarchyHandler : CallHierarchyHandlerBase where T : HandlerIdentity?, new() + { + private readonly Func>?>> _handlePrepare; + + private readonly Func, CallHierarchyCapability, CancellationToken, Task?>> + _handleIncomingCalls; + + private readonly Func, CallHierarchyCapability, CancellationToken, Task?>> + _handleOutgoingCalls; + + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + + public DelegatingCallHierarchyHandler( + Func>?>> handlePrepare, + Func, CallHierarchyCapability, CancellationToken, Task?>> handleIncomingCalls, + Func, CallHierarchyCapability, CancellationToken, Task?>> handleOutgoingCalls, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _handlePrepare = handlePrepare; + _handleIncomingCalls = handleIncomingCalls; + _handleOutgoingCalls = handleOutgoingCalls; + _registrationOptionsFactory = registrationOptionsFactory; + } + + protected override Task>?> HandlePrepare(CallHierarchyPrepareParams request, CancellationToken cancellationToken) => + _handlePrepare(request, Capability, cancellationToken); + + protected override Task?> HandleIncomingCalls( + CallHierarchyIncomingCallsParams request, CancellationToken cancellationToken + ) => + _handleIncomingCalls(request, Capability, cancellationToken); + + protected override Task?> HandleOutgoingCalls( + CallHierarchyOutgoingCallsParams request, CancellationToken cancellationToken + ) => + _handleOutgoingCalls(request, Capability, cancellationToken); + + protected internal override CallHierarchyRegistrationOptions CreateRegistrationOptions(CallHierarchyCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + } + + private class DelegatingPartialCallHierarchyHandler : PartialCallHierarchyHandlerBase where T : HandlerIdentity?, new() + { + private readonly Action>>, CallHierarchyCapability, CancellationToken> _handleParams; + + private readonly Action, IObserver>, CallHierarchyCapability, CancellationToken> + _handleIncoming; + + private readonly Action, IObserver>, CallHierarchyCapability, CancellationToken> + _handleOutgoing; + + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + + public DelegatingPartialCallHierarchyHandler( + IProgressManager progressManager, + Action>>, CallHierarchyCapability, CancellationToken> handleParams, + Action, IObserver>, CallHierarchyCapability, CancellationToken> handleIncoming, + Action, IObserver>, CallHierarchyCapability, CancellationToken> handleOutgoing, + RegistrationOptionsDelegate registrationOptionsFactory + ) : base(progressManager) + { + _handleParams = handleParams; + _handleIncoming = handleIncoming; + _handleOutgoing = handleOutgoing; + _registrationOptionsFactory = registrationOptionsFactory; + } + + protected override void Handle(CallHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken) => + _handleParams(request, results, Capability, cancellationToken); + + protected override void Handle( + CallHierarchyIncomingCallsParams request, IObserver> results, CancellationToken cancellationToken + ) => _handleIncoming(request, results, Capability, cancellationToken); + + protected override void Handle( + CallHierarchyOutgoingCallsParams request, IObserver> results, CancellationToken cancellationToken + ) => _handleOutgoing(request, results, Capability, cancellationToken); + + protected internal override CallHierarchyRegistrationOptions CreateRegistrationOptions(CallHierarchyCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + } + } + } +} diff --git a/src/Protocol/Features/Document/Proposals/MonikerFeature.cs b/src/Protocol/Features/Document/Proposals/MonikerFeature.cs new file mode 100644 index 000000000..f16eac541 --- /dev/null +++ b/src/Protocol/Features/Document/Proposals/MonikerFeature.cs @@ -0,0 +1,189 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models.Proposals + { + /// + /// Language Server Index Format (LSIF) introduced the concept of symbol monikers to help associate symbols across different indexes. + /// This request adds capability for LSP server implementations to provide the same symbol moniker information given a text document + /// position. Clients can utilize this method to get the moniker at the current location in a file user is editing and do further + /// code navigation queries in other services that rely on LSIF indexes and link symbols together. + /// + /// The `textDocument/moniker` request is sent from the client to the server to get the symbol monikers for a given text document + /// position. An array of Moniker types is returned as response to indicate possible monikers at the given location. If no monikers + /// can be calculated, an empty array or `null` should be returned. + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.Moniker, Direction.ClientToServer)][ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(MonikerRegistrationOptions)), Capability(typeof(MonikerCapability))] + public partial class MonikerParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest?, Moniker> { } + + /// + /// Moniker definition to match LSIF 0.5 moniker definition. + /// + [Obsolete(Constants.Proposal)] + public partial class Moniker + { + /// + /// The scheme of the moniker. For example tsc or .Net + /// + public string Scheme { get; set; } = null!; + + /// + /// The identifier of the moniker. The value is opaque in LSIF however + /// schema owners are allowed to define the structure if they want. + /// + public string Identifier { get; set; } = null!; + + /// + /// The scope in which the moniker is unique + /// + public UniquenessLevel Unique { get; set; } + + /// + /// The moniker kind if known. + /// + [Optional] + public MonikerKind Kind { get; set; } + } + + /// + /// Moniker uniqueness level to define scope of the moniker. + /// + [DebuggerDisplay("{" + nameof(_value) + "}")] + [JsonConverter(typeof(EnumLikeStringConverter))] + public readonly struct MonikerKind : IEquatable, IEnumLikeString + { + /// + /// The moniker represent a symbol that is imported into a project + /// + public static readonly MonikerKind Import = new MonikerKind("import"); + + /// + /// The moniker represents a symbol that is exported from a project + /// + public static readonly MonikerKind Export = new MonikerKind("export"); + + /// + /// The moniker represents a symbol that is local to a project (e.g. a local + /// variable of a function, a class not visible outside the project, ...) + /// + public static readonly MonikerKind Local = new MonikerKind("local"); + + private readonly string? _value; + + public MonikerKind(string kind) => _value = kind; + + public static implicit operator MonikerKind(string kind) => new MonikerKind(kind); + + public static implicit operator string(MonikerKind kind) => kind._value ?? string.Empty; + + /// + public override string ToString() => _value ?? string.Empty; + + public bool Equals(MonikerKind other) => _value == other._value; + + public override bool Equals(object obj) => obj is MonikerKind other && Equals(other); + + public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; + + public static bool operator ==(MonikerKind left, MonikerKind right) => left.Equals(right); + + public static bool operator !=(MonikerKind left, MonikerKind right) => !left.Equals(right); + } + + + /// + /// A set of predefined code action kinds + /// + [DebuggerDisplay("{" + nameof(_value) + "}")] + [JsonConverter(typeof(EnumLikeStringConverter))] + public readonly struct UniquenessLevel : IEquatable, IEnumLikeString + { + /// + /// The moniker is only unique inside a document + /// + public static readonly UniquenessLevel Document = new UniquenessLevel("document"); + + /// + /// The moniker is unique inside a project for which a dump got created + /// + public static readonly UniquenessLevel Project = new UniquenessLevel("project"); + + /// + /// The moniker is unique inside the group to which a project belongs + /// + public static readonly UniquenessLevel Group = new UniquenessLevel("group"); + + /// + /// The moniker is unique inside the moniker scheme. + /// + public static readonly UniquenessLevel Scheme = new UniquenessLevel("scheme"); + + /// + /// The moniker is globally unique + /// + public static readonly UniquenessLevel Global = new UniquenessLevel("global"); + + private readonly string? _value; + + public UniquenessLevel(string kind) => _value = kind; + + public static implicit operator UniquenessLevel(string kind) => new UniquenessLevel(kind); + + public static implicit operator string(UniquenessLevel kind) => kind._value ?? string.Empty; + + /// + public override string ToString() => _value ?? string.Empty; + + public bool Equals(UniquenessLevel other) => _value == other._value; + + public override bool Equals(object obj) => obj is UniquenessLevel other && Equals(other); + + public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; + + public static bool operator ==(UniquenessLevel left, UniquenessLevel right) => left.Equals(right); + + public static bool operator !=(UniquenessLevel left, UniquenessLevel right) => !left.Equals(right); + } + + [Obsolete(Constants.Proposal)] + [GenerateRegistrationOptions(nameof(ServerCapabilities.MonikerProvider))] + public partial class MonikerRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + + } + + namespace Client.Capabilities + { + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Moniker))] + public partial class MonikerCapability : DynamicCapability { } + } + + namespace Document.Proposals + { + + } +} diff --git a/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs b/src/Protocol/Features/Document/Proposals/SemanticTokensBuilder.cs similarity index 99% rename from src/Protocol/Document/Proposals/SemanticTokensBuilder.cs rename to src/Protocol/Features/Document/Proposals/SemanticTokensBuilder.cs index d99270dc8..259853367 100644 --- a/src/Protocol/Document/Proposals/SemanticTokensBuilder.cs +++ b/src/Protocol/Features/Document/Proposals/SemanticTokensBuilder.cs @@ -4,6 +4,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; +// ReSharper disable once CheckNamespace namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals { [Obsolete(Constants.Proposal)] diff --git a/src/Protocol/Document/Proposals/SemanticTokensDocument.cs b/src/Protocol/Features/Document/Proposals/SemanticTokensDocument.cs similarity index 99% rename from src/Protocol/Document/Proposals/SemanticTokensDocument.cs rename to src/Protocol/Features/Document/Proposals/SemanticTokensDocument.cs index b1044be90..f143c5e64 100644 --- a/src/Protocol/Document/Proposals/SemanticTokensDocument.cs +++ b/src/Protocol/Features/Document/Proposals/SemanticTokensDocument.cs @@ -3,6 +3,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; +// ReSharper disable once CheckNamespace namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals { [Obsolete(Constants.Proposal)] diff --git a/src/Protocol/Features/Document/Proposals/SemanticTokensFeature.cs b/src/Protocol/Features/Document/Proposals/SemanticTokensFeature.cs new file mode 100644 index 000000000..9c8c693ec --- /dev/null +++ b/src/Protocol/Features/Document/Proposals/SemanticTokensFeature.cs @@ -0,0 +1,1020 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models.Proposals + { + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.SemanticTokensFull, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals", Name = "SemanticTokensFull"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(SemanticTokensRegistrationOptions)), Capability(typeof(SemanticTokensCapability))] + public partial class SemanticTokensParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, + IPartialItemRequest + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(SemanticTokensRegistrationOptions)), Capability(typeof(SemanticTokensCapability))] + public partial class SemanticTokensDeltaParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, + IPartialItemRequest + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The previous result id. + /// + public string PreviousResultId { get; set; } = null!; + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(TextDocumentNames.SemanticTokensRange, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(SemanticTokensRegistrationOptions)), Capability(typeof(SemanticTokensCapability))] + public partial class SemanticTokensRangeParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, + IPartialItemRequest + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The range the semantic tokens are requested for. + /// + public Range Range { get; set; } = null!; + } + + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(WorkspaceNames.SemanticTokensRefresh, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(SemanticTokensWorkspaceCapability))] + public partial class SemanticTokensRefreshParams : IRequest + { + } + + [Obsolete(Constants.Proposal)] + public interface ISemanticTokenResult + { + /// + /// An optional result id. If provided and clients support delta updating + /// the client will include the result id in the next semantic token request. + /// A server can then instead of computing all semantic tokens again simply + /// send a delta. + /// + [Optional] + public string? ResultId { get; set; } + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public partial class SemanticTokens : ISemanticTokenResult + { + public SemanticTokens() + { + } + + public SemanticTokens(SemanticTokensPartialResult partialResult) + { + Data = partialResult.Data; + } + + /// + /// An optional result id. If provided and clients support delta updating + /// the client will include the result id in the next semantic token request. + /// A server can then instead of computing all semantic tokens again simply + /// send a delta. + /// + [Optional] + public string? ResultId { get; set; } + + /// + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + /// + /// + /// in the LSP spec + /// + public ImmutableArray Data { get; set; } + + [return: NotNullIfNotNull("result")] + public static SemanticTokens? From(SemanticTokensPartialResult? result) => result switch { + not null => new SemanticTokens(result), + _ => null + }; + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public partial class SemanticTokensPartialResult + { + /// + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + /// + public ImmutableArray Data { get; set; } + } + + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public class SemanticTokensDelta : ISemanticTokenResult + { + public SemanticTokensDelta() + { + } + + public SemanticTokensDelta(SemanticTokensDeltaPartialResult partialResult) + { + Edits = partialResult.Edits; + } + + /// + /// An optional result id. If provided and clients support delta updating + /// the client will include the result id in the next semantic token request. + /// A server can then instead of computing all semantic tokens again simply + /// send a delta. + /// + [Optional] + public string? ResultId { get; set; } + + /// + /// For a detailed description how these edits are structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131 + /// + public Container Edits { get; set; } = null!; + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public class SemanticTokensDeltaPartialResult + { + /// + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + /// + public Container Edits { get; set; } = null!; + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public class SemanticTokensEdit + { + /// + /// The start index of the edit + /// + /// + /// in the LSP spec + /// + public int Start { get; set; } + + /// + /// The number of items to delete + /// + /// + /// in the LSP spec + /// + public int DeleteCount { get; set; } + + /// + /// The actual tokens. For a detailed description about how the data is + /// structured pls see + /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + /// + /// + /// in the LSP spec + /// + [Optional] + public ImmutableArray? Data { get; set; } = ImmutableArray.Empty; + } + + [Obsolete(Constants.Proposal)] + [JsonConverter(typeof(SemanticTokensFullOrDeltaConverter))] + public class SemanticTokensFullOrDelta + { + public SemanticTokensFullOrDelta(SemanticTokensDelta delta) + { + Delta = delta; + Full = null; + } + + public SemanticTokensFullOrDelta(SemanticTokens full) + { + Delta = null; + Full = full; + } + + public SemanticTokensFullOrDelta(SemanticTokensFullOrDeltaPartialResult partialResult) + { + Full = null; + Delta = null; + + if (partialResult.IsDelta) + { + Delta = new SemanticTokensDelta(partialResult.Delta!) { + Edits = partialResult.Delta!.Edits + }; + } + + if (partialResult.IsFull) + { + Full = new SemanticTokens(partialResult.Full!); + } + } + + public bool IsFull => Full != null; + public SemanticTokens? Full { get; } + + public bool IsDelta => Delta != null; + public SemanticTokensDelta? Delta { get; } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokensDelta")] + public static SemanticTokensFullOrDelta? From(SemanticTokensDelta? semanticTokensDelta) => semanticTokensDelta switch { + not null => new(semanticTokensDelta), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokensDelta")] + public static implicit operator SemanticTokensFullOrDelta?(SemanticTokensDelta? semanticTokensDelta) => semanticTokensDelta switch { + not null => new(semanticTokensDelta), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokens")] + public static SemanticTokensFullOrDelta? From(SemanticTokens? semanticTokens) => semanticTokens switch { + not null => new(semanticTokens), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokens")] + public static implicit operator SemanticTokensFullOrDelta?(SemanticTokens? semanticTokens) => semanticTokens switch { + not null => new(semanticTokens), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokens")] + public static SemanticTokensFullOrDelta? From(SemanticTokensFullOrDeltaPartialResult? semanticTokens) => semanticTokens switch { + not null => new(semanticTokens), + _ => null + }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("semanticTokens")] + public static implicit operator SemanticTokensFullOrDelta?(SemanticTokensFullOrDeltaPartialResult? semanticTokens) => + semanticTokens switch { + not null => new(semanticTokens), + _ => null + }; + } + + [Obsolete(Constants.Proposal)] + [JsonConverter(typeof(SemanticTokensFullOrDeltaPartialResultConverter))] + public class SemanticTokensFullOrDeltaPartialResult + { + public SemanticTokensFullOrDeltaPartialResult( + SemanticTokensPartialResult full + ) + { + Full = full; + Delta = null; + } + + public SemanticTokensFullOrDeltaPartialResult( + SemanticTokensDeltaPartialResult delta + ) + { + Full = null; + Delta = delta; + } + + public bool IsDelta => Delta != null; + public SemanticTokensDeltaPartialResult? Delta { get; } + + public bool IsFull => Full != null; + public SemanticTokensPartialResult? Full { get; } + + public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensPartialResult semanticTokensPartialResult) => + new SemanticTokensFullOrDeltaPartialResult(semanticTokensPartialResult); + + public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensDeltaPartialResult semanticTokensDeltaPartialResult) => + new SemanticTokensFullOrDeltaPartialResult(semanticTokensDeltaPartialResult); + + public static implicit operator SemanticTokensFullOrDelta(SemanticTokensFullOrDeltaPartialResult semanticTokensDeltaPartialResult) => + new SemanticTokensFullOrDelta(semanticTokensDeltaPartialResult); + } + + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + public class SemanticTokensLegend + { + private ImmutableDictionary? _tokenModifiersData; + private ImmutableDictionary? _tokenTypesData; + + /// + /// The token types a server uses. + /// + public Container TokenTypes { get; set; } = new Container(SemanticTokenType.Defaults); + + /// + /// The token modifiers a server uses. + /// + public Container TokenModifiers { get; set; } = new Container(SemanticTokenModifier.Defaults); + + public int GetTokenTypeIdentity(string tokenType) + { + EnsureTokenTypes(); + if (string.IsNullOrWhiteSpace(tokenType)) return 0; + return _tokenTypesData != null && _tokenTypesData.TryGetValue(tokenType, out var tokenTypeNumber) ? tokenTypeNumber : 0; + } + + public int GetTokenTypeIdentity(SemanticTokenType? tokenType) + { + EnsureTokenTypes(); + if (!tokenType.HasValue) return 0; + if (string.IsNullOrWhiteSpace(tokenType.Value)) return 0; + return _tokenTypesData != null && _tokenTypesData.TryGetValue(tokenType.Value, out var tokenTypeNumber) ? tokenTypeNumber : 0; + } + + public int GetTokenModifiersIdentity(params string[]? tokenModifiers) + { + EnsureTokenModifiers(); + if (tokenModifiers == null) return 0; + return tokenModifiers + .Where(z => !string.IsNullOrWhiteSpace(z)) + .Aggregate( + 0, + (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) + ? acc + tokenModifer + : acc + ); + } + + public int GetTokenModifiersIdentity(IEnumerable? tokenModifiers) + { + EnsureTokenModifiers(); + if (tokenModifiers == null) return 0; + return tokenModifiers + .Where(z => !string.IsNullOrWhiteSpace(z)) + .Aggregate( + 0, + (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) + ? acc + tokenModifer + : acc + ); + } + + public int GetTokenModifiersIdentity(params SemanticTokenModifier[]? tokenModifiers) + { + EnsureTokenModifiers(); + if (tokenModifiers == null) return 0; + return tokenModifiers + .Where(z => !string.IsNullOrWhiteSpace(z)) + .Aggregate( + 0, + (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) + ? acc + tokenModifer + : acc + ); + } + + public int GetTokenModifiersIdentity(IEnumerable? tokenModifiers) + { + EnsureTokenModifiers(); + if (tokenModifiers == null) return 0; + return tokenModifiers + .Where(z => !string.IsNullOrWhiteSpace(z)) + .Aggregate( + 0, + (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) + ? acc + tokenModifer + : acc + ); + } + + private void EnsureTokenTypes() => + _tokenTypesData ??= TokenTypes + .Select( + (value, index) => ( + value: new SemanticTokenType(value), + index + ) + ) + .Where(z => !string.IsNullOrWhiteSpace(z.value)) + .ToImmutableDictionary(z => z.value, z => z.index); + + private void EnsureTokenModifiers() => + _tokenModifiersData ??= TokenModifiers + .Select( + (value, index) => ( + value: new SemanticTokenModifier(value), + index + ) + ) + .Where(z => !string.IsNullOrWhiteSpace(z.value)) + .ToImmutableDictionary(z => z.value, z => Convert.ToInt32(Math.Pow(2, z.index))); + } + + /// + /// The protocol defines an additional token format capability to allow future extensions of the format. + /// The only format that is currently specified is `relative` expressing that the tokens are described using relative positions. + /// + /// @since 3.16.0 + /// + [JsonConverter(typeof(EnumLikeStringConverter))] + [Obsolete(Constants.Proposal)] + [DebuggerDisplay("{_value}")] + public readonly struct SemanticTokenFormat : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(SemanticTokenFormat) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + } + ); + + public static IEnumerable Defaults => _defaults.Value; + + public static readonly SemanticTokenFormat Relative = new SemanticTokenFormat("relative"); + + private readonly string _value; + + public SemanticTokenFormat(string modifier) => _value = modifier; + + public static implicit operator SemanticTokenFormat(string kind) => new SemanticTokenFormat(kind); + + public static implicit operator string(SemanticTokenFormat kind) => kind._value; + + public override string ToString() => _value; + public bool Equals(SemanticTokenFormat other) => _value == other._value; + + public override bool Equals(object obj) => obj is SemanticTokenFormat other && Equals(other); + + public override int GetHashCode() => _value.GetHashCode(); + + public static bool operator ==(SemanticTokenFormat left, SemanticTokenFormat right) => left.Equals(right); + + public static bool operator !=(SemanticTokenFormat left, SemanticTokenFormat right) => !left.Equals(right); + } + + /// + /// A set of predefined token modifiers. This set is not fixed + /// an clients can specify additional token types via the + /// corresponding client capabilities. + /// + /// @since 3.16.0 + /// + [JsonConverter(typeof(EnumLikeStringConverter))] + [Obsolete(Constants.Proposal)] + [DebuggerDisplay("{_value}")] + public readonly struct SemanticTokenModifier : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(SemanticTokenModifier) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + } + ); + + public static IEnumerable Defaults => _defaults.Value; + + public static readonly SemanticTokenModifier Documentation = new SemanticTokenModifier("documentation"); + public static readonly SemanticTokenModifier Declaration = new SemanticTokenModifier("declaration"); + public static readonly SemanticTokenModifier Definition = new SemanticTokenModifier("definition"); + public static readonly SemanticTokenModifier Static = new SemanticTokenModifier("static"); + public static readonly SemanticTokenModifier Async = new SemanticTokenModifier("async"); + public static readonly SemanticTokenModifier Abstract = new SemanticTokenModifier("abstract"); + public static readonly SemanticTokenModifier Deprecated = new SemanticTokenModifier("deprecated"); + public static readonly SemanticTokenModifier Readonly = new SemanticTokenModifier("readonly"); + public static readonly SemanticTokenModifier Modification = new SemanticTokenModifier("modification"); + public static readonly SemanticTokenModifier DefaultLibrary = new SemanticTokenModifier("defaultLibrary"); + + private readonly string _value; + + public SemanticTokenModifier(string modifier) => _value = modifier; + + public static implicit operator SemanticTokenModifier(string kind) => new SemanticTokenModifier(kind); + + public static implicit operator string(SemanticTokenModifier kind) => kind._value; + + public override string ToString() => _value; + public bool Equals(SemanticTokenModifier other) => _value == other._value; + + public override bool Equals(object obj) => obj is SemanticTokenModifier other && Equals(other); + + public override int GetHashCode() => _value.GetHashCode(); + + public static bool operator ==(SemanticTokenModifier left, SemanticTokenModifier right) => left.Equals(right); + + public static bool operator !=(SemanticTokenModifier left, SemanticTokenModifier right) => !left.Equals(right); + } + + + /// + /// A set of predefined token types. This set is not fixed + /// an clients can specify additional token types via the + /// corresponding client capabilities. + /// + /// @since 3.16.0 + /// + [JsonConverter(typeof(EnumLikeStringConverter))] + [Obsolete(Constants.Proposal)] + [DebuggerDisplay("{_value}")] + public readonly struct SemanticTokenType : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(SemanticTokenType) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + } + ); + + public static IEnumerable Defaults => _defaults.Value; + + public static readonly SemanticTokenType Comment = new SemanticTokenType("comment"); + public static readonly SemanticTokenType Keyword = new SemanticTokenType("keyword"); + public static readonly SemanticTokenType String = new SemanticTokenType("string"); + public static readonly SemanticTokenType Number = new SemanticTokenType("number"); + public static readonly SemanticTokenType Regexp = new SemanticTokenType("regexp"); + public static readonly SemanticTokenType Operator = new SemanticTokenType("operator"); + public static readonly SemanticTokenType Namespace = new SemanticTokenType("namespace"); + public static readonly SemanticTokenType Type = new SemanticTokenType("type"); + public static readonly SemanticTokenType Struct = new SemanticTokenType("struct"); + public static readonly SemanticTokenType Class = new SemanticTokenType("class"); + public static readonly SemanticTokenType Interface = new SemanticTokenType("interface"); + public static readonly SemanticTokenType Enum = new SemanticTokenType("enum"); + public static readonly SemanticTokenType TypeParameter = new SemanticTokenType("typeParameter"); + public static readonly SemanticTokenType Function = new SemanticTokenType("function"); + public static readonly SemanticTokenType Member = new SemanticTokenType("member"); + public static readonly SemanticTokenType Property = new SemanticTokenType("property"); + public static readonly SemanticTokenType Macro = new SemanticTokenType("macro"); + public static readonly SemanticTokenType Variable = new SemanticTokenType("variable"); + public static readonly SemanticTokenType Parameter = new SemanticTokenType("parameter"); + public static readonly SemanticTokenType Label = new SemanticTokenType("label"); + public static readonly SemanticTokenType Modifier = new SemanticTokenType("modifier"); + public static readonly SemanticTokenType Event = new SemanticTokenType("event"); + public static readonly SemanticTokenType EnumMember = new SemanticTokenType("enumMember"); + + private readonly string _value; + + public SemanticTokenType(string type) => _value = type; + + public static implicit operator SemanticTokenType(string kind) => new SemanticTokenType(kind); + + public static implicit operator string(SemanticTokenType kind) => kind._value; + + public override string ToString() => _value; + public bool Equals(SemanticTokenType other) => _value == other._value; + + public override bool Equals(object obj) => obj is SemanticTokenType other && Equals(other); + + public override int GetHashCode() => _value.GetHashCode(); + + public static bool operator ==(SemanticTokenType left, SemanticTokenType right) => left.Equals(right); + + public static bool operator !=(SemanticTokenType left, SemanticTokenType right) => !left.Equals(right); + } + + [Obsolete(Constants.Proposal)] + [RegistrationName(TextDocumentNames.SemanticTokensRegistration)] + [GenerateRegistrationOptions(nameof(ServerCapabilities.SemanticTokensProvider))] + [RegistrationOptionsConverter(typeof(SemanticTokensRegistrationOptionsConverter))] + public partial class SemanticTokensRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + /// + /// The legend used by the server + /// + public SemanticTokensLegend Legend { get; set; } = null!; + + /// + /// Server supports providing semantic tokens for a specific range + /// of a document. + /// + [Optional] + public BooleanOr? Range { get; set; } + + /// + /// Server supports providing semantic tokens for a full document. + /// + [Optional] + public BooleanOr? Full { get; set; } + + class SemanticTokensRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public SemanticTokensRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.SemanticTokensProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(SemanticTokensRegistrationOptions source) + { + var result = new StaticOptions { + WorkDoneProgress = source.WorkDoneProgress, + Legend = source.Legend, + Full = source.Full, + Range = source.Range + }; + if (result.Full != null && result.Full?.Value.Delta != true) + { + var edits = _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ISemanticTokensDeltaHandler)); + if (edits) + { + result.Full = new BooleanOr( + new SemanticTokensCapabilityRequestFull { + Delta = true + } + ); + } + } + + return result; + } + } + } + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to the `textDocument/semanticTokens` + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.SemanticTokens))] + public partial class SemanticTokensCapability : DynamicCapability, ConnectedCapability, + ConnectedCapability, ConnectedCapability, + ConnectedCapability + { + /// + /// Which requests the client supports and might send to the server. + /// + public SemanticTokensCapabilityRequests Requests { get; set; } = null!; + + /// + /// The token types that the client supports. + /// + public Container TokenTypes { get; set; } = null!; + + /// + /// The token modifiers that the client supports. + /// + public Container TokenModifiers { get; set; } = null!; + + /// + /// The formats the clients supports. + /// + public Container Formats { get; set; } = null!; + + /// + /// Whether the client supports tokens that can overlap each other. + /// + [Optional] + public bool OverlappingTokenSupport { get; set; } + + /// + /// Whether the client supports tokens that can span multiple lines. + /// + [Optional] + public bool MultilineTokenSupport { get; set; } + } + + public partial class SemanticTokensCapabilityRequests + { + /// + /// The client will send the `textDocument/semanticTokens/range` request if + /// the server provides a corresponding handler. + /// + [Optional] + public Supports Range { get; set; } + + /// + /// The client will send the `textDocument/semanticTokens/full` request if + /// the server provides a corresponding handler. + /// + [Optional] + public Supports Full { get; set; } + } + + /// + /// The client will send the `textDocument/semanticTokens/range` request if + /// the server provides a corresponding handler. + /// + public partial class SemanticTokensCapabilityRequestRange + { + } + + /// + /// The client will send the `textDocument/semanticTokens/full` request if + /// the server provides a corresponding handler. + /// + public partial class SemanticTokensCapabilityRequestFull + { + /// + /// The client will send the `textDocument/semanticTokens/full/delta` request if + /// the server provides a corresponding handler. + /// + [Optional] + public bool Delta { get; set; } + } + + /// + /// Capabilities specific to the semantic token requests scoped to the + /// workspace. + /// + /// @since 3.16.0 - proposed state. + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.SemanticTokens))] + public class SemanticTokensWorkspaceCapability : ICapability + { + /// + /// Whether the client implementation supports a refresh request send from + /// the server to the client. This is useful if a server detects a project + /// wide configuration change which requires a re-calculation of all semantic + /// tokens provided by the server issuing the request. + /// + [Optional] + public bool RefreshSupport { get; set; } + } + } + + namespace Document.Proposals + { + [Obsolete(Constants.Proposal)] + public abstract class SemanticTokensHandlerBase : + AbstractHandlers.Base, + ISemanticTokensFullHandler, + ISemanticTokensDeltaHandler, + ISemanticTokensRangeHandler + { + public virtual async Task Handle(SemanticTokensParams request, CancellationToken cancellationToken) + { + var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); + var builder = document.Create(); + await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); + return builder.Commit().GetSemanticTokens(); + } + + public virtual async Task Handle(SemanticTokensDeltaParams request, CancellationToken cancellationToken) + { + var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); + var builder = document.Edit(request); + await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); + return builder.Commit().GetSemanticTokensEdits(); + } + + public virtual async Task Handle(SemanticTokensRangeParams request, CancellationToken cancellationToken) + { + var document = await GetSemanticTokensDocument(request, cancellationToken).ConfigureAwait(false); + var builder = document.Create(); + await Tokenize(builder, request, cancellationToken).ConfigureAwait(false); + return builder.Commit().GetSemanticTokens(request.Range); + } + + public virtual void SetCapability(SemanticTokensCapability capability) => Capability = capability; + protected SemanticTokensCapability Capability { get; private set; } = null!; + protected abstract Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, CancellationToken cancellationToken); + protected abstract Task GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken); + } + + [Obsolete(Constants.Proposal)] + public static partial class SemanticTokensExtensions + { + private static SemanticTokensRegistrationOptions RegistrationOptionsFactory(SemanticTokensCapability capability, ClientCapabilities clientCapabilities) + { + var registrationOptions = new SemanticTokensRegistrationOptions { + Full = new SemanticTokensCapabilityRequestFull() + }; + registrationOptions.Range ??= new SemanticTokensCapabilityRequestRange(); + if (registrationOptions.Full?.IsValue == true) + { + registrationOptions.Full.Value.Delta = true; + } + + // Ensure the legend is created properly. + registrationOptions.Legend = new SemanticTokensLegend() { + TokenModifiers = SemanticTokenModifier.Defaults.Join(capability.TokenModifiers, z => z, z => z, (a, b) => a).ToArray(), + TokenTypes = SemanticTokenType.Defaults.Join(capability.TokenTypes, z => z, z => z, (a, b) => a).ToArray(), + }; + + return registrationOptions; + } + + public static ILanguageServerRegistry OnSemanticTokens( + this ILanguageServerRegistry registry, + Func tokenize, + Func> getSemanticTokensDocument, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + registrationOptionsFactory ??= RegistrationOptionsFactory; + return registry.AddHandlers( + new DelegatingHandlerBase( + HandlerAdapter.Adapt(tokenize), + HandlerAdapter.Adapt(getSemanticTokensDocument), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnSemanticTokens( + this ILanguageServerRegistry registry, + Func tokenize, + Func> getSemanticTokensDocument, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + registrationOptionsFactory ??= RegistrationOptionsFactory; + return registry.AddHandlers( + new DelegatingHandlerBase( + HandlerAdapter.Adapt(tokenize), + HandlerAdapter.Adapt(getSemanticTokensDocument), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnSemanticTokens( + this ILanguageServerRegistry registry, + Func tokenize, + Func> getSemanticTokensDocument, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + registrationOptionsFactory ??= RegistrationOptionsFactory; + return registry.AddHandlers( + new DelegatingHandlerBase( + HandlerAdapter.Adapt(tokenize), + HandlerAdapter.Adapt(getSemanticTokensDocument), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + private class DelegatingHandlerBase : SemanticTokensHandlerBase + { + private readonly Func _tokenize; + private readonly Func> _getSemanticTokensDocument; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + + public DelegatingHandlerBase( + Func tokenize, + Func> getSemanticTokensDocument, + RegistrationOptionsDelegate registrationOptionsFactory + ) : base() + { + _tokenize = tokenize; + _getSemanticTokensDocument = getSemanticTokensDocument; + _registrationOptionsFactory = registrationOptionsFactory; + } + + protected override Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, CancellationToken cancellationToken) + => _tokenize(builder, identifier, Capability, cancellationToken); + + protected override Task GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken) + => _getSemanticTokensDocument(@params, Capability, cancellationToken); + + protected internal override SemanticTokensRegistrationOptions CreateRegistrationOptions(SemanticTokensCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public static IRequestProgressObservable RequestSemanticTokens( + this ITextDocumentLanguageClient mediator, + SemanticTokensParams @params, CancellationToken cancellationToken = default + ) => + mediator.ProgressManager.MonitorUntil( + @params, (partial, result) => new SemanticTokens { + Data = partial.Data, + ResultId = result?.ResultId + }, cancellationToken + ); + + public static IRequestProgressObservable RequestSemanticTokensDelta( + this ITextDocumentLanguageClient mediator, SemanticTokensDeltaParams @params, CancellationToken cancellationToken = default + ) => + mediator.ProgressManager.MonitorUntil( + @params, (partial, result) => { + if (partial.IsDelta) + { + return new SemanticTokensFullOrDelta( + new SemanticTokensDelta { + Edits = partial.Delta!.Edits, + ResultId = result?.Delta?.ResultId ?? result?.Full?.ResultId + } + ); + } + + if (partial.IsFull) + { + return new SemanticTokensFullOrDelta( + new SemanticTokens { + Data = partial.Full!.Data, + ResultId = result?.Full?.ResultId ?? result?.Delta?.ResultId + } + ); + } + + return new SemanticTokensFullOrDelta(new SemanticTokens()); + }, cancellationToken + ); + + public static IRequestProgressObservable RequestSemanticTokensRange( + this ITextDocumentLanguageClient mediator, + SemanticTokensRangeParams @params, CancellationToken cancellationToken = default + ) => + mediator.ProgressManager.MonitorUntil( + @params, (partial, result) => new SemanticTokens { + Data = partial.Data, + ResultId = result?.ResultId + }, cancellationToken + ); + } + } +} diff --git a/src/Protocol/Features/Document/PublishDiagnosticsFeature.cs b/src/Protocol/Features/Document/PublishDiagnosticsFeature.cs new file mode 100644 index 000000000..7273c1574 --- /dev/null +++ b/src/Protocol/Features/Document/PublishDiagnosticsFeature.cs @@ -0,0 +1,113 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.PublishDiagnostics, Direction.ServerToClient)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageServer), typeof(ILanguageServer)) + ] + [Capability(typeof(PublishDiagnosticsCapability))] + public class PublishDiagnosticsParams : IRequest + { + /// + /// The URI for which diagnostic information is reported. + /// + public DocumentUri Uri { get; set; } = null!; + + /// + /// Optional the version number of the document the diagnostics are published for. + /// + /// @since 3.15.0 + /// + /// + /// in the LSP spec + /// + [Optional] + public int? Version { get; set; } + + /// + /// An array of diagnostic information items. + /// + public Container Diagnostics { get; set; } = null!; + } + } + + namespace Document + { + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to `textDocument/publishDiagnostics`. + /// + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.PublishDiagnostics))] + public class PublishDiagnosticsCapability : ICapability + { + /// + /// Whether the clients accepts diagnostics with related information. + /// + [Optional] + public bool RelatedInformation { get; set; } + + /// + /// Client supports the tag property to provide meta data about a diagnostic. + /// Clients supporting tags have to handle unknown tags gracefully. + /// + /// @since 3.15.0 + /// + [Optional] + public Supports TagSupport { get; set; } + + /// + /// Whether the client interprets the version property of the + /// `textDocument/publishDiagnostics` notification's parameter. + /// + /// @since 3.15.0 + /// + [Optional] + public bool VersionSupport { get; set; } + + /// + /// Client supports a codeDescription property + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public bool CodeDescriptionSupport { get; set; } + + /// + /// Whether code action supports the `data` property which is + /// preserved between a `textDocument/publishDiagnostics` and + /// `textDocument/codeAction` request. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public bool DataSupport { get; set; } + } + + public class PublishDiagnosticsTagSupportCapabilityOptions + { + /// + /// The tags supported by the client. + /// + public Container ValueSet { get; set; } = null!; + } + } +} diff --git a/src/Protocol/Features/Document/ReferencesFeature.cs b/src/Protocol/Features/Document/ReferencesFeature.cs new file mode 100644 index 000000000..bd8bb6ca5 --- /dev/null +++ b/src/Protocol/Features/Document/ReferencesFeature.cs @@ -0,0 +1,53 @@ +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.References, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "References"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(ReferenceRegistrationOptions)), Capability(typeof(ReferenceCapability))] + public partial class ReferenceParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + public ReferenceContext Context { get; set; } = null!; + } + public class ReferenceContext + { + /// + /// Include the declaration of the current symbol. + /// + public bool IncludeDeclaration { get; set; } + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.ReferencesProvider))] + public partial class ReferenceRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.References))] + public partial class ReferenceCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/RenameFeature.cs b/src/Protocol/Features/Document/RenameFeature.cs new file mode 100644 index 000000000..c26695460 --- /dev/null +++ b/src/Protocol/Features/Document/RenameFeature.cs @@ -0,0 +1,183 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.Rename, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(RenameRegistrationOptions)), Capability(typeof(RenameCapability))] + public partial class RenameParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams + { + /// + /// The document to format. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The position at which this request was sent. + /// + public Position Position { get; set; } = null!; + + /// + /// The new name of the symbol. If the given name is not valid the + /// request must return a [ResponseError](#ResponseError) with an + /// appropriate message set. + /// + public string NewName { get; set; } = null!; + } + + [Parallel] + [Method(TextDocumentNames.PrepareRename, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(RenameRegistrationOptions)), Capability(typeof(RenameCapability))] + public partial class PrepareRenameParams : TextDocumentPositionParams, IRequest + { + } + + [JsonConverter(typeof(RangeOrPlaceholderRangeConverter))] + public class RangeOrPlaceholderRange + { + private RenameDefaultBehavior? _renameDefaultBehavior; + private Range? _range; + private PlaceholderRange? _placeholderRange; + + public RangeOrPlaceholderRange(Range value) + { + _range = value; + } + + public RangeOrPlaceholderRange(PlaceholderRange value) + { + _placeholderRange = value; + } + + public RangeOrPlaceholderRange(RenameDefaultBehavior renameDefaultBehavior) + { + _renameDefaultBehavior = renameDefaultBehavior; + } + + public bool IsPlaceholderRange => _placeholderRange != null; + + public PlaceholderRange? PlaceholderRange + { + get => _placeholderRange; + set { + _placeholderRange = value; + _renameDefaultBehavior = default; + _range = null; + } + } + + public bool IsRange => _range is not null; + + public Range? Range + { + get => _range; + set { + _placeholderRange = default; + _renameDefaultBehavior = default; + _range = value; + } + } + + public bool IsDefaultBehavior => _renameDefaultBehavior is not null; + + public RenameDefaultBehavior? DefaultBehavior + { + get => _renameDefaultBehavior; + set { + _placeholderRange = default; + _renameDefaultBehavior = value; + _range = default; + } + } + + public object? RawValue + { + get { + if (IsPlaceholderRange) return PlaceholderRange; + if (IsRange) return Range; + if (IsDefaultBehavior) return DefaultBehavior; + return default; + } + } + + public static implicit operator RangeOrPlaceholderRange(PlaceholderRange value) => new RangeOrPlaceholderRange(value); + + public static implicit operator RangeOrPlaceholderRange(Range value) => new RangeOrPlaceholderRange(value); + } + + public class PlaceholderRange + { + public Range Range { get; set; } = null!; + public string Placeholder { get; set; } = null!; + } + + public class RenameDefaultBehavior + { + public bool DefaultBehavior { get; set; } + } + + [RegistrationName(TextDocumentNames.Rename)] + [GenerateRegistrationOptions(nameof(ServerCapabilities.RenameProvider))] + public partial class RenameRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + /// + /// Renames should be checked and tested before being executed. + /// + [Optional] + public bool PrepareProvider { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Rename))] + public class RenameCapability : DynamicCapability, ConnectedCapability + { + /// + /// Client supports testing for validity of rename operations + /// before execution. + /// + [Optional] + public bool PrepareSupport { get; set; } + + /// + /// Client supports the default behavior result (`{ defaultBehavior: boolean }`). + /// + /// @since version 3.16.0 + /// + [Optional] + public bool PrepareSupportDefaultBehavior { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/SelectionRangeFeature.cs b/src/Protocol/Features/Document/SelectionRangeFeature.cs new file mode 100644 index 000000000..779adaee6 --- /dev/null +++ b/src/Protocol/Features/Document/SelectionRangeFeature.cs @@ -0,0 +1,86 @@ +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.SelectionRange, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(SelectionRangeRegistrationOptions)), Capability(typeof(SelectionRangeCapability))] + public partial class SelectionRangeParams : ITextDocumentIdentifierParams, IPartialItemsRequest?, SelectionRange>, IWorkDoneProgressParams + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The positions inside the text document. + /// + public Container Positions { get; set; } = null!; + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial class SelectionRange + { + /// + /// The [range](#Range) of this selection range. + /// + public Range Range { get; set; } = null!; + + /// + /// The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. + /// + public SelectionRange Parent { get; set; } = null!; + + private string DebuggerDisplay => $"{Range} {{{Parent}}}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.SelectionRangeProvider))] + public partial class SelectionRangeRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.SelectionRange))] + public partial class SelectionRangeCapability : DynamicCapability, ConnectedCapability + { + /// + /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a + /// hint, servers are free to follow the limit. + /// + [Optional] + public int? RangeLimit { get; set; } + + /// + /// If set, the client signals that it only supports folding complete lines. If set, client will + /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. + /// + public bool LineFoldingOnly { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/SignatureHelpFeature.cs b/src/Protocol/Features/Document/SignatureHelpFeature.cs new file mode 100644 index 000000000..31235eec3 --- /dev/null +++ b/src/Protocol/Features/Document/SignatureHelpFeature.cs @@ -0,0 +1,300 @@ +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.SignatureHelp, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(SignatureHelpRegistrationOptions)), Capability(typeof(SignatureHelpCapability))] + public partial class SignatureHelpParams : TextDocumentPositionParams, IWorkDoneProgressParams, IRequest + { + /// + /// The signature help context. This is only available if the client specifies + /// to send this using the client capability `textDocument.signatureHelp.contextSupport === true` + /// + /// @since 3.15.0 + /// + public SignatureHelpContext Context { get; set; } = null!; + } + + /// + /// Additional information about the context in which a signature help request was triggered. + /// + /// @since 3.15.0 + /// + public class SignatureHelpContext + { + /// + /// Action that caused signature help to be triggered. + /// + public SignatureHelpTriggerKind TriggerKind { get; set; } + + /// + /// Character that caused signature help to be triggered. + /// + /// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` + /// + [Optional] + public string? TriggerCharacter { get; set; } + + /// + /// `true` if signature help was already showing when it was triggered. + /// + /// Retriggers occur when the signature help is already active and can be caused by actions such as + /// typing a trigger character, a cursor move, or document content changes. + /// + public bool IsRetrigger { get; set; } + + /// + /// The currently active `SignatureHelp`. + /// + /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on + /// the user navigating through available signatures. + /// + [Optional] + public SignatureHelp? ActiveSignatureHelp { get; set; } + } + + /// + /// How a signature help was triggered. + /// + /// @since 3.15.0 + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum SignatureHelpTriggerKind + { + /// + /// Signature help was invoked manually by the user or by a command. + /// + Invoked = 1, + + /// + /// Signature help was triggered by a trigger character. + /// + TriggerCharacter = 2, + + /// + /// Signature help was triggered by the cursor moving or by the document content changing. + /// + ContentChange = 3, + } + + /// + /// Signature help represents the signature of something + /// callable. There can be multiple signature but only one + /// active and only one active parameter. + /// + public partial class SignatureHelp + { + /// + /// One or more signatures. + /// + public Container Signatures { get; set; } = new Container(); + + /// + /// The active signature. + /// + [Optional] + public int? ActiveSignature { get; set; } + + /// + /// The active parameter of the active signature. + /// + [Optional] + public int? ActiveParameter { get; set; } + } + + /// + /// Represents the signature of something callable. A signature + /// can have a label, like a function-name, a doc-comment, and + /// a set of parameters. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class SignatureInformation + { + /// + /// The label of this signature. Will be shown in + /// the UI. + /// + public string Label { get; set; } = null!; + + /// + /// The human-readable doc-comment of this signature. Will be shown + /// in the UI but can be omitted. + /// + [Optional] + public StringOrMarkupContent? Documentation { get; set; } + + /// + /// The parameters of this signature. + /// + [Optional] + public Container? Parameters { get; set; } + + /// + /// The index of the active parameter. + /// + /// If provided, this is used in place of `SignatureHelp.activeParameter`. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public int? ActiveParameter { get; set; } + + private string DebuggerDisplay => $"{Label}{Documentation?.ToString() ?? ""}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + /// + /// Represents a parameter of a callable-signature. A parameter can + /// have a label and a doc-comment. + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class ParameterInformation + { + /// + /// The label of this parameter. Will be shown in + /// the UI. + /// + public ParameterInformationLabel Label { get; set; } = null!; + + /// + /// The human-readable doc-comment of this parameter. Will be shown + /// in the UI but can be omitted. + /// + [Optional] + public StringOrMarkupContent? Documentation { get; set; } + + private string DebuggerDisplay => $"{Label}{( Documentation != null ? $" {Documentation}" : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [JsonConverter(typeof(ParameterInformationLabelConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class ParameterInformationLabel + { + public ParameterInformationLabel((int start, int end) range) => Range = range; + + public ParameterInformationLabel(string label) => Label = label; + + public (int start, int end) Range { get; } + public bool IsRange => Label == null; + public string? Label { get; } + public bool IsLabel => Label != null; + + public static implicit operator ParameterInformationLabel(string label) => new ParameterInformationLabel(label); + + public static implicit operator ParameterInformationLabel((int start, int end) range) => new ParameterInformationLabel(range); + + private string DebuggerDisplay => IsRange ? $"(start: {Range.start}, end: {Range.end})" : IsLabel ? Label! : string.Empty; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.SignatureHelpProvider))] + public partial class SignatureHelpRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// The characters that trigger signature help + /// automatically. + /// + [Optional] + public Container? TriggerCharacters { get; set; } + + /// + /// List of characters that re-trigger signature help. + /// + /// These trigger characters are only active when signature help is already showing. All trigger characters + /// are also counted as re-trigger characters. + /// + /// @since 3.15.0 + /// + [Optional] + public Container? RetriggerCharacters { get; set; } + } + } + + namespace Client.Capabilities + { + public partial class SignatureHelpCapability : DynamicCapability, ConnectedCapability + { + /// + /// The client supports the following `SignatureInformation` + /// specific properties. + /// + [Optional] + public SignatureInformationCapabilityOptions? SignatureInformation { get; set; } + + /// + /// The client supports to send additional context information for a + /// `textDocument/signatureHelp` request. A client that opts into + /// contextSupport will also support the `retriggerCharacters` on + /// `StaticOptions`. + /// + /// @since 3.15.0 + /// + [Optional] + public bool ContextSupport { get; set; } + } + + public class SignatureInformationCapabilityOptions + { + /// + /// Client supports the follow content formats for the content property. The order describes the preferred format of the client. + /// + [Optional] + public Container? DocumentationFormat { get; set; } + + [Optional] public SignatureParameterInformationCapabilityOptions? ParameterInformation { get; set; } + + /// + /// The client support the `activeParameter` property on `SignatureInformation` + /// literal. + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public bool ActiveParameterSupport { get; set; } + } + + public class SignatureParameterInformationCapabilityOptions + { + /// + /// The client supports processing label offsets instead of a + /// simple label string. + /// + [Optional] + public bool LabelOffsetSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/TextDocumentSyncFeature.cs b/src/Protocol/Features/Document/TextDocumentSyncFeature.cs new file mode 100644 index 000000000..983ef2351 --- /dev/null +++ b/src/Protocol/Features/Document/TextDocumentSyncFeature.cs @@ -0,0 +1,754 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Serial] + [Method(TextDocumentNames.DidChange, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumentChangeRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class DidChangeTextDocumentParams : IRequest + { + /// + /// The document that did change. The version number points + /// to the version after all provided content changes have + /// been applied. + /// + public VersionedTextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The actual content changes. + /// + public Container ContentChanges { get; set; } = null!; + } + + /// + /// Descibe options to be used when registered for text document change events. + /// + [GenerateRegistrationOptions] + public partial class TextDocumentChangeRegistrationOptions : ITextDocumentRegistrationOptions + { + /// + /// How documents are synced to the server. See TextDocumentSyncKind.Full + /// and TextDocumentSyncKindIncremental. + /// + public TextDocumentSyncKind SyncKind { get; set; } + } + + /// + /// An event describing a change to a text document. If range and rangeLength are omitted + /// the new text is considered to be the full content of the document. + /// + public class TextDocumentContentChangeEvent + { + /// + /// The range of the document that changed. + /// + [Optional] + public Range? Range { get; set; } + + /// + /// The length of the range that got replaced. + /// + /// + /// in the LSP spec + /// + [Optional] + public int RangeLength { get; set; } + + /// + /// The new text of the document. + /// + public string Text { get; set; } = null!; + } + + public class TextDocumentEdit + { + /// + /// The text document to change. + /// + public VersionedTextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The edits to be applied. + /// + public TextEditContainer Edits { get; set; } = null!; + } + + [Serial] + [Method(TextDocumentNames.DidOpen, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumentOpenRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class DidOpenTextDocumentParams : IRequest + { + /// + /// The document that was opened. + /// + public TextDocumentItem TextDocument { get; set; } = null!; + } + + [GenerateRegistrationOptions] + public partial class TextDocumentOpenRegistrationOptions : ITextDocumentRegistrationOptions + { + } + + [Parallel] + [Method(TextDocumentNames.DidClose, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumentCloseRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class DidCloseTextDocumentParams : ITextDocumentIdentifierParams, IRequest + { + /// + /// The document that was closed. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + } + + [GenerateRegistrationOptions] + public partial class TextDocumentCloseRegistrationOptions : ITextDocumentRegistrationOptions + { + } + + [Serial] + [Method(TextDocumentNames.DidSave, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumentSaveRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class DidSaveTextDocumentParams : ITextDocumentIdentifierParams, IRequest + { + /// + /// The document that was saved. + /// + /// + /// TODO: Change to RequiredVersionedTextDocumentIdentifier (or in the future will be VersionedTextDocumentIdentifier) + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// Optional the content when saved. Depends on the includeText value + /// when the save notification was requested. + /// + [Optional] + public string? Text { get; set; } + } + + [GenerateRegistrationOptions] + public partial class TextDocumentSaveRegistrationOptions : ITextDocumentRegistrationOptions + { + /// + /// The client is supposed to include the content on save. + /// + [Optional] + public bool IncludeText { get; set; } + } + + [GenerateRegistrationOptions] + public partial class TextDocumentSyncRegistrationOptions : ITextDocumentRegistrationOptions + { + public TextDocumentSyncRegistrationOptions() + { + SyncKind = TextDocumentSyncKind.Full; + } + + public TextDocumentSyncRegistrationOptions(TextDocumentSyncKind syncKind) + { + SyncKind = syncKind; + } + + /// + /// The client is supposed to include the content on save. + /// + [Optional] + public bool IncludeText { get; set; } + + /// + /// How documents are synced to the server. See TextDocumentSyncKind.Full + /// and TextDocumentSyncKindIncremental. + /// + public TextDocumentSyncKind SyncKind { get; init; } + + public static implicit operator TextDocumentSaveRegistrationOptions(TextDocumentSyncRegistrationOptions options) + { + return new() { + DocumentSelector = options.DocumentSelector, + IncludeText = options.IncludeText + }; + } + + public static implicit operator TextDocumentChangeRegistrationOptions(TextDocumentSyncRegistrationOptions options) + { + return new() { + DocumentSelector = options.DocumentSelector, + SyncKind = options.SyncKind, + }; + } + + public static implicit operator TextDocumentOpenRegistrationOptions(TextDocumentSyncRegistrationOptions options) + { + return new() { + DocumentSelector = options.DocumentSelector, + }; + } + + public static implicit operator TextDocumentCloseRegistrationOptions(TextDocumentSyncRegistrationOptions options) + { + return new() { + DocumentSelector = options.DocumentSelector, + }; + } + } + + /// + /// The parameters send in a will save text document notification. + /// + [Parallel] + [Method(TextDocumentNames.WillSave, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumenWillSaveRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class WillSaveTextDocumentParams : IRequest + { + /// + /// The document that will be saved. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The 'TextDocumentSaveReason'. + /// + public TextDocumentSaveReason Reason { get; set; } + } + + [GenerateRegistrationOptions] + public partial class TextDocumenWillSaveRegistrationOptions : ITextDocumentRegistrationOptions + { + } + + /// + /// The parameters send in a will save text document notification. + /// + [Parallel] + [Method(TextDocumentNames.WillSaveWaitUntil, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TextDocumentWillSaveWaitUntilRegistrationOptions)), Capability(typeof(SynchronizationCapability))] + public partial class WillSaveWaitUntilTextDocumentParams : IRequest + { + /// + /// The document that will be saved. + /// + public TextDocumentIdentifier TextDocument { get; set; } = null!; + + /// + /// The 'TextDocumentSaveReason'. + /// + public TextDocumentSaveReason Reason { get; set; } + } + + [GenerateRegistrationOptions] + public partial class TextDocumentWillSaveWaitUntilRegistrationOptions : ITextDocumentRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Synchronization))] + public class SynchronizationCapability : DynamicCapability, + ConnectedCapability, + ConnectedCapability, + ConnectedCapability, + ConnectedCapability, + ConnectedCapability, + ConnectedCapability + { + /// + /// The client supports sending will save notifications. + /// + [Optional] + public bool WillSave { get; set; } + + /// + /// The client supports sending a will save request and + /// waits for a response providing text edits which will + /// be applied to the document before it is saved. + /// + [Optional] + public bool WillSaveWaitUntil { get; set; } + + /// + /// The client supports did save notifications. + /// + [Optional] + public bool DidSave { get; set; } + } + } + + namespace Document + { + public interface ITextDocumentSyncHandler : IDidChangeTextDocumentHandler, IDidOpenTextDocumentHandler, + IDidCloseTextDocumentHandler, IDidSaveTextDocumentHandler, ITextDocumentIdentifier + { + } + + public abstract class TextDocumentSyncHandlerBase : ITextDocumentSyncHandler + { + + public TextDocumentSyncHandlerBase() + { + } + + public abstract TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri); + public abstract Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken); + + private TextDocumentSyncRegistrationOptions? _registrationOptions; + + protected TextDocumentSyncRegistrationOptions RegistrationOptions + { + get => _registrationOptions!; + private set => _registrationOptions = value; + } + + protected SynchronizationCapability Capability { get; private set; } = default!; + + protected abstract TextDocumentSyncRegistrationOptions CreateRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities); + private TextDocumentSyncRegistrationOptions AssignRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) + { + Capability = capability; + return CreateRegistrationOptions(capability, clientCapabilities); + } + + TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions( + SynchronizationCapability capability, ClientCapabilities clientCapabilities + ) => _registrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); + + TextDocumentOpenRegistrationOptions IRegistration.GetRegistrationOptions( + SynchronizationCapability capability, ClientCapabilities clientCapabilities + ) => _registrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); + + TextDocumentCloseRegistrationOptions IRegistration.GetRegistrationOptions( + SynchronizationCapability capability, ClientCapabilities clientCapabilities + ) => _registrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); + + TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions( + SynchronizationCapability capability, ClientCapabilities clientCapabilities + ) => _registrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); + } + + + public static class TextDocumentSyncExtensions + { + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + onOpenHandler, + onCloseHandler, + onChangeHandler, + onSaveHandler, + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnTextDocumentSync( + this ILanguageServerRegistry registry, + TextDocumentSyncKind kind, + Func getTextDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + TextDocumentSyncRegistrationOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getTextDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + private class DelegatingHandler : TextDocumentSyncHandlerBase + { + private readonly Func _onOpenHandler; + private readonly Func _onCloseHandler; + private readonly Func _onChangeHandler; + private readonly Func _onSaveHandler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Func _getTextDocumentAttributes; + + public DelegatingHandler( + Func getTextDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _onOpenHandler = onOpenHandler; + _onSaveHandler = onSaveHandler; + _registrationOptionsFactory = registrationOptionsFactory; + _onChangeHandler = onChangeHandler; + _onCloseHandler = onCloseHandler; + _getTextDocumentAttributes = getTextDocumentAttributes; + } + + public override async Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken) + { + await _onOpenHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken) + { + await _onChangeHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken) + { + await _onSaveHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken) + { + await _onCloseHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + + public override TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri) => _getTextDocumentAttributes.Invoke(uri); + } + } + } +} diff --git a/src/Protocol/Features/Document/TypeDefinitionFeature.cs b/src/Protocol/Features/Document/TypeDefinitionFeature.cs new file mode 100644 index 000000000..5b6ca7642 --- /dev/null +++ b/src/Protocol/Features/Document/TypeDefinitionFeature.cs @@ -0,0 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(TextDocumentNames.TypeDefinition, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(TypeDefinitionRegistrationOptions)), Capability(typeof(TypeDefinitionCapability))] + public partial class TypeDefinitionParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + { + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.TypeDefinitionProvider))] + public partial class TypeDefinitionRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions { } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.TypeDefinition))] + public partial class TypeDefinitionCapability : LinkSupportCapability, ConnectedCapability + { + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/General/ExitFeature.cs b/src/Protocol/Features/General/ExitFeature.cs new file mode 100644 index 000000000..f8d2fa6ea --- /dev/null +++ b/src/Protocol/Features/General/ExitFeature.cs @@ -0,0 +1,28 @@ +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Serial] + [Method(GeneralNames.Exit, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.General"), GenerateHandlerMethods, GenerateRequestMethods(typeof(ILanguageClient))] + public partial class ExitParams : IRequest + { + public static ExitParams Instance { get; } = new ExitParams(); + } + } + + namespace General + { + public static partial class ExitExtensions + { + public static void SendExit(this ILanguageClient mediator) => mediator.SendNotification(ExitParams.Instance); + } + } +} diff --git a/src/Protocol/Features/General/InitializeFeature.cs b/src/Protocol/Features/General/InitializeFeature.cs new file mode 100644 index 000000000..27b5d19e1 --- /dev/null +++ b/src/Protocol/Features/General/InitializeFeature.cs @@ -0,0 +1,303 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + public partial interface IInitializeParams : IWorkDoneProgressParams, IRequest + { + /// + /// The process Id of the parent process that started + /// the server. Is null if the process has not been started by another process. + /// If the parent process is not alive then the server should exit (see exit notification) its process. + /// + long? ProcessId { get; set; } + + /// + /// Information about the client + /// + /// @since 3.15.0 + /// + [DisallowNull] + ClientInfo? ClientInfo { get; set; } + + /// + /// The rootPath of the workspace. Is null + /// if no folder is open. + /// + /// @deprecated in favour of rootUri. + /// + [DisallowNull] + string? RootPath { get; set; } + + /// + /// The rootUri of the workspace. Is null if no + /// folder is open. If both `rootPath` and `rootUri` are set + /// `rootUri` wins. + /// + [DisallowNull] + DocumentUri? RootUri { get; set; } + + /// + /// User provided initialization options. + /// + [DisallowNull] + object? InitializationOptions { get; set; } + + /// + /// The capabilities provided by the client (editor or tool) + /// + [MaybeNull] + TClientCapabilities Capabilities { get; set; } + + /// + /// The initial trace setting. If omitted trace is disabled ('off'). + /// + InitializeTrace Trace { get; set; } + + /// + /// The workspace folders configured in the client when the server starts. + /// This property is only available if the client supports workspace folders. + /// It can be `null` if the client supports workspace folders but none are + /// configured. + /// + /// Since 3.6.0 + /// + [DisallowNull] + Container? WorkspaceFolders { get; set; } + } + + [Method(GeneralNames.Initialize, Direction.ClientToServer)] + public class InitializeParams : IInitializeParams + { + /// + /// The process Id of the parent process that started + /// the server. Is null if the process has not been started by another process. + /// If the parent process is not alive then the server should exit (see exit notification) its process. + /// + public long? ProcessId { get; set; } + + /// + /// Information about the client + /// + /// @since 3.15.0 + /// + [Optional] + [DisallowNull] + public ClientInfo? ClientInfo { get; set; } + + /// + /// The rootPath of the workspace. Is null + /// if no folder is open. + /// + /// @deprecated in favour of rootUri. + /// + [Optional] + [DisallowNull] + public string? RootPath + { + get => RootUri?.GetFileSystemPath(); + set { + if (!string.IsNullOrEmpty(value)) + { + RootUri = DocumentUri.FromFileSystemPath(value!); + } + } + } + + /// + /// The rootUri of the workspace. Is null if no + /// folder is open. If both `rootPath` and `rootUri` are set + /// `rootUri` wins. + /// + [DisallowNull] + public DocumentUri? RootUri { get; set; } + + /// + /// User provided initialization options. + /// + [DisallowNull] + public object? InitializationOptions { get; set; } + + /// + /// The capabilities provided by the client (editor or tool) + /// + [MaybeNull] + public ClientCapabilities Capabilities { get; set; } = null!; + + /// + /// The initial trace setting. If omitted trace is disabled ('off'). + /// + [Optional] + public InitializeTrace Trace { get; set; } = InitializeTrace.Off; + + /// + /// The workspace folders configured in the client when the server starts. + /// This property is only available if the client supports workspace folders. + /// It can be `null` if the client supports workspace folders but none are + /// configured. + /// + /// Since 3.6.0 + /// + [MaybeNull] + public Container? WorkspaceFolders { get; set; } + + /// + [Optional] + [MaybeNull] + public ProgressToken? WorkDoneToken { get; set; } + + /// + /// The locale the client is currently showing the user interface + /// in. This must not necessarily be the locale of the operating + /// system. + /// + /// Uses IETF language tags as the value's syntax + /// (See https://en.wikipedia.org/wiki/IETF_language_tag) + /// + /// @since 3.16.0 - proposed state + /// + [Optional] + public string? Locale { get; set; } + + public InitializeParams() + { + } + + internal InitializeParams(IInitializeParams @params, ClientCapabilities clientCapabilities) + { + ProcessId = @params.ProcessId; + Trace = @params.Trace; + Capabilities = clientCapabilities; + ClientInfo = @params.ClientInfo!; + InitializationOptions = @params.InitializationOptions!; + RootUri = @params.RootUri!; + WorkspaceFolders = @params.WorkspaceFolders!; + WorkDoneToken = @params.WorkDoneToken!; + } + } + + [Serial] + [Method(GeneralNames.Initialize, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.General", Name = "LanguageProtocolInitialize")] + [GenerateHandlerMethods(typeof(ILanguageServerRegistry))] + [GenerateRequestMethods(typeof(ILanguageClient))] + internal partial class InternalInitializeParams : IInitializeParams, IRequest // This is required for generation to work correctly. + { + /// + /// The process Id of the parent process that started + /// the server. Is null if the process has not been started by another process. + /// If the parent process is not alive then the server should exit (see exit notification) its process. + /// + public long? ProcessId { get; set; } + + /// + /// Information about the client + /// + /// @since 3.15.0 + /// + [Optional] + public ClientInfo? ClientInfo { get; set; } + + /// + /// The rootPath of the workspace. Is null + /// if no folder is open. + /// + /// @deprecated in favour of rootUri. + /// + [Optional] + public string? RootPath + { + get => RootUri.GetFileSystemPath(); + set => RootUri = ( value == null ? null : DocumentUri.FromFileSystemPath(value) )!; + } + + /// + /// The rootUri of the workspace. Is null if no + /// folder is open. If both `rootPath` and `rootUri` are set + /// `rootUri` wins. + /// + public DocumentUri RootUri { get; set; } = null!; + + /// + /// User provided initialization options. + /// + public object? InitializationOptions { get; set; } + + /// + /// The capabilities provided by the client (editor or tool) + /// + public JObject Capabilities { get; set; } = null!; + + /// + /// The initial trace setting. If omitted trace is disabled ('off'). + /// + [Optional] + public InitializeTrace Trace { get; set; } = InitializeTrace.Off; + + /// + /// The workspace folders configured in the client when the server starts. + /// This property is only available if the client supports workspace folders. + /// It can be `null` if the client supports workspace folders but none are + /// configured. + /// + /// Since 3.6.0 + /// + public Container? WorkspaceFolders { get; set; } + + /// + [Optional] + public ProgressToken? WorkDoneToken { get; set; } + } + + public partial class InitializeResult + { + /// + /// The capabilities the language server provides. + /// + public ServerCapabilities Capabilities { get; set; } = null!; + + /// + /// Information about the server. + /// + /// @since 3.15.0 + /// + [Optional] + public ServerInfo? ServerInfo { get; set; } + } + + public class InitializeError + { + /// + /// Indicates whether the client should retry to send the + /// initialize request after showing the message provided + /// in the ResponseError. + /// + public bool Retry { get; set; } + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum InitializeTrace + { + [EnumMember(Value = "off")] Off, + [EnumMember(Value = "messages")] Messages, + [EnumMember(Value = "verbose")] Verbose + } + } +} diff --git a/src/Protocol/Features/General/InitializedFeature.cs b/src/Protocol/Features/General/InitializedFeature.cs new file mode 100644 index 000000000..61705aef4 --- /dev/null +++ b/src/Protocol/Features/General/InitializedFeature.cs @@ -0,0 +1,24 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Serial] + [Method(GeneralNames.Initialized, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.General", Name = "LanguageProtocolInitialized")] + [GenerateHandlerMethods(typeof(ILanguageServerRegistry))] + [GenerateRequestMethods(typeof(ILanguageClient))] + public partial class InitializedParams : IRequest + { + } + } +} diff --git a/src/Protocol/Features/General/ShutdownFeature.cs b/src/Protocol/Features/General/ShutdownFeature.cs new file mode 100644 index 000000000..c9189ab5b --- /dev/null +++ b/src/Protocol/Features/General/ShutdownFeature.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Serial] + [Method(GeneralNames.Shutdown, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.General"), GenerateHandlerMethods, GenerateRequestMethods(typeof(ILanguageClient))] + public partial class ShutdownParams : IRequest + { + public static ShutdownParams Instance { get; } = new(); + } + } + + namespace General + { + public static partial class ShutdownExtensions + { + public static Task RequestShutdown(this ILanguageClient mediator, CancellationToken cancellationToken = default) => + mediator.SendRequest(ShutdownParams.Instance, cancellationToken); + } + } +} diff --git a/src/Protocol/Features/ProgressFeature.cs b/src/Protocol/Features/ProgressFeature.cs new file mode 100644 index 000000000..476fe5a29 --- /dev/null +++ b/src/Protocol/Features/ProgressFeature.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(GeneralNames.Progress, Direction.Bidirectional)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IGeneralLanguageClient), typeof(ILanguageClient), typeof(IGeneralLanguageServer), typeof(ILanguageServer))] + public class ProgressParams : IRequest + { + public static ProgressParams Create(ProgressToken token, T value, JsonSerializer jsonSerializer) => + new ProgressParams { + Token = token, + Value = JToken.FromObject(value, jsonSerializer) + }; + + /// + /// The progress token provided by the client or server. + /// + public ProgressToken Token { get; set; } = null!; + + /// + /// The progress data. + /// + public JToken Value { get; set; } = null!; + } + + [JsonConverter(typeof(ProgressTokenConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class ProgressToken : IEquatable, IEquatable, IEquatable + { + private long? _long; + private string? _string; + + public ProgressToken(long value) + { + _long = value; + _string = null; + } + + public ProgressToken(string value) + { + _long = null; + _string = value; + } + + public bool IsLong => _long.HasValue; + + public long Long + { + get => _long ?? 0; + set { + String = null; + _long = value; + } + } + + public bool IsString => _string != null; + + public string? String + { + get => _string; + set { + _string = value; + _long = null; + } + } + + public static implicit operator ProgressToken(long value) => new ProgressToken(value); + + public static implicit operator ProgressToken(string value) => new ProgressToken(value); + + public ProgressParams Create(T value, JsonSerializer jsonSerializer) => ProgressParams.Create(this, value, jsonSerializer); + + public override bool Equals(object obj) => + obj is ProgressToken token && + Equals(token); + + public override int GetHashCode() + { + var hashCode = 1456509845; + hashCode = hashCode * -1521134295 + IsLong.GetHashCode(); + hashCode = hashCode * -1521134295 + Long.GetHashCode(); + hashCode = hashCode * -1521134295 + IsString.GetHashCode(); + if (String != null) hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(String); + return hashCode; + } + + public bool Equals(ProgressToken other) => + IsLong == other.IsLong && + Long == other.Long && + IsString == other.IsString && + String == other.String; + + public bool Equals(long other) => IsLong && Long == other; + + public bool Equals(string other) => IsString && String == other; + + private string DebuggerDisplay => IsString ? String! : IsLong ? Long.ToString() : ""; + + /// + public override string ToString() => DebuggerDisplay; + } + } + + public static partial class ProgressExtensions + { + public static IRequestProgressObservable RequestProgress( + this ILanguageProtocolProxy requestRouter, IPartialItemRequest @params, Func factory, CancellationToken cancellationToken = default + ) + { + var resultToken = new ProgressToken(Guid.NewGuid().ToString()); + @params.PartialResultToken = resultToken; + + return requestRouter.ProgressManager.MonitorUntil(@params, factory, cancellationToken); + } + + public static IRequestProgressObservable, TResponse> RequestProgress( + this ILanguageProtocolProxy requestRouter, IPartialItemsRequest @params, Func, TResponse> factory, + CancellationToken cancellationToken = default + ) + where TResponse : IEnumerable + { + var resultToken = new ProgressToken(Guid.NewGuid().ToString()); + @params.PartialResultToken = resultToken; + + return requestRouter.ProgressManager.MonitorUntil(@params, factory, cancellationToken); + } + } +} diff --git a/src/Protocol/Features/Server/SetTraceFeature.cs b/src/Protocol/Features/Server/SetTraceFeature.cs new file mode 100644 index 000000000..87eb0d7fb --- /dev/null +++ b/src/Protocol/Features/Server/SetTraceFeature.cs @@ -0,0 +1,29 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(GeneralNames.SetTrace, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Server"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IClientLanguageClient), typeof(ILanguageClient))] + public class SetTraceParams : IRequest + { + /// + /// The new value that should be assigned to the trace setting. + /// + public InitializeTrace Value { get; set; } + } + } + + namespace Server + { + } +} diff --git a/src/Protocol/Features/Window/LogMessageFeature.cs b/src/Protocol/Features/Window/LogMessageFeature.cs new file mode 100644 index 000000000..cf5b05db8 --- /dev/null +++ b/src/Protocol/Features/Window/LogMessageFeature.cs @@ -0,0 +1,63 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WindowNames.LogMessage, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + public class LogMessageParams : IRequest + { + /// + /// The message type. See {@link MessageType} + /// + public MessageType Type { get; set; } + + /// + /// The actual message + /// + public string Message { get; set; } = null!; + } + } + + namespace Window + { + public static partial class LogMessageExtensions + { + public static void Log(this ILanguageServer mediator, LogMessageParams @params) => mediator.SendNotification(@params); + + public static void LogError(this ILanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Error, Message = message }); + + public static void Log(this ILanguageServer mediator, string message) => mediator.SendNotification(new LogMessageParams { Type = MessageType.Log, Message = message }); + + public static void LogWarning(this ILanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Warning, Message = message }); + + public static void LogInfo(this ILanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Info, Message = message }); + + public static void Log(this IWindowLanguageServer mediator, LogMessageParams @params) => mediator.SendNotification(@params); + + public static void LogError(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Error, Message = message }); + + public static void Log(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Log, Message = message }); + + public static void LogWarning(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Warning, Message = message }); + + public static void LogInfo(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new LogMessageParams { Type = MessageType.Info, Message = message }); + } + } +} diff --git a/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs b/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs new file mode 100644 index 000000000..4d7f31ffd --- /dev/null +++ b/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs @@ -0,0 +1,100 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + + namespace Models + { + /// + /// Params to show a document. + /// + /// @since 3.16.0 - proposed state + /// + [Obsolete(Constants.Proposal)] + [Parallel] + [Method(WindowNames.ShowDocument, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(ShowDocumentClientCapabilities))] + public class ShowDocumentParams : IRequest + { + /// + /// The document uri to show. + /// + public DocumentUri Uri { get; set; } = null!; + + /// + /// Indicates to show the resource in an external program. + /// To show for example `https://code.visualstudio.com/` + /// in the default WEB browser set `external` to `true`. + /// + [Optional] + public bool? External { get; set; } + + /// + /// An optional property to indicate whether the editor + /// showing the document should take focus or not. + /// Clients might ignore this property if an external + /// program is started. + /// + [Optional] + public bool? TakeFocus { get; set; } + + /// + /// An optional selection range if the document is a text + /// document. Clients might ignore the property if an + /// external program is started or the file is not a text + /// file. + /// + [Optional] + public Range? Selection { get; set; } + } + + /// + /// The result of an show document request. + /// + /// @since 3.16.0 - proposed state + /// + [Obsolete(Constants.Proposal)] + public class ShowDocumentResult + { + /// + /// A boolean indicating if the show was successful. + /// + public bool Success { get; set; } + } + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to the showDocument request + /// + /// @since 3.16.0 - proposed state + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.Window), nameof(WindowClientCapabilities.ShowDocument))] + public class ShowDocumentClientCapabilities: ICapability + { + /// + /// Capabilities specific to the `MessageActionItem` type. + /// + [Optional] + public bool Support { get; set; } + } + } + + namespace Window + { + } +} diff --git a/src/Protocol/Features/Window/ShowMessageFeature.cs b/src/Protocol/Features/Window/ShowMessageFeature.cs new file mode 100644 index 000000000..6c89368f1 --- /dev/null +++ b/src/Protocol/Features/Window/ShowMessageFeature.cs @@ -0,0 +1,65 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + + + namespace Models + { + /// + /// The show message notification is sent from a server to a client to ask the client to display a particular message in the user interface. + /// + [Parallel] + [Method(WindowNames.ShowMessage, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + public class ShowMessageParams : IRequest + { + /// + /// The message type. See {@link MessageType}. + /// + public MessageType Type { get; set; } + + /// + /// The actual message. + /// + public string Message { get; set; } = null!; + } + } + + namespace Window + { + public static partial class ShowMessageExtensions + { + public static void Show(this ILanguageServer mediator, ShowMessageParams @params) => mediator.SendNotification(@params); + + public static void ShowError(this ILanguageServer mediator, string message) => mediator.SendNotification(new ShowMessageParams { Type = MessageType.Error, Message = message }); + + public static void Show(this ILanguageServer mediator, string message) => mediator.SendNotification(new ShowMessageParams { Type = MessageType.Log, Message = message }); + + public static void ShowWarning(this ILanguageServer mediator, string message) => + mediator.SendNotification(new ShowMessageParams { Type = MessageType.Warning, Message = message }); + + public static void ShowInfo(this ILanguageServer mediator, string message) => mediator.SendNotification(new ShowMessageParams { Type = MessageType.Info, Message = message }); + + public static void Show(this IWindowLanguageServer mediator, ShowMessageParams @params) => mediator.SendNotification(@params); + + public static void ShowError(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new ShowMessageParams { Type = MessageType.Error, Message = message }); + + public static void Show(this IWindowLanguageServer mediator, string message) => mediator.SendNotification(new ShowMessageParams { Type = MessageType.Log, Message = message }); + + public static void ShowWarning(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new ShowMessageParams { Type = MessageType.Warning, Message = message }); + + public static void ShowInfo(this IWindowLanguageServer mediator, string message) => + mediator.SendNotification(new ShowMessageParams { Type = MessageType.Info, Message = message }); + } + } +} diff --git a/src/Protocol/Features/Window/ShowMessageRequestFeature.cs b/src/Protocol/Features/Window/ShowMessageRequestFeature.cs new file mode 100644 index 000000000..f18d8faf7 --- /dev/null +++ b/src/Protocol/Features/Window/ShowMessageRequestFeature.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + + + namespace Models + { + /// + /// The show message request is sent from a server to a client to ask the client to display a particular message in the user interface. In addition to the show message notification + /// the request allows to pass actions and to wait for an answer from the client. + /// + [Parallel] + [Method(WindowNames.ShowMessageRequest, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + public class ShowMessageRequestParams : IRequest + { + /// + /// The message type. See {@link MessageType} + /// + public MessageType Type { get; set; } + + /// + /// The actual message + /// + public string Message { get; set; } = null!; + + /// + /// The message action items to present. + /// + [Optional] + public Container? Actions { get; set; } + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class MessageActionItem + { + /// + /// A short title like 'Retry', 'Open Log' etc. + /// + public string Title { get; set; } = null!; + + /// + /// Extension data that may contain additional properties based on + /// + [JsonExtensionData] + public IDictionary ExtensionData { get; set; } = new Dictionary(); + + private string DebuggerDisplay => Title; + + /// + public override string ToString() => DebuggerDisplay; + } + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to the showMessage request + /// + /// @since 3.16.0 - proposed state + /// + [Obsolete(Constants.Proposal)] + [CapabilityKey(nameof(ClientCapabilities.Window), nameof(WindowClientCapabilities.ShowMessage))] + public class ShowMessageRequestClientCapabilities + { + /// + /// Capabilities specific to the `MessageActionItem` type. + /// + [Optional] + public ShowMessageRequestMessageActionItemClientCapabilities? MessageActionItem { get; set; } + } + + [Obsolete(Constants.Proposal)] + public class ShowMessageRequestMessageActionItemClientCapabilities + { + /// + /// Whether the client supports additional attribues which + /// are preserved and send back to the server in the + /// request's response. + /// + [Optional] + public bool AdditionalPropertiesSupport { get; set; } + } + } + + namespace Window + { + + } +} diff --git a/src/Protocol/Window/ITelemetryEventHandler.cs b/src/Protocol/Features/Window/TelemetryEventFeature.cs similarity index 51% rename from src/Protocol/Window/ITelemetryEventHandler.cs rename to src/Protocol/Features/Window/TelemetryEventFeature.cs index c05966837..484c99cf7 100644 --- a/src/Protocol/Window/ITelemetryEventHandler.cs +++ b/src/Protocol/Features/Window/TelemetryEventFeature.cs @@ -1,13 +1,32 @@ +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol { + + namespace Models + { + [Parallel] + [Method(WindowNames.TelemetryEvent, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + public class TelemetryEventParams : IRequest + { + [JsonExtensionData] public IDictionary Data { get; set; } = new Dictionary(); + } + } + + namespace Window + { + } [Parallel] [Method(WindowNames.TelemetryEvent, Direction.ServerToClient)] [GenerateHandlerMethods] diff --git a/src/Protocol/Features/Window/WorkDoneProgressFeature.cs b/src/Protocol/Features/Window/WorkDoneProgressFeature.cs new file mode 100644 index 000000000..a6eac17ef --- /dev/null +++ b/src/Protocol/Features/Window/WorkDoneProgressFeature.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WindowNames.WorkDoneProgressCreate, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] + public partial class WorkDoneProgressCreateParams : IRequest + { + /// + /// The token to be used to report progress. + /// + public ProgressToken? Token { get; set; } + } + + [Parallel] + [Method(WindowNames.WorkDoneProgressCancel, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWindowLanguageClient), typeof(ILanguageClient))] + public partial class WorkDoneProgressCancelParams : IRequest + { + /// + /// The token to be used to report progress. + /// + public ProgressToken? Token { get; set; } + } + + + public interface IWorkDoneProgressParams + { + /// + /// An optional token that a server can use to report work done progress. + /// + [Optional] + ProgressToken? WorkDoneToken { get; set; } + } + + public interface IWorkDoneProgressOptions + { + [Optional] bool WorkDoneProgress { get; set; } + } + + public abstract class WorkDoneProgress + { + public WorkDoneProgress(WorkDoneProgressKind kind) => Kind = kind; + + public WorkDoneProgressKind Kind { get; } + + /// + /// Optional, a final message indicating to for example indicate the outcome + /// of the operation. + /// + [Optional] + public string? Message { get; set; } + } + + [JsonConverter(typeof(EnumLikeStringConverter))] + public readonly struct WorkDoneProgressKind : IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = + new Lazy>( + () => { + return typeof(WorkDoneProgressKind) + .GetFields(BindingFlags.Static | BindingFlags.Public) + .Select(z => z.GetValue(null)) + .Cast() + .ToArray(); + } + ); + + public static IEnumerable Defaults => _defaults.Value; + + public static WorkDoneProgressKind Begin = new WorkDoneProgressKind("begin"); + public static WorkDoneProgressKind End = new WorkDoneProgressKind("end"); + public static WorkDoneProgressKind Report = new WorkDoneProgressKind("report"); + + private readonly string _value; + + public WorkDoneProgressKind(string modifier) => _value = modifier; + + public static implicit operator WorkDoneProgressKind(string kind) => new WorkDoneProgressKind(kind); + + public static implicit operator string(WorkDoneProgressKind kind) => kind._value; + + public override string ToString() => _value; + public bool Equals(WorkDoneProgressKind other) => _value == other._value; + + public override bool Equals(object obj) => obj is WorkDoneProgressKind other && Equals(other); + + public override int GetHashCode() => _value.GetHashCode(); + + public static bool operator ==(WorkDoneProgressKind left, WorkDoneProgressKind right) => left.Equals(right); + + public static bool operator !=(WorkDoneProgressKind left, WorkDoneProgressKind right) => !left.Equals(right); + } + + /// + /// To start progress reporting a `$/progress` notification with the following payload must be sent + /// + public class WorkDoneProgressBegin : WorkDoneProgress + { + public WorkDoneProgressBegin() : base(WorkDoneProgressKind.Begin) + { + } + + /// + /// Mandatory title of the progress operation. Used to briefly inform about + /// the kind of operation being performed. + /// + /// Examples: "Indexing" or "Linking dependencies". + /// + public string Title { get; set; } = null!; + + /// + /// Controls if a cancel button should show to allow the user to cancel the + /// long running operation. Clients that don't support cancellation are allowed + /// to ignore the setting. + /// + [Optional] + public bool Cancellable { get; set; } + + /// + /// Optional progress percentage to display (value 100 is considered 100%). + /// If not provided infinite progress is assumed and clients are allowed + /// to ignore the `percentage` value in subsequent in report notifications. + /// + /// The value should be steadily rising. Clients are free to ignore values + /// that are not following this rule. + /// + /// + /// TODO: Change this (breaking) + /// in the LSP spec + /// + [Optional] + public double? Percentage { get; set; } + } + + /// + /// Signaling the end of a progress reporting is done using the following payload + /// + public class WorkDoneProgressEnd : WorkDoneProgress + { + public WorkDoneProgressEnd() : base(WorkDoneProgressKind.End) + { + } + } + + public class WorkDoneProgressOptions : IWorkDoneProgressOptions + { + [Optional] public bool WorkDoneProgress { get; set; } + } + + /// + /// Reporting progress is done using the following payload + /// + public class WorkDoneProgressReport : WorkDoneProgress + { + public WorkDoneProgressReport() : base(WorkDoneProgressKind.Report) + { + } + + /// + /// Controls enablement state of a cancel button. This property is only valid if a cancel + /// button got requested in the `WorkDoneProgressStart` payload. + /// + /// Clients that don't support cancellation or don't support control the button's + /// enablement state are allowed to ignore the setting. + /// + [Optional] + public bool Cancellable { get; set; } + + /// + /// Optional progress percentage to display (value 100 is considered 100%). + /// If not provided infinite progress is assumed and clients are allowed + /// to ignore the `percentage` value in subsequent in report notifications. + /// + /// The value should be steadily rising. Clients are free to ignore values + /// that are not following this rule. + /// + /// + /// TODO: Change this (breaking) + /// in the LSP spec + /// + [Optional] + public double? Percentage { get; set; } + } + } + + namespace Window + { + public static partial class WorkDoneProgressExtensions + { + public static void SendWorkDoneProgressCancel(this IWindowLanguageClient mediator, IWorkDoneProgressParams @params) => + mediator.SendNotification(WindowNames.WorkDoneProgressCancel, new WorkDoneProgressCancelParams { Token = @params.WorkDoneToken }); + + public static void SendWorkDoneProgressCancel(this IWindowLanguageClient mediator, ProgressToken token) => + mediator.SendNotification(WindowNames.WorkDoneProgressCancel, new WorkDoneProgressCancelParams { Token = token }); + } + } +} diff --git a/src/Protocol/Features/Workspace/ApplyEditFeature.cs b/src/Protocol/Features/Workspace/ApplyEditFeature.cs new file mode 100644 index 000000000..8fb397f3f --- /dev/null +++ b/src/Protocol/Features/Workspace/ApplyEditFeature.cs @@ -0,0 +1,60 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.ApplyEdit, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + public partial class ApplyWorkspaceEditParams : IRequest + { + /// + /// An optional label of the workspace edit. This label is + /// presented in the user interface for example on an undo + /// stack to undo the workspace edit. + /// + [Optional] + public string? Label { get; set; } + + /// + /// The edits to apply. + /// + public WorkspaceEdit Edit { get; set; } = null!; + } + + public partial class ApplyWorkspaceEditResponse + { + /// + /// Indicates whether the edit was applied or not. + /// + public bool Applied { get; set; } + + /// + /// An optional textual description for why the edit was not applied. + /// This may be used may be used by the server for diagnostic + /// logging or to provide a suitable error for a request that + /// triggered the edit. + /// + [Optional] + public string? FailureReason { get; set; } + + /// + /// Depending on the client's failure handling strategy `failedChange` + /// might contain the index of the change that failed. This property is + /// only available if the client signals a `failureHandlingStrategy` + /// in its client capabilities. + /// + [Optional] + public int? FailedChange { get; set; } + } + } +} diff --git a/src/Protocol/Features/Workspace/ConfigurationFeature.cs b/src/Protocol/Features/Workspace/ConfigurationFeature.cs new file mode 100644 index 000000000..7519ada98 --- /dev/null +++ b/src/Protocol/Features/Workspace/ConfigurationFeature.cs @@ -0,0 +1,58 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.Configuration, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + public partial class ConfigurationParams : IRequest> + { + public Container Items { get; set; } = null!; + } + + public class ConfigurationItem : IEquatable + { + [Optional] public DocumentUri? ScopeUri { get; set; } + [Optional] public string? Section { get; set; } + + public bool Equals(ConfigurationItem? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(ScopeUri, other.ScopeUri) && Section == other.Section; + } + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((ConfigurationItem)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ( ( ScopeUri is not null ? ScopeUri.GetHashCode() : 0 ) * 397 ) ^ ( Section is not 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); + } + } +} diff --git a/src/Protocol/Features/Workspace/DidChangeConfigurationFeature.cs b/src/Protocol/Features/Workspace/DidChangeConfigurationFeature.cs new file mode 100644 index 000000000..3891e0110 --- /dev/null +++ b/src/Protocol/Features/Workspace/DidChangeConfigurationFeature.cs @@ -0,0 +1,37 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.DidChangeConfiguration, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + [Capability(typeof(DidChangeConfigurationCapability))] + public partial class DidChangeConfigurationParams : IRequest + { + /// + /// The actual changed settings + /// + public JToken? Settings { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Configuration))] + public partial class DidChangeConfigurationCapability : DynamicCapability + { + } + } +} diff --git a/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs b/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs new file mode 100644 index 000000000..64a7f3122 --- /dev/null +++ b/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs @@ -0,0 +1,48 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.DidChangeWatchedFiles, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(DidChangeWatchedFilesRegistrationOptions)), Capability(typeof(DidChangeWatchedFilesCapability))] + public partial class DidChangeWatchedFilesParams : IRequest + { + /// + /// The actual file events. + /// + public Container Changes { get; set; } = null!; + } + + [GenerateRegistrationOptions] + public partial class DidChangeWatchedFilesRegistrationOptions + { + /// + /// The watchers to register. + /// + [Optional] + public Container? Watchers { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.DidChangeWatchedFiles))] + public partial class DidChangeWatchedFilesCapability : DynamicCapability + { + } + } +} diff --git a/src/Protocol/Features/Workspace/DidChangeWorkspaceFoldersFeature.cs b/src/Protocol/Features/Workspace/DidChangeWorkspaceFoldersFeature.cs new file mode 100644 index 000000000..1a8e2b772 --- /dev/null +++ b/src/Protocol/Features/Workspace/DidChangeWorkspaceFoldersFeature.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.DidChangeWorkspaceFolders, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + public partial class DidChangeWorkspaceFoldersParams : IRequest + { + /// + /// The actual workspace folder change event. + /// + public WorkspaceFoldersChangeEvent Event { get; set; } = null!; + } + } +} diff --git a/src/Protocol/Features/Workspace/ExecuteCommandFeature.cs b/src/Protocol/Features/Workspace/ExecuteCommandFeature.cs new file mode 100644 index 000000000..8f686bf2a --- /dev/null +++ b/src/Protocol/Features/Workspace/ExecuteCommandFeature.cs @@ -0,0 +1,513 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using ISerializer = OmniSharp.Extensions.JsonRpc.ISerializer; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Serial] + [Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(ExecuteCommandRegistrationOptions)), Capability(typeof(ExecuteCommandCapability))] + public partial class ExecuteCommandParams : IJsonRpcRequest, IWorkDoneProgressParams, IExecuteCommandParams + { + /// + /// The identifier of the actual command handler. + /// + public string Command { get; set; } = null!; + + /// + /// Arguments that the command should be invoked with. + /// + [Optional] + public JArray? Arguments { get; set; } + } + + /// + /// Execute command registration options. + /// + [GenerateRegistrationOptions(nameof(ServerCapabilities.ExecuteCommandProvider))] + [RegistrationOptionsConverter(typeof(ExecuteCommandRegistrationOptionsConverter))] + public partial class ExecuteCommandRegistrationOptions : IWorkDoneProgressOptions + { + /// + /// The commands to be executed on the server + /// + public Container Commands { get; set; } = null!; + + class ExecuteCommandRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public ExecuteCommandRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.ExecuteCommandProvider)) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(ExecuteCommandRegistrationOptions source) + { + var allRegistrationOptions = _handlersManager.Descriptors + .OfType() + .Where(z => z.HasRegistration) + .Select(z => z.RegistrationOptions) + .OfType() + .ToArray(); + return new () { + Commands = allRegistrationOptions.SelectMany(z => z.Commands).ToArray(), +// WorkDoneProgress = allRegistrationOptions.Any(x => x.WorkDoneProgress) + }; + } + } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.ExecuteCommand))] + public class ExecuteCommandCapability : DynamicCapability, ConnectedCapability + { + } + } + + namespace Workspace + { + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, cancellationToken); + } + + public abstract Task Handle(T arg1, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + T2 arg2 = default; + if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, arg2!, cancellationToken); + } + + public abstract Task Handle(T arg1, T2 arg2, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + T2 arg2 = default; + if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); + T3 arg3 = default; + if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, arg2!, arg3!, cancellationToken); + } + + public abstract Task Handle(T arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + T2 arg2 = default; + if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); + T3 arg3 = default; + if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); + T4 arg4 = default; + if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, arg2!, arg3!, arg4!, cancellationToken); + } + + public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + T2 arg2 = default; + if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); + T3 arg3 = default; + if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); + T4 arg4 = default; + if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); + T5 arg5 = default; + if (args.Count > 4) arg5 = args[4].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, arg2!, arg3!, arg4!, arg5!, cancellationToken); + } + + public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandlerBase + { + private readonly string _command; + private readonly ISerializer _serializer; + + public ExecuteCommandHandlerBase(string command, ISerializer serializer) + { + _command = command; + _serializer = serializer; + } + + public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) + { + var args = request.Arguments ?? new JArray(); + T arg1 = default; + if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); + T2 arg2 = default; + if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); + T3 arg3 = default; + if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); + T4 arg4 = default; + if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); + T5 arg5 = default; + if (args.Count > 4) arg5 = args[4].ToObject(_serializer.JsonSerializer); + T6 arg6 = default; + if (args.Count > 5) arg6 = args[5].ToObject(_serializer.JsonSerializer); + return Handle(arg1!, arg2!, arg3!, arg4!, arg5!, arg6!, cancellationToken); + } + + public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, CancellationToken cancellationToken); + + protected internal override ExecuteCommandRegistrationOptions CreateRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) => + new ExecuteCommandRegistrationOptions { Commands = new Container(_command) }; + } + + public static partial class ExecuteCommandExtensions + { + public static Task ExecuteCommand(this IWorkspaceLanguageClient mediator, Command @params, CancellationToken cancellationToken = default) + => mediator.SendRequest(new ExecuteCommandParams { Arguments = @params.Arguments, Command = @params.Name }, cancellationToken); + + public static Task ExecuteCommand(this ILanguageClient mediator, Command @params, CancellationToken cancellationToken = default) + => mediator.SendRequest(new ExecuteCommandParams { Arguments = @params.Arguments, Command = @params.Name }, cancellationToken); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, capability, token) => handler(arg1, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, capability, token) => handler(arg1), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => + _handler = handler; + + public override async Task Handle(T arg1, CancellationToken cancellationToken) + { + await _handler(arg1, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, capability, token) => handler(arg1, arg2, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, capability, token) => handler(arg1, arg2), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => + _handler = handler; + + public override async Task Handle(T arg1, T2 arg2, CancellationToken cancellationToken) + { + await _handler(arg1, arg2, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, capability, token) => handler(arg1, arg2, arg3, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, capability, token) => handler(arg1, arg2, arg3), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => + _handler = handler; + + public override async Task Handle(T arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) + { + await _handler(arg1, arg2, arg3, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, capability, token) => handler(arg1, arg2, arg3, arg4, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, capability, token) => handler(arg1, arg2, arg3, arg4), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler( + string command, Func handler, ISerializer serializer + ) : base(command, serializer) => + _handler = handler; + + public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cancellationToken) + { + await _handler(arg1, arg2, arg3, arg4, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, arg5, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, arg5, capability, token) => handler(arg1, arg2, arg3, arg4, arg5), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler(string command, Func handler, ISerializer serializer) : + base(command, serializer) => _handler = handler; + + public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cancellationToken) + { + await _handler(arg1, arg2, arg3, arg4, arg5, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, arg5, arg6, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, arg6, token), + _.GetRequiredService() + ) + ); + + public static ILanguageServerRegistry OnExecuteCommand( + this ILanguageServerRegistry registry, string command, Func handler + ) => + registry.AddHandler( + _ => new Handler( + command, + (arg1, arg2, arg3, arg4, arg5, arg6, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, arg6), + _.GetRequiredService() + ) + ); + + private class Handler : ExecuteCommandHandlerBase + { + private readonly Func _handler; + + public Handler(string command, Func handler, ISerializer serializer) : base( + command, serializer + ) => _handler = handler; + + public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, CancellationToken cancellationToken) + { + await _handler(arg1, arg2, arg3, arg4, arg5, arg6, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + } + } +} diff --git a/src/Protocol/Features/Workspace/Proposals/CodeLensRefreshFeature.cs b/src/Protocol/Features/Workspace/Proposals/CodeLensRefreshFeature.cs new file mode 100644 index 000000000..cb4fff1f7 --- /dev/null +++ b/src/Protocol/Features/Workspace/Proposals/CodeLensRefreshFeature.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + + namespace Workspace.Proposals + { + }} + diff --git a/src/Protocol/Features/Workspace/Proposals/SemanticTokensRefreshFeature.cs b/src/Protocol/Features/Workspace/Proposals/SemanticTokensRefreshFeature.cs new file mode 100644 index 000000000..5902b1147 --- /dev/null +++ b/src/Protocol/Features/Workspace/Proposals/SemanticTokensRefreshFeature.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models.Proposals + { + } + + namespace Workspace.Proposals + { + + } + + namespace Client.Capabilities + { + } +} diff --git a/src/Protocol/Features/Workspace/WorkspaceFoldersFeature.cs b/src/Protocol/Features/Workspace/WorkspaceFoldersFeature.cs new file mode 100644 index 000000000..c5c4d8739 --- /dev/null +++ b/src/Protocol/Features/Workspace/WorkspaceFoldersFeature.cs @@ -0,0 +1,95 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + [Parallel] + [Method(WorkspaceNames.WorkspaceFolders, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace", Name = "WorkspaceFolders"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + public partial class WorkspaceFolderParams : IRequest?> + { + public static WorkspaceFolderParams Instance = new WorkspaceFolderParams(); + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial class WorkspaceFolder : IEquatable + { + /// + /// The associated URI for this workspace folder. + /// + public DocumentUri Uri { get; set; } = null!; + + /// + /// The name of the workspace folder. Defaults to the uri's basename. + /// + public string Name { get; set; } = null!; + + public bool Equals(WorkspaceFolder? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(Uri, other.Uri) && Name == other.Name; + } + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((WorkspaceFolder) obj); + } + + public override int GetHashCode() + { + unchecked + { + return ( ( Uri is not null ? Uri.GetHashCode() : 0 ) * 397 ) ^ ( Name != null ? Name.GetHashCode() : 0 ); + } + } + + public static bool operator ==(WorkspaceFolder left, WorkspaceFolder right) => Equals(left, right); + + public static bool operator !=(WorkspaceFolder left, WorkspaceFolder right) => !Equals(left, right); + + private string DebuggerDisplay => $"{Name} ({Uri})"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [GenerateRegistrationOptions] + public partial class WorkspaceFolderRegistrationOptions : IWorkspaceFolderOptions + { + public bool Supported { get; set; } + public BooleanString ChangeNotifications { get; set; } + } + + /// + /// The workspace folder change event. + /// + public partial class WorkspaceFoldersChangeEvent + { + /// + /// The array of added workspace folders + /// + public Container Added { get; set; } = new Container(); + + /// + /// The array of the removed workspace folders + /// + public Container Removed { get; set; } = new Container(); + } + } +} diff --git a/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs b/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs new file mode 100644 index 000000000..c25a3812e --- /dev/null +++ b/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs @@ -0,0 +1,106 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + namespace Models + { + /// + /// The parameters of a Workspace Symbol Request. + /// + [Parallel] + [Method(WorkspaceNames.WorkspaceSymbol, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace", Name = "WorkspaceSymbols"), GenerateHandlerMethods, GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(WorkspaceSymbolRegistrationOptions)), Capability(typeof(WorkspaceSymbolCapability))] + public partial class WorkspaceSymbolParams : IPartialItemsRequest?, SymbolInformation>, IWorkDoneProgressParams + { + /// + /// A non-empty query string + /// + public string Query { get; set; } = null!; + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class WorkspaceSymbolRegistrationOptions : IWorkDoneProgressOptions { } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial class SymbolInformation + { + /// + /// The name of this symbol. + /// + public string Name { get; set; } = null!; + + /// + /// The kind of this symbol. + /// + public SymbolKind Kind { get; set; } + + /// + /// Tags for this completion item. + /// + /// @since 3.16.0 - Proposed state + /// + [Obsolete(Constants.Proposal)] + [Optional] + public Container? Tags { get; set; } + + /// + /// Indicates if this item is deprecated. + /// + [Optional] + public bool Deprecated { get; set; } + + /// + /// The location of this symbol. + /// + public Location Location { get; set; } = null!; + + /// + /// The name of the symbol containing this symbol. + /// + [Optional] + public string? ContainerName { get; set; } + + private string DebuggerDisplay => $"[{Kind}@{Location}] {Name}"; + + /// + public override string ToString() => DebuggerDisplay; + } + } + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Symbol))] + public partial class WorkspaceSymbolCapability : DynamicCapability//, ConnectedCapability + { + /// + /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. + /// + [Optional] + public SymbolKindCapabilityOptions? SymbolKind { get; set; } + + /// + /// The client supports tags on `SymbolInformation`.Tags are supported on + /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. + /// Clients supporting tags have to handle unknown tags gracefully. + /// + /// @since 3.16.0 + /// + [Obsolete(Constants.Proposal)] + [Optional] + public Supports TagSupport { get; set; } + } + } +} diff --git a/src/Protocol/General/IExitHandler.cs b/src/Protocol/General/IExitHandler.cs deleted file mode 100644 index ad15ed84f..000000000 --- a/src/Protocol/General/IExitHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.General -{ - [Serial] - [Method(GeneralNames.Exit, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ILanguageClient))] - public interface IExitHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ExitHandler : IExitHandler - { - public virtual async Task Handle(ExitParams request, CancellationToken cancellationToken) - { - await Handle(cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected abstract Task Handle(CancellationToken cancellationToken); - } - - public static partial class ExitExtensions - { - public static void SendExit(this ILanguageClient mediator) => mediator.SendNotification(ExitParams.Instance); - } -} diff --git a/src/Protocol/General/ILanguageProtocolInitializeHandler.cs b/src/Protocol/General/ILanguageProtocolInitializeHandler.cs deleted file mode 100644 index 63bdf3bb9..000000000 --- a/src/Protocol/General/ILanguageProtocolInitializeHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.General -{ - [Serial] - [Method(GeneralNames.Initialize, Direction.ClientToServer)] - [GenerateHandlerMethods(typeof(ILanguageServerRegistry), MethodName = "OnLanguageProtocolInitialize")] - [GenerateRequestMethods(typeof(ILanguageClient), MethodName = "RequestLanguageProtocolInitialize")] - internal interface ILanguageProtocolInitializeHandler : IJsonRpcRequestHandler - { - } - - internal abstract class LanguageProtocolInitializeHandler : ILanguageProtocolInitializeHandler - { - public abstract Task Handle(InternalInitializeParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/General/ILanguageProtocolInitializedHandler.cs b/src/Protocol/General/ILanguageProtocolInitializedHandler.cs deleted file mode 100644 index 18a3f1fd5..000000000 --- a/src/Protocol/General/ILanguageProtocolInitializedHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.General -{ - [Serial] - [Method(GeneralNames.Initialized, Direction.ClientToServer)] - [GenerateHandlerMethods(typeof(ILanguageServerRegistry), MethodName = "OnLanguageProtocolInitialized")] - [GenerateRequestMethods(typeof(ILanguageClient), MethodName = "SendLanguageProtocolInitialized")] - internal interface ILanguageProtocolInitializedHandler : IJsonRpcNotificationHandler - { - } - - internal abstract class LanguageProtocolInitializedHandler : ILanguageProtocolInitializedHandler - { - public abstract Task Handle(InitializedParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/General/IShutdownHandler.cs b/src/Protocol/General/IShutdownHandler.cs deleted file mode 100644 index 43aba3296..000000000 --- a/src/Protocol/General/IShutdownHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.General -{ - [Serial] - [Method(GeneralNames.Shutdown, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IShutdownHandler : IJsonRpcRequestHandler - { - } - - public abstract class ShutdownHandler : IShutdownHandler - { - public virtual async Task Handle(ShutdownParams request, CancellationToken cancellationToken) - { - await Handle(cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected abstract Task Handle(CancellationToken cancellationToken); - } - - public static partial class ShutdownExtensions - { - public static Task RequestShutdown(this ILanguageClient mediator, CancellationToken cancellationToken = default) => - mediator.SendRequest(ShutdownParams.Instance, cancellationToken); - } -} diff --git a/src/Protocol/Generation/CapabilityAttribute.cs b/src/Protocol/Generation/CapabilityAttribute.cs new file mode 100644 index 000000000..a1a77c049 --- /dev/null +++ b/src/Protocol/Generation/CapabilityAttribute.cs @@ -0,0 +1,20 @@ +using System; +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Used by source generation to identify the capability type to use + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class CapabilityAttribute : Attribute + { + public Type CapabilityType { get; } + + public CapabilityAttribute(Type capabilityType) + { + CapabilityType = capabilityType; + } + } +} diff --git a/src/Protocol/Generation/GenerateContainerAttribute.cs b/src/Protocol/Generation/GenerateContainerAttribute.cs new file mode 100644 index 000000000..cd4edd67c --- /dev/null +++ b/src/Protocol/Generation/GenerateContainerAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Diagnostics; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Allows generating a typed container counterpart to any model that implements + /// + /// + /// Efforts will be made to make this available for consumers once source generators land + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] + [Conditional("CodeGeneration")] + public class GenerateContainerAttribute : Attribute + { + public GenerateContainerAttribute(string? className = null) + { + + } + } +} diff --git a/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs b/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs new file mode 100644 index 000000000..ff2af76d4 --- /dev/null +++ b/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Defines a converter that is used for converting from dynamic to static + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class GenerateRegistrationOptionsAttribute : Attribute + { + public string? ServerCapabilitiesKey { get; } + public bool SupportsWorkDoneProgress { get; init; } + public bool SupportsStaticRegistrationOptions { get; init; } + public bool SupportsDocumentSelector { get; init; } + public Type? Converter { get; init; } + + public bool SupportsTextDocument + { + get => SupportsDocumentSelector; + init => SupportsDocumentSelector = value; + } + + public GenerateRegistrationOptionsAttribute(string? serverCapabilitiesKey = null) + { + ServerCapabilitiesKey = serverCapabilitiesKey; + } + } +} diff --git a/src/Protocol/Generation/GenerateTypedDataAttribute.cs b/src/Protocol/Generation/GenerateTypedDataAttribute.cs new file mode 100644 index 000000000..c016fe25f --- /dev/null +++ b/src/Protocol/Generation/GenerateTypedDataAttribute.cs @@ -0,0 +1,18 @@ +using System; +using System.Diagnostics; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Allows generating a typed counterpart to any model that implements + /// + /// + /// Efforts will be made to make this available for consumers once source generators land + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class GenerateTypedDataAttribute : Attribute + { + } +} diff --git a/src/Protocol/Generation/RegistrationOptionsAttribute.cs b/src/Protocol/Generation/RegistrationOptionsAttribute.cs new file mode 100644 index 000000000..e56dde5e7 --- /dev/null +++ b/src/Protocol/Generation/RegistrationOptionsAttribute.cs @@ -0,0 +1,20 @@ +using System; +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Used by source generation to identify the registration options type to use + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class RegistrationOptionsAttribute : Attribute + { + public Type RegistrationOptionsType { get; } + + public RegistrationOptionsAttribute(Type registrationOptionsType) + { + RegistrationOptionsType = registrationOptionsType; + } + } +} diff --git a/src/Protocol/Generation/ResolverAttribute.cs b/src/Protocol/Generation/ResolverAttribute.cs new file mode 100644 index 000000000..c2dc3458a --- /dev/null +++ b/src/Protocol/Generation/ResolverAttribute.cs @@ -0,0 +1,20 @@ +using System; +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Generation +{ + /// + /// Used by source generation to identify the resolver of a given type + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("CodeGeneration")] + public class ResolverAttribute : Attribute + { + public Type ResolverType { get; } + + public ResolverAttribute(Type resolverType) + { + ResolverType = resolverType; + } + } +} diff --git a/src/Protocol/ICapability.cs b/src/Protocol/ICapability.cs index d9a4db990..ed6dc96e4 100644 --- a/src/Protocol/ICapability.cs +++ b/src/Protocol/ICapability.cs @@ -1,6 +1,6 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { - public interface ICapability + public interface ICapability { void SetCapability(TCapability capability); } diff --git a/src/Protocol/IProgressHandler.cs b/src/Protocol/IProgressHandler.cs deleted file mode 100644 index 30bc225d4..000000000 --- a/src/Protocol/IProgressHandler.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Progress; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol -{ - [Parallel] - [Method(GeneralNames.Progress, Direction.Bidirectional)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IGeneralLanguageClient), typeof(ILanguageClient), typeof(IGeneralLanguageServer), typeof(ILanguageServer))] - public interface IProgressHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ProgressHandler : IProgressHandler - { - public abstract Task Handle(ProgressParams request, CancellationToken cancellationToken); - } - - public static partial class ProgressExtensions - { - public static IRequestProgressObservable RequestProgress( - this ILanguageProtocolProxy requestRouter, IPartialItemRequest @params, Func factory, CancellationToken cancellationToken = default - ) - { - var resultToken = new ProgressToken(Guid.NewGuid().ToString()); - @params.PartialResultToken = resultToken; - - return requestRouter.ProgressManager.MonitorUntil(@params, factory, cancellationToken); - } - - public static IRequestProgressObservable, TResponse> RequestProgress( - this ILanguageProtocolProxy requestRouter, IPartialItemsRequest @params, Func, TResponse> factory, - CancellationToken cancellationToken = default - ) - where TResponse : IEnumerable - { - var resultToken = new ProgressToken(Guid.NewGuid().ToString()); - @params.PartialResultToken = resultToken; - - return requestRouter.ProgressManager.MonitorUntil(@params, factory, cancellationToken); - } - } -} diff --git a/src/Protocol/IRegistration.cs b/src/Protocol/IRegistration.cs index 526464009..5ae893efb 100644 --- a/src/Protocol/IRegistration.cs +++ b/src/Protocol/IRegistration.cs @@ -1,11 +1,26 @@ +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; + namespace OmniSharp.Extensions.LanguageServer.Protocol { + public interface IRegistration + where TOptions : class + where TCapability : ICapability + { + TOptions GetRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities); + } + public interface IRegistration - where TOptions : class?, new() + where TOptions : class { - TOptions GetRegistrationOptions(); + TOptions GetRegistrationOptions(ClientCapabilities clientCapabilities); } + public delegate TOptions RegistrationOptionsDelegate(ClientCapabilities clientCapabilities) + where TOptions : class; + public delegate TOptions RegistrationOptionsDelegate(TCapability capability, ClientCapabilities clientCapabilities) + where TOptions : class + where TCapability : ICapability; + /// /// Identifies a handler that does not participate in dynamic registration. /// diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.cs index eba50a456..704c74b62 100644 --- a/src/Protocol/LanguageProtocolDelegatingHandlers.cs +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; @@ -15,53 +16,39 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { public static class LanguageProtocolDelegatingHandlers { - public sealed class Request : + public sealed class Request : + AbstractHandlers.Base, IJsonRpcRequestHandler, - IRegistration, ICapability, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() where TCapability : ICapability { private readonly Func> _handler; - private readonly TRegistrationOptions _registrationOptions; - private TCapability _capability = default!; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public Request(Func> handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (a, c, ct) => handler(a, c), registrationOptions) - { - } - - public Request(Func> handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) - { - } - - public Request(Guid id, Func> handler, TRegistrationOptions registrationOptions) : - this(id, (a, c, ct) => handler(a, c), registrationOptions) + public Request(Guid id, Func> handler, RegistrationOptionsDelegate registrationOptionsFactory) { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; } - public Request(Guid id, Func> handler, TRegistrationOptions registrationOptions) + public Request(Func> handler, RegistrationOptionsDelegate registrationOptionsFactory) : + this(Guid.Empty, handler, registrationOptionsFactory) { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; } - Task IRequestHandler. - Handle(TParams request, CancellationToken cancellationToken) => - _handler(request, _capability, cancellationToken); + Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => + _handler(request, Capability, cancellationToken); - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } - public sealed class CanBeResolved : - IRegistration, - ICapability, + public sealed class CanBeResolved : + AbstractHandlers.Base, ICanBeResolvedHandler, ICanBeIdentifiedHandler where TItem : ICanBeResolved, IRequest @@ -69,176 +56,133 @@ public sealed class CanBeResolved : where TCapability : ICapability { private readonly Func> _resolveHandler; - private readonly TRegistrationOptions _registrationOptions; - private TCapability _capability = default!; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public CanBeResolved(Guid id, Func> resolveHandler, TRegistrationOptions registrationOptions) : - this(id, (a, c, ct) => resolveHandler(a, c), registrationOptions) - { - } - - public CanBeResolved(Guid id, Func> resolveHandler, TRegistrationOptions registrationOptions) + public CanBeResolved(Guid id, Func> resolveHandler, RegistrationOptionsDelegate registrationOptionsFactory) { _resolveHandler = resolveHandler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; _id = id; } - Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, _capability, cancellationToken); + Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, Capability, cancellationToken); - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } public sealed class CanBeResolved : - IRegistration, + AbstractHandlers.Base, ICanBeResolvedHandler, ICanBeIdentifiedHandler where TItem : ICanBeResolved, IRequest where TRegistrationOptions : class, new() { private readonly Func> _resolveHandler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public CanBeResolved(Guid id, Func> resolveHandler, TRegistrationOptions registrationOptions) : - this(id, (a, c) => resolveHandler(a), registrationOptions) - { - } - - public CanBeResolved(Guid id, Func> resolveHandler, TRegistrationOptions registrationOptions) + public CanBeResolved(Guid id, Func> resolveHandler, RegistrationOptionsDelegate registrationOptionsFactory) { _id = id; _resolveHandler = resolveHandler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; } Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, cancellationToken); - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } - public sealed class Request : + public sealed class Request : + AbstractHandlers.Base, IJsonRpcRequestHandler, - IRegistration, ICapability, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() where TCapability : ICapability { private readonly Func _handler; - private readonly TRegistrationOptions _registrationOptions; - private TCapability _capability = default!; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public Request(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (a, c, ct) => handler(a, c), registrationOptions) - { - } - - public Request(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) + public Request(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; } - - public Request(Guid id, Func handler, TRegistrationOptions registrationOptions) : - this(id, (a, c, ct) => handler(a, c), registrationOptions) + public Request(Func handler, RegistrationOptionsDelegate registrationOptionsFactory): + this(Guid.Empty, handler, registrationOptionsFactory) { } - public Request(Guid id, Func handler, TRegistrationOptions registrationOptions) - { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; - } async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { - await _handler(request, _capability, cancellationToken).ConfigureAwait(false); + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); return Unit.Value; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } public sealed class RequestRegistration : + AbstractHandlers.Base, IJsonRpcRequestHandler, - IRegistration, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() { private readonly Func> _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public RequestRegistration(Func> handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (a, ct) => handler(a), registrationOptions) - { - } - - public RequestRegistration(Func> handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) - { - } - - public RequestRegistration(Guid id, Func> handler, TRegistrationOptions registrationOptions) : - this(id, (a, ct) => handler(a), registrationOptions) + public RequestRegistration(Func> handler, RegistrationOptionsDelegate registrationOptionsFactory) : + this(Guid.Empty, handler, registrationOptionsFactory) { } - public RequestRegistration(Guid id, Func> handler, TRegistrationOptions registrationOptions) + public RequestRegistration(Guid id, Func> handler, RegistrationOptionsDelegate registrationOptionsFactory) { _id = id; _handler = handler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; } Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => _handler(request, cancellationToken); - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } public sealed class RequestRegistration : + AbstractHandlers.Base, IJsonRpcRequestHandler, - IRegistration, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() { private readonly Func _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public RequestRegistration(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (a, ct) => handler(a), registrationOptions) - { - } - - public RequestRegistration(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) - { - } - - public RequestRegistration(Guid id, Func handler, TRegistrationOptions registrationOptions) : - this(id, (a, ct) => handler(a), registrationOptions) + public RequestRegistration(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; } - public RequestRegistration(Guid id, Func handler, TRegistrationOptions registrationOptions) + public RequestRegistration(Func handler, RegistrationOptionsDelegate registrationOptionsFactory): + this(Guid.Empty, handler, registrationOptionsFactory) { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; } async Task IRequestHandler. @@ -248,36 +192,25 @@ async Task IRequestHandler. return Unit.Value; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } public sealed class RequestCapability : + AbstractHandlers.BaseCapability, IJsonRpcRequestHandler, - ICapability, ICanBeIdentifiedHandler where TParams : IRequest where TCapability : ICapability { private readonly Func> _handler; - private TCapability _capability = default!; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public RequestCapability(Func> handler) : - this(Guid.Empty, (a, c, ct) => handler(a, c)) - { - } - public RequestCapability(Func> handler) : this(Guid.Empty, handler) { } - public RequestCapability(Guid id, Func> handler) : - this(id, (a, c, ct) => handler(a, c)) - { - } - public RequestCapability(Guid id, Func> handler) { _id = id; @@ -286,38 +219,25 @@ public RequestCapability(Guid id, Func IRequestHandler. Handle(TParams request, CancellationToken cancellationToken) => - _handler(request, _capability, cancellationToken); - - void ICapability.SetCapability(TCapability capability) => _capability = capability; + _handler(request, Capability, cancellationToken); } public sealed class RequestCapability : + AbstractHandlers.BaseCapability, IJsonRpcRequestHandler, - ICapability, ICanBeIdentifiedHandler where TParams : IRequest where TCapability : ICapability { private readonly Func _handler; - private TCapability _capability = default!; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public RequestCapability(Func handler) : - this(Guid.Empty, handler) - { - } - public RequestCapability(Func handler) : this(Guid.Empty, handler) { } - public RequestCapability(Guid id, Func handler) : - this(id, (a, c, ct) => handler(a, c)) - { - } - public RequestCapability(Guid id, Func handler) { _id = id; @@ -327,66 +247,49 @@ public RequestCapability(Guid id, Func IRequestHandler. Handle(TParams request, CancellationToken cancellationToken) { - await _handler(request, _capability, cancellationToken).ConfigureAwait(false); + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); return Unit.Value; } - - void ICapability.SetCapability(TCapability capability) => _capability = capability; } - public sealed class PartialResult : - IJsonRpcRequestHandler, - IRegistration, ICapability, + public sealed class PartialResult : + AbstractHandlers.Base, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler - where TParams : IPartialItemRequest - where TResponse : new() + where TParams : IPartialItemRequest + where TItem : class? + where TResponse : class? where TRegistrationOptions : class, new() where TCapability : ICapability { - private readonly Func _factory; + private readonly Func _factory; private readonly Action, TCapability, CancellationToken> _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly IProgressManager _progressManager; - private TCapability _capability = default!; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; public PartialResult( - Action, TCapability> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, Func factory - ) : - this(Guid.Empty, (p, o, c, ct) => handler(p, o, c), registrationOptions, progressManager, factory) - { - } - - public PartialResult( - Action, TCapability, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func factory - ) : - this(Guid.Empty, handler, registrationOptions, progressManager, factory) - { - } - - public PartialResult( - Guid id, Action, TCapability> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func factory - ) : - this(id, (p, o, c, ct) => handler(p, o, c), registrationOptions, progressManager, factory) - { - } - - public PartialResult( - Guid id, Action, TCapability, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func factory + Guid id, Action, TCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory ) { _id = id; _handler = handler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle( + public PartialResult( + Action, TCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory + ): + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) + { + } + + async Task IRequestHandler.Handle( TParams request, CancellationToken cancellationToken ) @@ -394,125 +297,100 @@ CancellationToken cancellationToken var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver.Noop) { - _handler(request, observer, _capability, cancellationToken); + _handler(request, observer, Capability, cancellationToken); await observer; - return new TResponse(); + return _factory(default); } - var subject = new AsyncSubject(); + var subject = new AsyncSubject(); // in the event nothing is emitted... subject.OnNext(default!); - _handler(request, subject, _capability, cancellationToken); + _handler(request, subject, Capability, cancellationToken); return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false); } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } public sealed class PartialResult : - IJsonRpcRequestHandler, - IRegistration, + AbstractHandlers.Base, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemRequest - where TResponse : new() + where TItem : class? + where TResponse : class? where TRegistrationOptions : class, new() { private readonly Action, CancellationToken> _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly IProgressManager _progressManager; - private readonly Func _factory; + private readonly Func _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; public PartialResult( - Action> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, Func factory + Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory ) : - this(Guid.Empty, (p, o, ct) => handler(p, o), registrationOptions, progressManager, factory) + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) { } - public PartialResult( - Action, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func factory - ) : - this(Guid.Empty, handler, registrationOptions, progressManager, factory) - { - } - - public PartialResult( - Guid id, Action> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, Func factory - ) : - this(id, (p, o, ct) => handler(p, o), registrationOptions, progressManager, factory) - { - } - - public PartialResult( - Guid id, Action, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func factory + Guid id, Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory ) { _id = id; _handler = handler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver.Noop) { _handler(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(default); } - var subject = new AsyncSubject(); + var subject = new AsyncSubject(); // in the event nothing is emitted... subject.OnNext(default!); _handler(request, subject, cancellationToken); return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false); } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } public sealed class PartialResultCapability : - IJsonRpcRequestHandler, - ICapability, + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemRequest - where TResponse : new() + where TItem : class? + where TResponse : class? where TCapability : ICapability { private readonly Action, CancellationToken> _handler; private readonly IProgressManager _progressManager; - private readonly Func _factory; - private TCapability _capability = default!; + private readonly Func _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public PartialResultCapability(Action> handler, IProgressManager progressManager, Func factory) : - this((p, c, o, ct) => handler(p, c, o), progressManager, factory) - { - } - public PartialResultCapability( - Action, CancellationToken> handler, IProgressManager progressManager, Func factory + Action, CancellationToken> handler, IProgressManager progressManager, Func factory ) : this(Guid.Empty, handler, progressManager, factory) { } - public PartialResultCapability(Guid id, Action> handler, IProgressManager progressManager, Func factory) : - this(id, (p, c, o, ct) => handler(p, c, o), progressManager, factory) - { - } - public PartialResultCapability( - Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory + Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory ) { _id = id; @@ -521,57 +399,43 @@ public PartialResultCapability( _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver.Noop) { - _handler(request, _capability, observer, cancellationToken); + _handler(request, Capability, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(default); } - var subject = new AsyncSubject(); + var subject = new AsyncSubject(); // in the event nothing is emitted... subject.OnNext(default!); - _handler(request, _capability, subject, cancellationToken); + _handler(request, Capability, subject, cancellationToken); return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false); } - - void ICapability.SetCapability(TCapability capability) => _capability = capability; } public sealed class PartialResult : - IJsonRpcRequestHandler, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemRequest - where TResponse : new() + where TItem : class? + where TResponse : class? { private readonly Action, CancellationToken> _handler; private readonly IProgressManager _progressManager; - private readonly Func _factory; + private readonly Func _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public PartialResult(Action> handler, IProgressManager progressManager, Func factory) : - this(Guid.Empty, (p, o, ct) => handler(p, o), progressManager, factory) - { - } - - public PartialResult(Action, CancellationToken> handler, IProgressManager progressManager, Func factory) : + public PartialResult(Action, CancellationToken> handler, IProgressManager progressManager, Func factory) : this(Guid.Empty, handler, progressManager, factory) - { - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - public PartialResult(Guid id, Action> handler, IProgressManager progressManager, Func factory) : - this(id, (p, o, ct) => handler(p, o), progressManager, factory) { } - public PartialResult(Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory) + public PartialResult(Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory) { _id = id; _handler = handler; @@ -579,17 +443,17 @@ public PartialResult(Guid id, Action, CancellationToke _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver.Noop) { _handler(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(default); } - var subject = new AsyncSubject(); + var subject = new AsyncSubject(); // in the event nothing is emitted... subject.OnNext(default!); _handler(request, subject, cancellationToken); @@ -597,67 +461,51 @@ async Task IRequestHandler.Handle(TParams request } } - public sealed class PartialResults : - IJsonRpcRequestHandler, - IRegistration, ICapability, + public sealed class PartialResults : + AbstractHandlers.Base, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemsRequest - where TResponse : IEnumerable?, new() + where TItem : class? + where TResponse : IEnumerable? where TRegistrationOptions : class, new() where TCapability : ICapability { private readonly Action>, TCapability, CancellationToken> _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly IProgressManager _progressManager; - private readonly Func, TResponse> _factory; - private TCapability _capability = default!; + private readonly Func, TResponse?> _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; public PartialResults( - Action>, TCapability> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory + Action>, TCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func, TResponse?> factory ) : - this(Guid.Empty, (p, o, c, ct) => handler(p, o, c), registrationOptions, progressManager, factory) + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) { } public PartialResults( - Action>, TCapability, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory - ) : - this(Guid.Empty, handler, registrationOptions, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>, TCapability> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory - ) : - this(id, (p, o, c, ct) => handler(p, o, c), registrationOptions, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>, TCapability, CancellationToken> handler, TRegistrationOptions registrationOptions, - IProgressManager progressManager, Func, TResponse> factory + Guid id, Action>, TCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, Func, TResponse?> factory ) { _id = id; _handler = handler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver>.Noop) { - _handler(request, observer, _capability, cancellationToken); + _handler(request, observer, Capability, cancellationToken); await observer; - return new TResponse(); + return _factory(Enumerable.Empty()); } var subject = new Subject>(); @@ -668,74 +516,58 @@ async Task IRequestHandler.Handle(TParams request } ) .ToTask(cancellationToken); - _handler(request, subject, _capability, cancellationToken); + _handler(request, subject, Capability, cancellationToken); var result = _factory(await task.ConfigureAwait(false)); return result; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } public sealed class PartialResults : - IJsonRpcRequestHandler, - IRegistration, + AbstractHandlers.Base, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemsRequest - where TResponse : IEnumerable?, new() + where TItem : class? + where TResponse : IEnumerable? where TRegistrationOptions : class, new() { private readonly Action>, CancellationToken> _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly IProgressManager _progressManager; - private readonly Func, TResponse> _factory; + private readonly Func, TResponse?> _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; public PartialResults( - Action>> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory + Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func, TResponse?> factory ) : - this(Guid.Empty, (p, o, ct) => handler(p, o), registrationOptions, progressManager, factory) + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) { } public PartialResults( - Action>, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory - ) : - this(Guid.Empty, handler, registrationOptions, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory - ) : - this(id, (p, o, ct) => handler(p, o), registrationOptions, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>, CancellationToken> handler, TRegistrationOptions registrationOptions, IProgressManager progressManager, - Func, TResponse> factory + Guid id, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func, TResponse?> factory ) { _id = id; _handler = handler; - _registrationOptions = registrationOptions; + _registrationOptionsFactory = registrationOptionsFactory; _progressManager = progressManager; _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver>.Noop) { _handler(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(Enumerable.Empty()); } var subject = new Subject>(); @@ -751,48 +583,35 @@ async Task IRequestHandler.Handle(TParams request return result; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } public sealed class PartialResultsCapability : - IJsonRpcRequestHandler, ICapability, + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemsRequest - where TResponse : IEnumerable, new() + where TItem : class? + where TResponse : IEnumerable? where TCapability : ICapability { private readonly Action>, CancellationToken> _handler; private readonly IProgressManager _progressManager; - private readonly Func, TResponse> _factory; - private TCapability _capability = default!; + private readonly Func, TResponse?> _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public PartialResultsCapability( - Action>> handler, IProgressManager progressManager, Func, TResponse> factory - ) : - this(Guid.Empty, (p, c, o, ct) => handler(p, c, o), progressManager, factory) - { - } - public PartialResultsCapability( Action>, CancellationToken> handler, IProgressManager progressManager, - Func, TResponse> factory + Func, TResponse?> factory ) : this(Guid.Empty, handler, progressManager, factory) { } - public PartialResultsCapability( - Guid id, Action>> handler, IProgressManager progressManager, Func, TResponse> factory - ) : - this(id, (p, c, o, ct) => handler(p, c, o), progressManager, factory) - { - } - public PartialResultsCapability( Guid id, Action>, CancellationToken> handler, IProgressManager progressManager, - Func, TResponse> factory + Func, TResponse?> factory ) { _id = id; @@ -801,14 +620,14 @@ Func, TResponse> factory _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver>.Noop) { - _handler(request, _capability, observer, cancellationToken); + _handler(request, Capability, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(Enumerable.Empty()); } var subject = new Subject>(); @@ -819,33 +638,27 @@ async Task IRequestHandler.Handle(TParams request } ) .ToTask(cancellationToken); - _handler(request, _capability, subject, cancellationToken); + _handler(request, Capability, subject, cancellationToken); var result = _factory(await task.ConfigureAwait(false)); return result; } - - void ICapability.SetCapability(TCapability capability) => _capability = capability; } public sealed class PartialResults : - IJsonRpcRequestHandler, + IJsonRpcRequestHandler, ICanBeIdentifiedHandler where TParams : IPartialItemsRequest - where TResponse : IEnumerable, new() + where TItem : class? + where TResponse : IEnumerable? { private readonly Action>, CancellationToken> _handler; private readonly IProgressManager _progressManager; - private readonly Func, TResponse> _factory; + private readonly Func, TResponse?> _factory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public PartialResults(Action>> handler, IProgressManager progressManager, Func, TResponse> factory) : - this(Guid.Empty, (p, o, ct) => handler(p, o), progressManager, factory) - { - } - public PartialResults( - Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse> factory + Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory ) : this(Guid.Empty, handler, progressManager, factory) { @@ -854,13 +667,8 @@ Action>, CancellationToken> handler, IProg _factory = factory; } - public PartialResults(Guid id, Action>> handler, IProgressManager progressManager, Func, TResponse> factory) : - this(id, (p, o, ct) => handler(p, o), progressManager, factory) - { - } - public PartialResults( - Guid id, Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse> factory + Guid id, Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory ) { _id = id; @@ -869,14 +677,14 @@ public PartialResults( _factory = factory; } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { var observer = _progressManager.For(request, cancellationToken); if (observer != ProgressObserver>.Noop) { _handler(request, observer, cancellationToken); await observer; - return new TResponse(); + return _factory(Enumerable.Empty()); } var subject = new Subject>(); @@ -893,245 +701,117 @@ async Task IRequestHandler.Handle(TParams request } } - public sealed class Notification : + public sealed class Notification : + AbstractHandlers.Base, IJsonRpcNotificationHandler, - IRegistration, ICapability, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() where TCapability : ICapability { private readonly Func _handler; - private readonly TRegistrationOptions _registrationOptions; - private TCapability _capability = default!; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public Notification(Action handler, TRegistrationOptions registrationOptions) : - this( - Guid.Empty, (request, capability, ct) => { - handler(request, capability); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Action handler, TRegistrationOptions registrationOptions) : - this( - Guid.Empty, (request, c, ct) => { - handler(request, c, ct); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (request, capability, ct) => handler(request, capability), registrationOptions) - { - } - - public Notification(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) - { - } - - public Notification(Guid id, Action handler, TRegistrationOptions registrationOptions) : - this( - id, (request, capability, ct) => { - handler(request, capability); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Guid id, Action handler, TRegistrationOptions registrationOptions) : - this( - id, (request, c, ct) => { - handler(request, c, ct); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Guid id, Func handler, TRegistrationOptions registrationOptions) : - this(id, (request, capability, ct) => handler(request, capability), registrationOptions) + public Notification(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; } - public Notification(Guid id, Func handler, TRegistrationOptions registrationOptions) + public Notification(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : + this(Guid.Empty, handler, registrationOptionsFactory) { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; } async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { - await _handler(request, _capability, cancellationToken).ConfigureAwait(false); + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); return Unit.Value; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; - void ICapability.SetCapability(TCapability capability) => _capability = capability; + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); } public sealed class Notification : + AbstractHandlers.Base, IJsonRpcNotificationHandler, - IRegistration, ICanBeIdentifiedHandler where TParams : IRequest where TRegistrationOptions : class, new() { private readonly Func _handler; - private readonly TRegistrationOptions _registrationOptions; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public Notification(Action handler, TRegistrationOptions registrationOptions) : - this( - Guid.Empty, (request, ct) => { - handler(request); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Action handler, TRegistrationOptions registrationOptions) : - this( - Guid.Empty, (request, ct) => { - handler(request, ct); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, (request, ct) => handler(request), registrationOptions) - { - } - - public Notification(Func handler, TRegistrationOptions registrationOptions) : - this(Guid.Empty, handler, registrationOptions) - { - } - - public Notification(Guid id, Action handler, TRegistrationOptions registrationOptions) : - this( - id, (request, ct) => { - handler(request); - return Task.CompletedTask; - }, registrationOptions - ) - { - } - - public Notification(Guid id, Action handler, TRegistrationOptions registrationOptions) : - this( - id, (request, ct) => { - handler(request, ct); - return Task.CompletedTask; - }, registrationOptions - ) + public Notification(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; } - public Notification(Guid id, Func handler, TRegistrationOptions registrationOptions) : - this(id, (request, ct) => handler(request), registrationOptions) + public Notification(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : + this(Guid.Empty, handler, registrationOptionsFactory) { } - public Notification(Guid id, Func handler, TRegistrationOptions registrationOptions) - { - _id = id; - _handler = handler; - _registrationOptions = registrationOptions; - } - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { await _handler(request, cancellationToken).ConfigureAwait(false); return Unit.Value; } - TRegistrationOptions IRegistration.GetRegistrationOptions() => _registrationOptions; + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); } public sealed class NotificationCapability : - IJsonRpcNotificationHandler, ICapability, + AbstractHandlers.BaseCapability, + IJsonRpcNotificationHandler, ICanBeIdentifiedHandler where TParams : IRequest where TCapability : ICapability { private readonly Func _handler; - private TCapability _capability = default!; private readonly Guid _id; Guid ICanBeIdentifiedHandler.Id => _id; - public NotificationCapability(Action handler) : - this( - Guid.Empty, (request, capability, ct) => { - handler(request, capability); - return Task.CompletedTask; - } - ) - { - } - - public NotificationCapability(Func handler) : - this(Guid.Empty, (request, capability, ct) => handler(request, capability)) - { - } - - public NotificationCapability(Action handler) : - this( - Guid.Empty, (request, capability, ct) => { - handler(request, capability, ct); - return Task.CompletedTask; - } - ) + public NotificationCapability(Guid id, Func handler) { + _id = id; + _handler = handler; } - public NotificationCapability(Func handler) : this(Guid.Empty, handler) { } - public NotificationCapability(Guid id, Action handler) : - this( - id, (request, capability, ct) => { - handler(request, capability); - return Task.CompletedTask; - } - ) + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) { + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; } + } - public NotificationCapability(Guid id, Func handler) : - this(id, (request, capability, ct) => handler(request, capability)) - { - } + public sealed class TypedPartialObserver : IObserver> + { + private readonly IObserver> _results; + private readonly Func _factory; - public NotificationCapability(Guid id, Func handler) + public TypedPartialObserver(IObserver> results, Func factory) { - _id = id; - _handler = handler; + _results = results; + _factory = factory; } + public void OnCompleted() => _results.OnCompleted(); - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, _capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } + public void OnError(Exception error) => _results.OnError(error); - void ICapability.SetCapability(TCapability capability) => _capability = capability; + public void OnNext(IEnumerable value) => _results.OnNext(value.Select(_factory)); } } } diff --git a/src/Protocol/Models/ApplyWorkspaceEditParams.cs b/src/Protocol/Models/ApplyWorkspaceEditParams.cs deleted file mode 100644 index dae2ea702..000000000 --- a/src/Protocol/Models/ApplyWorkspaceEditParams.cs +++ /dev/null @@ -1,23 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.ApplyEdit, Direction.ServerToClient)] - public class ApplyWorkspaceEditParams : IRequest - { - /// - /// An optional label of the workspace edit. This label is - /// presented in the user interface for example on an undo - /// stack to undo the workspace edit. - /// - [Optional] - public string? Label { get; set; } - - /// - /// The edits to apply. - /// - public WorkspaceEdit Edit { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/ApplyWorkspaceEditResponse.cs b/src/Protocol/Models/ApplyWorkspaceEditResponse.cs deleted file mode 100644 index a68d36e40..000000000 --- a/src/Protocol/Models/ApplyWorkspaceEditResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ApplyWorkspaceEditResponse - { - /// - /// Indicates whether the edit was applied or not. - /// - public bool Applied { get; set; } - - /// - /// An optional textual description for why the edit was not applied. - /// This may be used may be used by the server for diagnostic - /// logging or to provide a suitable error for a request that - /// triggered the edit. - /// - [Optional] - public string? FailureReason { get; set; } - - /// - /// Depending on the client's failure handling strategy `failedChange` - /// might contain the index of the change that failed. This property is - /// only available if the client signals a `failureHandlingStrategy` - /// in its client capabilities. - /// - [Optional] - public int? FailedChange { get; set; } - } -} diff --git a/src/Protocol/Models/CodeAction.cs b/src/Protocol/Models/CodeAction.cs deleted file mode 100644 index aa2a17275..000000000 --- a/src/Protocol/Models/CodeAction.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System.Diagnostics; -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - [Method(TextDocumentNames.CodeActionResolve, Direction.ClientToServer)] - public class CodeAction : ICanBeResolved, IRequest - { - /// - /// A short, human-readable, title for this code action. - /// - public string Title { get; set; } = null!; - - /// - /// The kind of the code action. - /// - /// Used to filter code actions. - /// - [Optional] - public CodeActionKind Kind { get; set; } - - /// - /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted - /// by keybindings. - /// - /// A quick fix should be marked preferred if it properly addresses the underlying error. - /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take. - /// - /// @since 3.15.0 - /// - [Optional] - public bool IsPreferred { get; set; } - - /// - /// The diagnostics that this code action resolves. - /// - [Optional] - public Container? Diagnostics { get; set; } - - /// - /// The workspace edit this code action performs. - /// - [Optional] - public WorkspaceEdit? Edit { get; set; } - - /// - /// A command this code action executes. If a code action - /// provides an edit and a command, first the edit is - /// executed and then the command. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// Marks that the code action cannot currently be applied. - /// - /// Clients should follow the following guidelines regarding disabled code actions: - /// - /// - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) - /// code action menu. - /// - /// - Disabled actions are shown as faded out in the code action menu when the user request a more specific type - /// of code action, such as refactorings. - /// - /// - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) - /// that auto applies a code action and only a disabled code actions are returned, the client should show the user an - /// error message with `reason` in the editor. - /// - /// @since 3.16.0 - /// - [Optional] - public CodeActionDisabled? Disabled { get; set; } - - /// - /// A data entry field that is preserved on a document link between a - /// DocumentLinkRequest and a DocumentLinkResolveRequest. - /// - [Optional] - public JToken? Data { get; set; } - - private string DebuggerDisplay => $"[{Kind}] {Title}"; - - /// - public override string ToString() => DebuggerDisplay; - } - - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CodeAction : ICanBeResolved - where T : HandlerIdentity?, new() - { - /// - /// A short, human-readable, title for this code action. - /// - public string Title { get; set; } = null!; - - /// - /// The kind of the code action. - /// - /// Used to filter code actions. - /// - [Optional] - public CodeActionKind Kind { get; set; } - - /// - /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted - /// by keybindings. - /// - /// A quick fix should be marked preferred if it properly addresses the underlying error. - /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take. - /// - /// @since 3.15.0 - /// - [Optional] - public bool IsPreferred { get; set; } - - /// - /// The diagnostics that this code action resolves. - /// - [Optional] - public Container? Diagnostics { get; set; } - - /// - /// The workspace edit this code action performs. - /// - [Optional] - public WorkspaceEdit? Edit { get; set; } - - /// - /// A command this code action executes. If a code action - /// provides an edit and a command, first the edit is - /// executed and then the command. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// Marks that the code action cannot currently be applied. - /// - /// Clients should follow the following guidelines regarding disabled code actions: - /// - /// - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) - /// code action menu. - /// - /// - Disabled actions are shown as faded out in the code action menu when the user request a more specific type - /// of code action, such as refactorings. - /// - /// - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) - /// that auto applies a code action and only a disabled code actions are returned, the client should show the user an - /// error message with `reason` in the editor. - /// - /// @since 3.16.0 - /// - [Optional] - public CodeActionDisabled? Disabled { get; set; } - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - [Optional] - public T Data - { - get => ( (ICanBeResolved) this ).Data?.ToObject()!; - set => ( (ICanBeResolved) this ).Data = JToken.FromObject(value); - } - - JToken? ICanBeResolved.Data { get; set; } - - public static implicit operator CodeAction(CodeAction value) => new CodeAction { - Data = ( (ICanBeResolved) value ).Data, - Command = value.Command, - Diagnostics = value.Diagnostics, - Disabled = value.Disabled, - Edit = value.Edit, - Kind = value.Kind, - Title = value.Title, - IsPreferred = value.IsPreferred, - }; - - public static implicit operator CodeAction(CodeAction value) - { - var item = new CodeAction { - Command = value.Command, - Diagnostics = value.Diagnostics, - Disabled = value.Disabled, - Edit = value.Edit, - Kind = value.Kind, - Title = value.Title, - IsPreferred = value.IsPreferred, - }; - ( (ICanBeResolved) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => $"[{Kind}] {Title}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/CodeActionContext.cs b/src/Protocol/Models/CodeActionContext.cs deleted file mode 100644 index 86b2bf686..000000000 --- a/src/Protocol/Models/CodeActionContext.cs +++ /dev/null @@ -1,29 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Contains additional diagnostic information about the context in which - /// a code action is run. - /// - public class CodeActionContext - { - /// - /// An array of diagnostics known on the client side overlapping the range provided to the - /// `textDocument/codeAction` request. They are provied so that the server knows which - /// errors are currently presented to the user for the given range. There is no guarantee - /// that these accurately reflect the error state of the resource. The primary parameter - /// to compute code actions is the provided range. - /// - public Container Diagnostics { get; set; } = null!; - - /// - /// Requested kind of actions to return. - /// - /// Actions not of this kind are filtered out by the client before being shown. So servers - /// can omit computing them. - /// - [Optional] - public Container? Only { get; set; } - } -} diff --git a/src/Protocol/Models/CodeActionDisabled.cs b/src/Protocol/Models/CodeActionDisabled.cs deleted file mode 100644 index 417b95552..000000000 --- a/src/Protocol/Models/CodeActionDisabled.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Marks that the code action cannot currently be applied. - /// - /// Clients should follow the following guidelines regarding disabled code actions: - /// - /// - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) - /// code action menu. - /// - /// - Disabled actions are shown as faded out in the code action menu when the user request a more specific type - /// of code action, such as refactorings. - /// - /// - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) - /// that auto applies a code action and only a disabled code actions are returned, the client should show the user an - /// error message with `reason` in the editor. - /// - /// @since 3.16.0 - /// - public class CodeActionDisabled - { - /// - /// Human readable description of why the code action is currently disabled. - /// - /// This is displayed in the code actions UI. - /// - public string Reason { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/CodeActionKind.cs b/src/Protocol/Models/CodeActionKind.cs deleted file mode 100644 index 62b157869..000000000 --- a/src/Protocol/Models/CodeActionKind.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A set of predefined code action kinds - /// - [DebuggerDisplay("{" + nameof(_value) + "}")] - [JsonConverter(typeof(EnumLikeStringConverter))] - public readonly struct CodeActionKind : IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = - new Lazy>( - () => { - return typeof(CodeActionKind) - .GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(z => z.GetValue(null)) - .Cast() - .ToArray(); - } - ); - - public static IEnumerable Defaults => _defaults.Value; - - /// - /// Base kind for quickfix actions: '' - /// - public static readonly CodeActionKind Empty = new CodeActionKind(""); - - /// - /// Base kind for quickfix actions: 'quickfix' - /// - public static readonly CodeActionKind QuickFix = new CodeActionKind("quickfix"); - - /// - /// Base kind for refactoring actions: 'refactor' - /// - public static readonly CodeActionKind Refactor = new CodeActionKind("refactor"); - - /// - /// Base kind for refactoring extraction actions: 'refactor.extract' - /// - /// Example extract actions: - /// - /// - Extract method - /// - Extract function - /// - Extract variable - /// - Extract interface from class - /// - ... - /// - public static readonly CodeActionKind RefactorExtract = new CodeActionKind("refactor.extract"); - - /// - /// Base kind for refactoring inline actions: 'refactor.inline' - /// - /// Example inline actions: - /// - /// - Inline function - /// - Inline variable - /// - Inline constant - /// - ... - /// - public static readonly CodeActionKind RefactorInline = new CodeActionKind("refactor.inline"); - - /// - /// Base kind for refactoring rewrite actions: 'refactor.rewrite' - /// - /// Example rewrite actions: - /// - /// - Convert JavaScript function to class - /// - Add or remove parameter - /// - Encapsulate field - /// - Make method static - /// - Move method to base class - /// - ... - /// - public static readonly CodeActionKind RefactorRewrite = new CodeActionKind("refactor.rewrite"); - - /// - /// Base kind for source actions: `source` - /// - /// Source code actions apply to the entire file. - /// - public static readonly CodeActionKind Source = new CodeActionKind("source"); - - /// - /// Base kind for an organize imports source action: `source.organizeImports` - /// - public static readonly CodeActionKind SourceOrganizeImports = new CodeActionKind("source.organizeImports"); - - private readonly string? _value; - - public CodeActionKind(string kind) => _value = kind; - - public static implicit operator CodeActionKind(string kind) => new CodeActionKind(kind); - - public static implicit operator string(CodeActionKind kind) => kind._value ?? string.Empty; - - /// - public override string ToString() => _value ?? string.Empty; - - public bool Equals(CodeActionKind other) => _value == other._value; - - public override bool Equals(object obj) => obj is CodeActionKind other && Equals(other); - - public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; - - public static bool operator ==(CodeActionKind left, CodeActionKind right) => left.Equals(right); - - public static bool operator !=(CodeActionKind left, CodeActionKind right) => !left.Equals(right); - } -} diff --git a/src/Protocol/Models/CodeActionParams.cs b/src/Protocol/Models/CodeActionParams.cs deleted file mode 100644 index 30eb5b43b..000000000 --- a/src/Protocol/Models/CodeActionParams.cs +++ /dev/null @@ -1,35 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Params for the CodeActionRequest - /// - [Method(TextDocumentNames.CodeAction, Direction.ClientToServer)] - public class CodeActionParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams - { - /// - /// The document in which the command was invoked. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The range for which the command was invoked. - /// - public Range Range { get; set; } = null!; - - /// - /// Context carrying additional information. - /// - public CodeActionContext Context { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/CodeActionRegistrationOptions.cs b/src/Protocol/Models/CodeActionRegistrationOptions.cs deleted file mode 100644 index 56f2f0d49..000000000 --- a/src/Protocol/Models/CodeActionRegistrationOptions.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CodeActionRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// CodeActionKinds that this server may return. - /// - /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server - /// may list out every specific kind they provide. - /// - [Optional] - public Container? CodeActionKinds { get; set; } = new Container(); - - /// - /// The server provides support to resolve additional - /// information for a code action. - /// - /// @since 3.16.0 - /// - public bool ResolveProvider { get; set; } - - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// CodeActionKinds that this server may return. - /// - /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server - /// may list out every specific kind they provide. - /// - [Optional] - public Container? CodeActionKinds { get; set; } = new Container(); - - /// - /// The server provides support to resolve additional - /// information for a code action. - /// - /// @since 3.16.0 - /// - [Optional] - public bool ResolveProvider { get; set; } - } - - class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public CodeActionRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CodeActionProvider)) - { - _handlersManager = handlersManager; - } - - public override StaticOptions Convert(CodeActionRegistrationOptions source) - { - return new StaticOptions { - CodeActionKinds = source.CodeActionKinds, - ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICodeActionResolveHandler)), - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } - } -} diff --git a/src/Protocol/Models/CodeDescription.cs b/src/Protocol/Models/CodeDescription.cs deleted file mode 100644 index b4fe9b834..000000000 --- a/src/Protocol/Models/CodeDescription.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Structure to capture a description for an error code. - /// - /// @since 3.16.0 - proposed state - /// - public class CodeDescription - { - /// - /// An URI to open with more information about the diagnostic error. - /// - public Uri Href { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/CodeLens.cs b/src/Protocol/Models/CodeLens.cs deleted file mode 100644 index d61d0f557..000000000 --- a/src/Protocol/Models/CodeLens.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Diagnostics; -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A code lens represents a command that should be shown along with - /// source text, like the number of references, a way to run tests, etc. - /// - /// A code lens is _unresolved_ when no command is associated to it. For performance - /// reasons the creation of a code lens and resolving should be done in two stages. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - [Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] - public class CodeLens : IRequest, ICanBeResolved - { - /// - /// The range in which this code lens is valid. Should only span a single line. - /// - public Range Range { get; set; } = null!; - - /// - /// The command this code lens represents. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - [Optional] - public JToken? Data { get; set; } - - private string DebuggerDisplay => $"{Range}{( Command != null ? $" {Command}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } - - /// - /// A code lens represents a command that should be shown along with - /// source text, like the number of references, a way to run tests, etc. - /// - /// A code lens is _unresolved_ when no command is associated to it. For performance - /// reasons the creation of a code lens and resolving should be done in two stages. - /// - /// - /// Typed code lens used for the typed handlers - /// - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CodeLens : ICanBeResolved - where T : HandlerIdentity?, new() - { - /// - /// The range in which this code lens is valid. Should only span a single line. - /// - public Range Range { get; set; } = null!; - - /// - /// The command this code lens represents. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - public T Data - { - get => ( (ICanBeResolved) this ).Data?.ToObject()!; - set => ( (ICanBeResolved) this ).Data = JToken.FromObject(value); - } - - JToken? ICanBeResolved.Data { get; set; } - - public static implicit operator CodeLens(CodeLens value) => new CodeLens { - Data = ( (ICanBeResolved) value ).Data, - Command = value.Command, - Range = value.Range, - }; - - public static implicit operator CodeLens(CodeLens value) - { - var item = new CodeLens { - Command = value.Command, - Range = value.Range, - }; - ( (ICanBeResolved) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => $"{Range}{( Command != null ? $" {Command}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/CodeLensContainer.cs b/src/Protocol/Models/CodeLensContainer.cs deleted file mode 100644 index 45f970598..000000000 --- a/src/Protocol/Models/CodeLensContainer.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CodeLensContainer : Container - { - public CodeLensContainer() : this(Enumerable.Empty()) - { - } - - public CodeLensContainer(IEnumerable items) : base(items) - { - } - - public CodeLensContainer(params CodeLens[] items) : base(items) - { - } - - public static implicit operator CodeLensContainer(CodeLens[] items) => new CodeLensContainer(items); - - public static implicit operator CodeLensContainer(Collection items) => new CodeLensContainer(items); - - public static implicit operator CodeLensContainer(List items) => new CodeLensContainer(items); - } - - /// - /// Typed code lens used for the typed handlers - /// - public class CodeLensContainer : Container> where T : HandlerIdentity?, new() - { - public CodeLensContainer() : this(Enumerable.Empty>()) - { - } - - public CodeLensContainer(IEnumerable> items) : base(items) - { - } - - public CodeLensContainer(params CodeLens[] items) : base(items) - { - } - - public static implicit operator CodeLensContainer(CodeLens[] items) => new CodeLensContainer(items); - - public static implicit operator CodeLensContainer(Collection> items) => new CodeLensContainer(items); - - public static implicit operator CodeLensContainer(List> items) => new CodeLensContainer(items); - - public static implicit operator CodeLensContainer(CodeLensContainer container) => new CodeLensContainer(container.Select(z => (CodeLens) z)); - } -} diff --git a/src/Protocol/Models/CodeLensParams.cs b/src/Protocol/Models/CodeLensParams.cs deleted file mode 100644 index 59ec4d103..000000000 --- a/src/Protocol/Models/CodeLensParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.CodeLens, Direction.ClientToServer)] - public class CodeLensParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, IPartialItemsRequest - { - /// - /// The document to request code lens for. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/CodeLensRegistrationOptions.cs b/src/Protocol/Models/CodeLensRegistrationOptions.cs deleted file mode 100644 index 512da1de0..000000000 --- a/src/Protocol/Models/CodeLensRegistrationOptions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CodeLensRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// Code lens has a resolve provider as well. - /// - [Optional] - public bool ResolveProvider { get; set; } - - /// - /// Code Lens options. - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// Code lens has a resolve provider as well. - /// - [Optional] - public bool ResolveProvider { get; set; } - } - - class CodeLensRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public CodeLensRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CodeLensProvider)) - { - _handlersManager = handlersManager; - } - public override StaticOptions Convert(CodeLensRegistrationOptions source) - { - return new StaticOptions { - ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICodeLensResolveHandler)), - WorkDoneProgress = source.WorkDoneProgress - }; - } - } - } -} diff --git a/src/Protocol/Models/ColorInformation.cs b/src/Protocol/Models/ColorInformation.cs deleted file mode 100644 index 6152af896..000000000 --- a/src/Protocol/Models/ColorInformation.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ColorInformation - { - /// - /// The range in the document where this color appers. - /// - public Range Range { get; set; } = null!; - - /// - /// The actual color value for this color range. - /// - public DocumentColor Color { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/ColorPresentation.cs b/src/Protocol/Models/ColorPresentation.cs deleted file mode 100644 index 85043e81a..000000000 --- a/src/Protocol/Models/ColorPresentation.cs +++ /dev/null @@ -1,29 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ColorPresentation - { - /// - /// The label of this color presentation. It will be shown on the color - /// picker header. By default this is also the text that is inserted when selecting - /// this color presentation. - /// - public string Label { get; set; } = null!; - - /// - /// An [edit](#TextEdit) which is applied to a document when selecting - /// this presentation for the color. When `falsy` the [label](#ColorPresentation.label) - /// is used. - /// - [Optional] - public TextEdit? TextEdit { get; set; } - - /// - /// An optional array of additional [text edits](#TextEdit) that are applied when - /// selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. - /// - [Optional] - public TextEditContainer? AdditionalTextEdits { get; set; } - } -} diff --git a/src/Protocol/Models/ColorPresentationParams.cs b/src/Protocol/Models/ColorPresentationParams.cs deleted file mode 100644 index c6e864aba..000000000 --- a/src/Protocol/Models/ColorPresentationParams.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.ColorPresentation, Direction.ClientToServer)] - public class ColorPresentationParams : IRequest> - { - /// - /// The document to provide document links for. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The actual color value for this color range. - /// - public DocumentColor Color { get; set; } = null!; - - /// - /// The range in the document where this color appers. - /// - public Range Range { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/CommandOrCodeAction.cs b/src/Protocol/Models/CommandOrCodeAction.cs deleted file mode 100644 index 300ca0d0e..000000000 --- a/src/Protocol/Models/CommandOrCodeAction.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Diagnostics; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(CommandOrCodeActionConverter))] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CommandOrCodeAction : ICanBeResolved // This to ensure that code actions get updated as expected - { - private CodeAction? _codeAction; - private Command? _command; - - public CommandOrCodeAction(CodeAction value) - { - _codeAction = value; - _command = default; - } - - public CommandOrCodeAction(Command value) - { - _codeAction = default; - _command = value; - } - - public bool IsCommand => _command != null; - - public Command? Command - { - get => _command; - set { - _command = value; - _codeAction = null; - } - } - - public bool IsCodeAction => _codeAction != null; - - public CodeAction? CodeAction - { - get => _codeAction; - set { - _command = default; - _codeAction = value; - } - } - - public object? RawValue - { - get { - if (IsCommand) return Command!; - if (IsCodeAction) return CodeAction!; - return default; - } - } - - public static implicit operator CommandOrCodeAction(Command value) => new CommandOrCodeAction(value); - - public static implicit operator CommandOrCodeAction(CodeAction value) => new CommandOrCodeAction(value); - - private string DebuggerDisplay => $"{( IsCommand ? $"command: {Command}" : IsCodeAction ? $"code action: {CodeAction}" : "..." )}"; - - /// - public override string ToString() => DebuggerDisplay; - - JToken? ICanBeResolved.Data - { - get => _codeAction?.Data; - set { - if (_codeAction == null) return; - _codeAction.Data = value; - } - } - } -} diff --git a/src/Protocol/Models/CommandOrCodeActionContainer.cs b/src/Protocol/Models/CommandOrCodeActionContainer.cs deleted file mode 100644 index b90b28596..000000000 --- a/src/Protocol/Models/CommandOrCodeActionContainer.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CommandOrCodeActionContainer : Container - { - public CommandOrCodeActionContainer() : this(Enumerable.Empty()) - { - } - - public CommandOrCodeActionContainer(IEnumerable items) : base(items) - { - } - - public CommandOrCodeActionContainer(params CommandOrCodeAction[] items) : base(items) - { - } - - public static implicit operator CommandOrCodeActionContainer(CommandOrCodeAction[] items) => new CommandOrCodeActionContainer(items); - - public static implicit operator CommandOrCodeActionContainer(Collection items) => new CommandOrCodeActionContainer(items); - - public static implicit operator CommandOrCodeActionContainer(List items) => new CommandOrCodeActionContainer(items); - } - - /// - /// Typed code lens used for the typed handlers - /// - public class CodeActionContainer : Container> where T : HandlerIdentity?, new() - { - public CodeActionContainer() : this(Enumerable.Empty>()) - { - } - - public CodeActionContainer(IEnumerable> items) : base(items) - { - } - - public CodeActionContainer(params CodeAction[] items) : base(items) - { - } - - public static implicit operator CodeActionContainer(CodeAction[] items) => new CodeActionContainer(items); - - public static implicit operator CodeActionContainer(Collection> items) => new CodeActionContainer(items); - - public static implicit operator CodeActionContainer(List> items) => new CodeActionContainer(items); - - public static implicit operator CommandOrCodeActionContainer(CodeActionContainer container) => new CommandOrCodeActionContainer(container.Select(z => new CommandOrCodeAction(z))); - } -} diff --git a/src/Protocol/Models/CompletionContext.cs b/src/Protocol/Models/CompletionContext.cs deleted file mode 100644 index 9c6873eff..000000000 --- a/src/Protocol/Models/CompletionContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CompletionContext - { - /// - /// How the completion was triggered. - /// - public CompletionTriggerKind TriggerKind { get; set; } - - /// - /// Most tools trigger completion request automatically without explicitly requesting - /// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user - /// starts to type an identifier. For example if the user types `c` in a JavaScript file - /// code complete will automatically pop up present `console` besides others as a - /// completion item. Characters that make up identifiers don't need to be listed here. - /// - /// If code complete should automatically be trigger on characters not being valid inside - /// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. - /// - [Optional] - public string? TriggerCharacter { get; set; } - } -} diff --git a/src/Protocol/Models/CompletionItem.cs b/src/Protocol/Models/CompletionItem.cs deleted file mode 100644 index 72de1f854..000000000 --- a/src/Protocol/Models/CompletionItem.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - [Method(TextDocumentNames.CompletionResolve, Direction.ClientToServer)] - public class CompletionItem : ICanBeResolved, IRequest - { - /// - /// The label of this completion item. By default - /// also the text that is inserted when selecting - /// this completion. - /// - public string Label { get; set; } = null!; - - /// - /// The kind of this completion item. Based of the kind - /// an icon is chosen by the editor. - /// - [Optional] - public CompletionItemKind Kind { get; set; } - - /// - /// Tags for this completion item. - /// - /// @since 3.15.0 - /// - [Optional] - public Container? Tags { get; set; } - - /// - /// A human-readable string with additional information - /// about this item, like type or symbol information. - /// - [Optional] - public string? Detail { get; set; } - - /// - /// A human-readable string that represents a doc-comment. - /// - [Optional] - public StringOrMarkupContent? Documentation { get; set; } - - /// - /// Indicates if this item is deprecated. - /// - [Optional] - public bool Deprecated { get; set; } - - /// - /// Select this item when showing. - /// - /// *Note* that only one completion item can be selected and that the - /// tool / client decides which item that is. The rule is that the *first* - /// item of those that match best is selected. - /// - [Optional] - public bool Preselect { get; set; } - - /// - /// A string that shoud be used when comparing this item - /// with other items. When `falsy` the label is used. - /// - [Optional] - public string? SortText { get; set; } - - /// - /// A string that should be used when filtering a set of - /// completion items. When `falsy` the label is used. - /// - - [Optional] - public string? FilterText { get; set; } - - /// - /// A string that should be inserted a document when selecting - /// this completion. When `falsy` the label is used. - /// - - [Optional] - public string? InsertText { get; set; } - - /// - /// The format of the insert text. The format applies to both the `insertText` property - /// and the `newText` property of a provided `textEdit`. - /// - [Optional] - public InsertTextFormat InsertTextFormat { get; set; } - - /// - /// How whitespace and indentation is handled during completion - /// item insertion. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public InsertTextMode InsertTextMode { get; set; } - - /// - /// An edit which is applied to a document when selecting this completion. When an edit is provided the value of - /// `insertText` is ignored. - /// - /// *Note:* The range of the edit must be a single line range and it must contain the position at which completion - /// has been requested. - /// - /// Most editors support two different operation when accepting a completion - /// item. One is to insert a completion text and the other is to replace an - /// existing text with a competion text. Since this can usually not - /// predetermend by a server it can report both ranges. Clients need to - /// signal support for `InsertReplaceEdits` via the - /// `textDocument.completion.insertReplaceSupport` client capability - /// property. - /// - /// *Note 1:* The text edit's range as well as both ranges from a insert - /// replace edit must be a [single line] and they must contain the position - /// at which completion has been requested. - /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range - /// must be a prefix of the edit's replace range, that means it must be - /// contained and starting at the same position. - /// - /// @since 3.16.0 additional type `InsertReplaceEdit` - proposed state - /// - /// - /// TODO: Update this to union - /// - [Optional] - public TextEdit? TextEdit { get; set; } - - /// - /// An optional array of additional text edits that are applied when - /// selecting this completion. Edits must not overlap with the main edit - /// nor with themselves. - /// - [Optional] - public TextEditContainer? AdditionalTextEdits { get; set; } - - /// - /// An optional set of characters that when pressed while this completion is active will accept it first and - /// then type that character. *Note* that all commit characters should have `length=1` and that superfluous - /// characters will be ignored. - /// - [Optional] - public Container? CommitCharacters { get; set; } - - /// - /// An optional command that is executed/// after* inserting this completion./// Note* that - /// additional modifications to the current document should be described with the - /// additionalTextEdits-property. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// An data entry field that is preserved on a completion item between - /// a completion and a completion resolve request. - /// - [Optional] - public JToken? Data { get; set; } - - private string DebuggerDisplay => $"[{Kind}] {Label}{( Tags?.Any() == true ? $" tags: {string.Join(", ", Tags.Select(z => z.ToString()))}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } - - /// - /// Typed code lens used for the typed handlers - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CompletionItem : ICanBeResolved - where T : HandlerIdentity?, new() - { - /// - /// The label of this completion item. By default - /// also the text that is inserted when selecting - /// this completion. - /// - public string Label { get; set; } = null!; - - /// - /// The kind of this completion item. Based of the kind - /// an icon is chosen by the editor. - /// - [Optional] - public CompletionItemKind Kind { get; set; } - - /// - /// Tags for this completion item. - /// - /// @since 3.15.0 - /// - [Optional] - public Container? Tags { get; set; } - - /// - /// A human-readable string with additional information - /// about this item, like type or symbol information. - /// - [Optional] - public string? Detail { get; set; } - - /// - /// A human-readable string that represents a doc-comment. - /// - [Optional] - public StringOrMarkupContent? Documentation { get; set; } - - /// - /// Indicates if this item is deprecated. - /// - [Optional] - public bool Deprecated { get; set; } - - /// - /// Select this item when showing. - /// - /// *Note* that only one completion item can be selected and that the - /// tool / client decides which item that is. The rule is that the *first* - /// item of those that match best is selected. - /// - [Optional] - public bool Preselect { get; set; } - - /// - /// A string that shoud be used when comparing this item - /// with other items. When `falsy` the label is used. - /// - [Optional] - public string? SortText { get; set; } - - /// - /// A string that should be used when filtering a set of - /// completion items. When `falsy` the label is used. - /// - - [Optional] - public string? FilterText { get; set; } - - /// - /// A string that should be inserted a document when selecting - /// this completion. When `falsy` the label is used. - /// - - [Optional] - public string? InsertText { get; set; } - - /// - /// The format of the insert text. The format applies to both the `insertText` property - /// and the `newText` property of a provided `textEdit`. - /// - [Optional] - public InsertTextFormat InsertTextFormat { get; set; } - - /// - /// An edit which is applied to a document when selecting this completion. When an edit is provided the value of - /// `insertText` is ignored. - /// - /// *Note:* The range of the edit must be a single line range and it must contain the position at which completion - /// has been requested. - /// - [Optional] - public TextEdit? TextEdit { get; set; } - - /// - /// An optional array of additional text edits that are applied when - /// selecting this completion. Edits must not overlap with the main edit - /// nor with themselves. - /// - [Optional] - public TextEditContainer? AdditionalTextEdits { get; set; } - - /// - /// An optional set of characters that when pressed while this completion is active will accept it first and - /// then type that character. *Note* that all commit characters should have `length=1` and that superfluous - /// characters will be ignored. - /// - [Optional] - public Container? CommitCharacters { get; set; } - - /// - /// An optional command that is executed/// after* inserting this completion./// Note* that - /// additional modifications to the current document should be described with the - /// additionalTextEdits-property. - /// - [Optional] - public Command? Command { get; set; } - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - [Optional] - [MaybeNull] - public T Data - { - get => ( (ICanBeResolved) this ).Data?.ToObject()!; - set => ( (ICanBeResolved) this ).Data = JToken.FromObject(value); - } - - JToken? ICanBeResolved.Data { get; set; } - - public static implicit operator CompletionItem(CompletionItem value) => new CompletionItem { - Data = ( (ICanBeResolved) value ).Data, - Command = value.Command, - Deprecated = value.Deprecated, - Detail = value.Detail, - Documentation = value.Documentation, - Kind = value.Kind, - Label = value.Label, - Preselect = value.Preselect, - Tags = value.Tags, - CommitCharacters = value.CommitCharacters, - FilterText = value.FilterText, - InsertText = value.InsertText, - SortText = value.SortText, - TextEdit = value.TextEdit, - AdditionalTextEdits = value.AdditionalTextEdits, - InsertTextFormat = value.InsertTextFormat, - }; - - public static implicit operator CompletionItem(CompletionItem value) - { - var item = new CompletionItem { - Command = value.Command, - Deprecated = value.Deprecated, - Detail = value.Detail, - Documentation = value.Documentation, - Kind = value.Kind, - Label = value.Label, - Preselect = value.Preselect, - Tags = value.Tags, - CommitCharacters = value.CommitCharacters, - FilterText = value.FilterText, - InsertText = value.InsertText, - SortText = value.SortText, - TextEdit = value.TextEdit, - AdditionalTextEdits = value.AdditionalTextEdits, - InsertTextFormat = value.InsertTextFormat, - }; - ( (ICanBeResolved) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => $"[{Kind}] {Label}{( Tags?.Any() == true ? $" tags: {string.Join(", ", Tags.Select(z => z.ToString()))}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/CompletionItemKind.cs b/src/Protocol/Models/CompletionItemKind.cs deleted file mode 100644 index 3888af738..000000000 --- a/src/Protocol/Models/CompletionItemKind.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The kind of a completion entry. - /// - [JsonConverter(typeof(NumberEnumConverter))] - public enum CompletionItemKind - { - Text = 1, - Method = 2, - Function = 3, - Constructor = 4, - Field = 5, - Variable = 6, - Class = 7, - Interface = 8, - Module = 9, - Property = 10, - Unit = 11, - Value = 12, - Enum = 13, - Keyword = 14, - Snippet = 15, - Color = 16, - File = 17, - Reference = 18, - Folder = 19, - EnumMember = 20, - Constant = 21, - Struct = 22, - Event = 23, - Operator = 24, - TypeParameter = 25, - } -} diff --git a/src/Protocol/Models/CompletionItemTag.cs b/src/Protocol/Models/CompletionItemTag.cs deleted file mode 100644 index 4a0ecd0ac..000000000 --- a/src/Protocol/Models/CompletionItemTag.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Completion item tags are extra annotations that tweak the rendering of a completion - /// item. - /// - /// @since 3.15.0 - /// - [JsonConverter(typeof(NumberEnumConverter))] - public enum CompletionItemTag - { - /// - /// Render a completion as obsolete, usually using a strike-out. - /// - Deprecated = 1 - } -} diff --git a/src/Protocol/Models/CompletionList.cs b/src/Protocol/Models/CompletionList.cs deleted file mode 100644 index 01df44d59..000000000 --- a/src/Protocol/Models/CompletionList.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents a collection of [completion items](#CompletionItem) to be presented - /// in the editor. - /// - [JsonConverter(typeof(CompletionListConverter))] - public class CompletionList : Container - { - public CompletionList() : base(Enumerable.Empty()) - { - } - - public CompletionList(bool isIncomplete) : base(Enumerable.Empty()) => IsIncomplete = isIncomplete; - - public CompletionList(IEnumerable items) : base(items) - { - } - - public CompletionList(IEnumerable items, bool isIncomplete) : base(items) => IsIncomplete = isIncomplete; - - public CompletionList(params CompletionItem[] items) : base(items) - { - } - - public CompletionList(bool isIncomplete, params CompletionItem[] items) : base(items) => IsIncomplete = isIncomplete; - - /// - /// This list it not complete. Further typing should result in recomputing - /// this list. - /// - public bool IsIncomplete { get; } - - /// - /// The completion items. - /// - public IEnumerable Items => this; - - public static implicit operator CompletionList(CompletionItem[] items) => new CompletionList(items); - - public static implicit operator CompletionList(Collection items) => new CompletionList(items); - - public static implicit operator CompletionList(List items) => new CompletionList(items); - - public static implicit operator CompletionItem[](CompletionList list) => list.ToArray(); - } - - /// - /// Represents a collection of [completion items](#CompletionItem) to be presented - /// in the editor. - /// - public class CompletionList : Container> where T : HandlerIdentity?, new() - { - public CompletionList() : base(Enumerable.Empty>()) - { - } - - public CompletionList(bool isIncomplete) : base(Enumerable.Empty>()) => IsIncomplete = isIncomplete; - - public CompletionList(IEnumerable> items) : base(items) - { - } - - public CompletionList(IEnumerable> items, bool isIncomplete) : base(items) => IsIncomplete = isIncomplete; - - public CompletionList(params CompletionItem[] items) : base(items) - { - } - - public CompletionList(bool isIncomplete, params CompletionItem[] items) : base(items) => IsIncomplete = isIncomplete; - - /// - /// This list it not complete. Further typing should result in recomputing - /// this list. - /// - public bool IsIncomplete { get; } - - /// - /// The completion items. - /// - public IEnumerable> Items => this; - - public static implicit operator CompletionList(CompletionItem[] items) => new CompletionList(items); - - public static implicit operator CompletionList(Collection> items) => new CompletionList(items); - - public static implicit operator CompletionList(List> items) => new CompletionList(items); - - public static implicit operator CompletionItem[](CompletionList list) => list.ToArray(); - - public static implicit operator CompletionList(CompletionList container) => new CompletionList(container.Select(z => (CompletionItem) z)); - } -} diff --git a/src/Protocol/Models/CompletionParams.cs b/src/Protocol/Models/CompletionParams.cs deleted file mode 100644 index 4aaf1b941..000000000 --- a/src/Protocol/Models/CompletionParams.cs +++ /dev/null @@ -1,20 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Completion, Direction.ClientToServer)] - public class CompletionParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - /// The completion context. This is only available it the client specifies to send - /// this using `Capability.textDocument.completion.contextSupport === true` - /// - [Optional] - public CompletionContext? Context { get; set; } - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/CompletionRegistrationOptions.cs b/src/Protocol/Models/CompletionRegistrationOptions.cs deleted file mode 100644 index 5f01eb09e..000000000 --- a/src/Protocol/Models/CompletionRegistrationOptions.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class CompletionRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// The server provides support to resolve additional - /// information for a completion item. - /// - [Optional] - public bool ResolveProvider { get; set; } - - /// - /// Most tools trigger completion request automatically without explicitly requesting - /// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user - /// starts to type an identifier. For example if the user types `c` in a JavaScript file - /// code complete will automatically pop up present `console` besides others as a - /// completion item. Characters that make up identifiers don't need to be listed here. - /// - /// If code complete should automatically be trigger on characters not being valid inside - /// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. - /// - [Optional] - public Container? TriggerCharacters { get; set; } - - /// - /// The list of all possible characters that commit a completion. This field can be used - /// if clients don't support individual commmit characters per completion item. See - /// `Capability.textDocument.completion.completionItem.commitCharactersSupport` - /// - /// @since 3.2.0 - /// - [Optional] - public Container? AllCommitCharacters { get; set; } - - /// - /// Completion options. - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// The server provides support to resolve additional - /// information for a completion item. - /// - [Optional] - public bool ResolveProvider { get; set; } - - /// - /// Most tools trigger completion request automatically without explicitly requesting - /// it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user - /// starts to type an identifier. For example if the user types `c` in a JavaScript file - /// code complete will automatically pop up present `console` besides others as a - /// completion item. Characters that make up identifiers don't need to be listed here. - /// - /// If code complete should automatically be trigger on characters not being valid inside - /// an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. - /// - [Optional] - public Container? TriggerCharacters { get; set; } - - /// - /// The list of all possible characters that commit a completion. This field can be used - /// if clients don't support individual commmit characters per completion item. See - /// `Capability.textDocument.completion.completionItem.commitCharactersSupport` - /// - /// @since 3.2.0 - /// - [Optional] - public Container? AllCommitCharacters { get; set; } - } - - class CompletionRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public CompletionRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.CompletionProvider)) - { - _handlersManager = handlersManager; - } - - public override StaticOptions Convert(CompletionRegistrationOptions source) - { - return new StaticOptions { - ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICompletionResolveHandler)), - AllCommitCharacters = source.AllCommitCharacters, - TriggerCharacters = source.TriggerCharacters, - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } - } -} diff --git a/src/Protocol/Models/CompletionTriggerKind.cs b/src/Protocol/Models/CompletionTriggerKind.cs deleted file mode 100644 index ab5f71446..000000000 --- a/src/Protocol/Models/CompletionTriggerKind.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(NumberEnumConverter))] - public enum CompletionTriggerKind - { - /// - /// Completion was triggered by typing an identifier (24x7 code complete), manual invocation (e.g Ctrl+Space) or via API. - /// - Invoked = 1, - - /// - /// Completion was triggered by a trigger character specified by the `triggerCharacters` properties of the `CompletionRegistrationOptions`. - /// - TriggerCharacter = 2, - - /// - /// Completion was re-triggered as the current completion list is incomplete. - /// - TriggerForIncompleteCompletions = 3, - } -} diff --git a/src/Protocol/Models/ConfigurationItem.cs b/src/Protocol/Models/ConfigurationItem.cs deleted file mode 100644 index 672e31fe2..000000000 --- a/src/Protocol/Models/ConfigurationItem.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ConfigurationItem : IEquatable - { - [Optional] public DocumentUri? ScopeUri { get; set; } - [Optional] public string? Section { get; set; } - - public bool Equals(ConfigurationItem? other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return Equals(ScopeUri, other.ScopeUri) && Section == other.Section; - } - - public override bool Equals(object? obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((ConfigurationItem)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ( ( ScopeUri is not null ? ScopeUri.GetHashCode() : 0 ) * 397 ) ^ ( Section is not 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); - } -} diff --git a/src/Protocol/Models/ConfigurationParams.cs b/src/Protocol/Models/ConfigurationParams.cs deleted file mode 100644 index 8c7ee080e..000000000 --- a/src/Protocol/Models/ConfigurationParams.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.Configuration, Direction.ServerToClient)] - public class ConfigurationParams : IRequest> - { - public Container Items { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/Container.cs b/src/Protocol/Models/Container.cs index 45aa40737..097abf5f3 100644 --- a/src/Protocol/Models/Container.cs +++ b/src/Protocol/Models/Container.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using System.Collections.Immutable; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models @@ -18,10 +20,70 @@ public Container(params T[] items) : base(items) { } - public static implicit operator Container(T[] items) => new Container(items); + [return: NotNullIfNotNull("items")] + public static Container? From(IEnumerable? items) => items switch { + not null => new Container(items), + _ => null + }; - public static implicit operator Container(Collection items) => new Container(items); + [return: NotNullIfNotNull("items")] + public static implicit operator Container?(T[] items) => items switch { + not null => new Container(items), + _ => null + }; - public static implicit operator Container(List items) => new Container(items); + [return: NotNullIfNotNull("items")] + public static Container? From(params T[] items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static implicit operator Container?(Collection? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static Container? From(Collection? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static implicit operator Container?(List? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static Container? From(List? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static implicit operator Container?(in ImmutableArray? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static Container? From(in ImmutableArray? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static implicit operator Container?(ImmutableList? items) => items switch { + not null => new Container(items), + _ => null + }; + + [return: NotNullIfNotNull("items")] + public static Container? From(ImmutableList? items) => items switch { + not null => new Container(items), + _ => null + }; } } diff --git a/src/Protocol/Models/DeclarationParams.cs b/src/Protocol/Models/DeclarationParams.cs deleted file mode 100644 index f66e39e16..000000000 --- a/src/Protocol/Models/DeclarationParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Declaration, Direction.ClientToServer)] - public class DeclarationParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/DeclarationRegistrationOptions.cs b/src/Protocol/Models/DeclarationRegistrationOptions.cs deleted file mode 100644 index cf11106b4..000000000 --- a/src/Protocol/Models/DeclarationRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DeclarationRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions { } - - class DeclarationRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DeclarationRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DeclarationProvider)) - { - } - public override StaticOptions Convert(DeclarationRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/DefinitionParams.cs b/src/Protocol/Models/DefinitionParams.cs deleted file mode 100644 index 94e39a3e5..000000000 --- a/src/Protocol/Models/DefinitionParams.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Definition, Direction.ClientToServer)] - public class DefinitionParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/DefinitionRegistrationOptions.cs b/src/Protocol/Models/DefinitionRegistrationOptions.cs deleted file mode 100644 index 0547d3532..000000000 --- a/src/Protocol/Models/DefinitionRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DefinitionRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions { } - - class DefinitionRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DefinitionRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DefinitionProvider)) - { - } - public override StaticOptions Convert(DefinitionRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/Diagnostic.cs b/src/Protocol/Models/Diagnostic.cs index d8d296539..9ee4ee282 100644 --- a/src/Protocol/Models/Diagnostic.cs +++ b/src/Protocol/Models/Diagnostic.cs @@ -1,12 +1,17 @@ +using System; using System.Diagnostics; using System.Linq; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class Diagnostic : ICanHaveData + [GenerateTypedData] + public partial class Diagnostic : ICanHaveData { /// /// The range at which the message applies. @@ -75,111 +80,111 @@ public class Diagnostic : ICanHaveData $" {( Message?.Length > 20 ? Message.Substring(0, 20) : Message )}"; } - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class Diagnostic : ICanHaveData - where T : class?, new() + [JsonConverter(typeof(DiagnosticCodeConverter))] + public struct DiagnosticCode { - /// - /// The range at which the message applies. - /// - public Range Range { get; set; } = null!; + public DiagnosticCode(long value) + { + Long = value; + String = null; + } + public DiagnosticCode(string value) + { + Long = 0; + String = value; + } + + public bool IsLong => String == null; + public long Long { get; set; } + public bool IsString => String != null; + public string? String { get; set; } + + public static implicit operator DiagnosticCode(long value) => new DiagnosticCode(value); + + public static implicit operator DiagnosticCode(string value) => new DiagnosticCode(value); + + public static implicit operator long(DiagnosticCode value) => value.IsLong ? value.Long : 0; + + public static implicit operator string?(DiagnosticCode value) => value.IsString ? value.String : null; + } + + [JsonConverter(typeof(NumberEnumConverter))] + public enum DiagnosticSeverity + { /// - /// The diagnostic's severity. Can be omitted. If omitted it is up to the - /// client to interpret diagnostics as error, warning, info or hint. + /// Reports an error. /// - [Optional] - public DiagnosticSeverity? Severity { get; set; } + Error = 1, /// - /// The diagnostic's code. Can be omitted. + /// Reports a warning. /// - [Optional] - public DiagnosticCode? Code { get; set; } + Warning = 2, /// - /// An optional property to describe the error code. - /// - /// @since 3.16.0 - proposed state + /// Reports an information. /// - [Optional] - public CodeDescription? CodeDescription { get; set; } + Information = 3, /// - /// A human-readable string describing the source of this - /// diagnostic, e.g. 'typescript' or 'super lint'. + /// Reports a hint. /// - [Optional] - public string? Source { get; set; } + Hint = 4, + } + /// + /// The diagnostic tags. + /// + /// @since 3.15.0 + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum DiagnosticTag + { /// - /// The diagnostic's message. + /// Unused or unnecessary code. + /// + /// Clients are allowed to render diagnostics with this tag faded out instead of having + /// an error squiggle. /// - public string Message { get; set; } = null!; + Unnecessary = 1, /// - /// Additional metadata about the diagnostic. + /// Deprecated or obsolete code. /// - /// @since 3.15.0 + /// Clients are allowed to rendered diagnostics with this tag strike through. /// - [Optional] - public Container? Tags { get; set; } + Deprecated = 2, + } + /// + /// Structure to capture a description for an error code. + /// + /// @since 3.16.0 - proposed state + /// + public class CodeDescription + { /// - /// An array of related diagnostic information, e.g. when symbol-names within - /// a scope collide all definitions can be marked via this property. + /// An URI to open with more information about the diagnostic error. /// - [Optional] - public Container? RelatedInformation { get; set; } + public Uri Href { get; set; } = null!; + } + /// + /// Represents a related message and source code location for a diagnostic. This should be + /// used to point to code locations that cause or related to a diagnostics, e.g when duplicating + /// a symbol in a scope. + /// + public class DiagnosticRelatedInformation + { /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. + /// The location of this related diagnostic information. /// - public T Data - { - get => ( (ICanHaveData) this ).Data?.ToObject()!; - set => ( (ICanHaveData) this ).Data = JToken.FromObject(value); - } - - JToken? ICanHaveData.Data { get; set; } - - public static implicit operator Diagnostic(Diagnostic value) => new Diagnostic { - Data = ( (ICanHaveData) value ).Data, - Code = value.Code, - Message = value.Message, - Range = value.Range, - Severity = value.Severity, - Source = value.Source, - Tags = value.Tags, - CodeDescription = value.CodeDescription, - RelatedInformation = value.RelatedInformation - }; - - public static implicit operator Diagnostic(Diagnostic value) - { - var item = new Diagnostic { - Code = value.Code, - Message = value.Message, - Range = value.Range, - Severity = value.Severity, - Source = value.Source, - Tags = value.Tags, - CodeDescription = value.CodeDescription, - RelatedInformation = value.RelatedInformation - }; - ( (ICanHaveData) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => - $"{( Code.HasValue ? $"[{Code.Value.ToString()}]" : "" )}" + - $"{Range}" + - $"{( string.IsNullOrWhiteSpace(Source) ? "" : $" ({Source})" )}" + - $"{( Tags?.Any() == true ? $" [tags: {string.Join(", ", Tags.Select(z => z.ToString()))}]" : "" )}" + - $" {( Message?.Length > 20 ? Message.Substring(0, 20) : Message )}"; + public Location Location { get; set; } = null!; - /// - public override string ToString() => DebuggerDisplay; + /// + /// The message of this related diagnostic information. + /// + public string Message { get; set; } = null!; } } diff --git a/src/Protocol/Models/DiagnosticCode.cs b/src/Protocol/Models/DiagnosticCode.cs deleted file mode 100644 index 7f29d2175..000000000 --- a/src/Protocol/Models/DiagnosticCode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(DiagnosticCodeConverter))] - public struct DiagnosticCode - { - public DiagnosticCode(long value) - { - Long = value; - String = null; - } - - public DiagnosticCode(string value) - { - Long = 0; - String = value; - } - - public bool IsLong => String == null; - public long Long { get; set; } - public bool IsString => String != null; - public string? String { get; set; } - - public static implicit operator DiagnosticCode(long value) => new DiagnosticCode(value); - - public static implicit operator DiagnosticCode(string value) => new DiagnosticCode(value); - - public static implicit operator long(DiagnosticCode value) => value.IsLong ? value.Long : 0; - - public static implicit operator string?(DiagnosticCode value) => value.IsString ? value.String : null; - } -} diff --git a/src/Protocol/Models/DiagnosticRelatedInformation.cs b/src/Protocol/Models/DiagnosticRelatedInformation.cs deleted file mode 100644 index c02aaa24d..000000000 --- a/src/Protocol/Models/DiagnosticRelatedInformation.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents a related message and source code location for a diagnostic. This should be - /// used to point to code locations that cause or related to a diagnostics, e.g when duplicating - /// a symbol in a scope. - /// - public class DiagnosticRelatedInformation - { - /// - /// The location of this related diagnostic information. - /// - public Location Location { get; set; } = null!; - - /// - /// The message of this related diagnostic information. - /// - public string Message { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DiagnosticSeverity.cs b/src/Protocol/Models/DiagnosticSeverity.cs deleted file mode 100644 index 18c9147ca..000000000 --- a/src/Protocol/Models/DiagnosticSeverity.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(NumberEnumConverter))] - public enum DiagnosticSeverity - { - /// - /// Reports an error. - /// - Error = 1, - - /// - /// Reports a warning. - /// - Warning = 2, - - /// - /// Reports an information. - /// - Information = 3, - - /// - /// Reports a hint. - /// - Hint = 4, - } -} diff --git a/src/Protocol/Models/DiagnosticTag.cs b/src/Protocol/Models/DiagnosticTag.cs deleted file mode 100644 index e444c1f68..000000000 --- a/src/Protocol/Models/DiagnosticTag.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The diagnostic tags. - /// - /// @since 3.15.0 - /// - [JsonConverter(typeof(NumberEnumConverter))] - public enum DiagnosticTag - { - /// - /// Unused or unnecessary code. - /// - /// Clients are allowed to render diagnostics with this tag faded out instead of having - /// an error squiggle. - /// - Unnecessary = 1, - - /// - /// Deprecated or obsolete code. - /// - /// Clients are allowed to rendered diagnostics with this tag strike through. - /// - Deprecated = 2, - } -} diff --git a/src/Protocol/Models/DidChangeConfigurationParams.cs b/src/Protocol/Models/DidChangeConfigurationParams.cs deleted file mode 100644 index 8fa61a79a..000000000 --- a/src/Protocol/Models/DidChangeConfigurationParams.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.DidChangeConfiguration, Direction.ClientToServer)] - public class DidChangeConfigurationParams : IRequest - { - /// - /// The actual changed settings - /// - public JToken? Settings { get; set; } - } -} diff --git a/src/Protocol/Models/DidChangeTextDocumentParams.cs b/src/Protocol/Models/DidChangeTextDocumentParams.cs deleted file mode 100644 index efb5c8fd2..000000000 --- a/src/Protocol/Models/DidChangeTextDocumentParams.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DidChange, Direction.ClientToServer)] - public class DidChangeTextDocumentParams : IRequest - { - /// - /// The document that did change. The version number points - /// to the version after all provided content changes have - /// been applied. - /// - public VersionedTextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The actual content changes. - /// - public Container ContentChanges { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DidChangeWatchedFilesParams.cs b/src/Protocol/Models/DidChangeWatchedFilesParams.cs deleted file mode 100644 index 8a89aa416..000000000 --- a/src/Protocol/Models/DidChangeWatchedFilesParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.DidChangeWatchedFiles, Direction.ClientToServer)] - public class DidChangeWatchedFilesParams : IRequest - { - /// - /// The actual file events. - /// - public Container Changes { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DidChangeWatchedFilesRegistrationOptions.cs b/src/Protocol/Models/DidChangeWatchedFilesRegistrationOptions.cs deleted file mode 100644 index 99a8a3ef3..000000000 --- a/src/Protocol/Models/DidChangeWatchedFilesRegistrationOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DidChangeWatchedFilesRegistrationOptions - { - /// - /// The watchers to register. - /// - [Optional] - public Container? Watchers { get; set; } - } -} diff --git a/src/Protocol/Models/DidChangeWorkspaceFoldersParams.cs b/src/Protocol/Models/DidChangeWorkspaceFoldersParams.cs deleted file mode 100644 index 14d847b48..000000000 --- a/src/Protocol/Models/DidChangeWorkspaceFoldersParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.DidChangeWorkspaceFolders, Direction.ClientToServer)] - public class DidChangeWorkspaceFoldersParams : IRequest - { - /// - /// The actual workspace folder change event. - /// - public WorkspaceFoldersChangeEvent Event { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DidCloseTextDocumentParams.cs b/src/Protocol/Models/DidCloseTextDocumentParams.cs deleted file mode 100644 index 484c74cc4..000000000 --- a/src/Protocol/Models/DidCloseTextDocumentParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DidClose, Direction.ClientToServer)] - public class DidCloseTextDocumentParams : ITextDocumentIdentifierParams, IRequest - { - /// - /// The document that was closed. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DidOpenTextDocumentParams.cs b/src/Protocol/Models/DidOpenTextDocumentParams.cs deleted file mode 100644 index 092defc4e..000000000 --- a/src/Protocol/Models/DidOpenTextDocumentParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DidOpen, Direction.ClientToServer)] - public class DidOpenTextDocumentParams : IRequest - { - /// - /// The document that was opened. - /// - public TextDocumentItem TextDocument { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DidSaveTextDocumentParams.cs b/src/Protocol/Models/DidSaveTextDocumentParams.cs deleted file mode 100644 index bce389f2a..000000000 --- a/src/Protocol/Models/DidSaveTextDocumentParams.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DidSave, Direction.ClientToServer)] - public class DidSaveTextDocumentParams : ITextDocumentIdentifierParams, IRequest - { - /// - /// The document that was saved. - /// - /// - /// TODO: Change to RequiredVersionedTextDocumentIdentifier (or in the future will be VersionedTextDocumentIdentifier) - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// Optional the content when saved. Depends on the includeText value - /// when the save notification was requested. - /// - [Optional] - public string? Text { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentColor.cs b/src/Protocol/Models/DocumentColor.cs deleted file mode 100644 index 18f0d5f81..000000000 --- a/src/Protocol/Models/DocumentColor.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Diagnostics; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents a color in RGBA space. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class DocumentColor - { - /// - /// The red component of this color in the range [0-1]. - /// - public double Red { get; set; } - - /// - /// The green component of this color in the range [0-1]. - /// - public double Green { get; set; } - - /// - /// The blue component of this color in the range [0-1]. - /// - public double Blue { get; set; } - - /// - /// The alpha component of this color in the range [0-1]. - /// - public double Alpha { get; set; } - - private string DebuggerDisplay => $"R:{Red} G:{Green} B:{Blue} A:{Alpha}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/DocumentColorParams.cs b/src/Protocol/Models/DocumentColorParams.cs deleted file mode 100644 index e898379fc..000000000 --- a/src/Protocol/Models/DocumentColorParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DocumentColor, Direction.ClientToServer)] - public class DocumentColorParams : IPartialItemsRequest, ColorInformation>, IWorkDoneProgressParams - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentColorRegistrationOptions.cs b/src/Protocol/Models/DocumentColorRegistrationOptions.cs deleted file mode 100644 index 572b39d8f..000000000 --- a/src/Protocol/Models/DocumentColorRegistrationOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentColorRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions - { - } - - class DocumentColorRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DocumentColorRegistrationOptionsConverter() : base(nameof(ServerCapabilities.ColorProvider)) - { - } - public override StaticOptions Convert(DocumentColorRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/DocumentFormattingParams.cs b/src/Protocol/Models/DocumentFormattingParams.cs deleted file mode 100644 index 8fb0b8811..000000000 --- a/src/Protocol/Models/DocumentFormattingParams.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DocumentFormatting, Direction.ClientToServer)] - public class DocumentFormattingParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams - { - /// - /// The document to format. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The format options. - /// - public FormattingOptions Options { get; set; } = null!; - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentFormattingRegistrationOptions.cs b/src/Protocol/Models/DocumentFormattingRegistrationOptions.cs deleted file mode 100644 index e76d70b17..000000000 --- a/src/Protocol/Models/DocumentFormattingRegistrationOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentFormattingRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions - { - } - - class DocumentFormattingRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DocumentFormattingRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DocumentFormattingProvider)) - { - } - public override StaticOptions Convert(DocumentFormattingRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/DocumentHighlight.cs b/src/Protocol/Models/DocumentHighlight.cs deleted file mode 100644 index 316a07a7f..000000000 --- a/src/Protocol/Models/DocumentHighlight.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A document highlight is a range inside a text document which deserves - /// special attention. Usually a document highlight is visualized by changing - /// the background color of its range. - /// - /// - public class DocumentHighlight - { - /// - /// The range this highlight applies to. - /// - public Range Range { get; set; } = null!; - - /// - /// The highlight kind, default is DocumentHighlightKind.Text. - /// - public DocumentHighlightKind Kind { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentHighlightContainer.cs b/src/Protocol/Models/DocumentHighlightContainer.cs deleted file mode 100644 index ffed1720e..000000000 --- a/src/Protocol/Models/DocumentHighlightContainer.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentHighlightContainer : Container - { - public DocumentHighlightContainer() : this(Enumerable.Empty()) - { - } - - public DocumentHighlightContainer(IEnumerable items) : base(items) - { - } - - public DocumentHighlightContainer(params DocumentHighlight[] items) : base(items) - { - } - - public static implicit operator DocumentHighlightContainer(DocumentHighlight[] items) => new DocumentHighlightContainer(items); - - public static implicit operator DocumentHighlightContainer(Collection items) => new DocumentHighlightContainer(items); - - public static implicit operator DocumentHighlightContainer(List items) => new DocumentHighlightContainer(items); - } -} diff --git a/src/Protocol/Models/DocumentHighlightKind.cs b/src/Protocol/Models/DocumentHighlightKind.cs deleted file mode 100644 index 9661345aa..000000000 --- a/src/Protocol/Models/DocumentHighlightKind.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A document highlight kind. - /// - [JsonConverter(typeof(NumberEnumConverter))] - public enum DocumentHighlightKind - { - /// - /// A textual occurrence. - /// - Text = 1, - - /// - /// Read-access of a symbol, like reading a variable. - /// - Read = 2, - - /// - /// Write-access of a symbol, like writing to a variable. - /// - Write = 3, - } -} diff --git a/src/Protocol/Models/DocumentHighlightParams.cs b/src/Protocol/Models/DocumentHighlightParams.cs deleted file mode 100644 index 78bfe8b4e..000000000 --- a/src/Protocol/Models/DocumentHighlightParams.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DocumentHighlight, Direction.ClientToServer)] - public class DocumentHighlightParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentHighlightRegistrationOptions.cs b/src/Protocol/Models/DocumentHighlightRegistrationOptions.cs deleted file mode 100644 index a55e6c1ab..000000000 --- a/src/Protocol/Models/DocumentHighlightRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentHighlightRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions { } - - class DocumentHighlightRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DocumentHighlightRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DocumentHighlightProvider)) - { - } - public override StaticOptions Convert(DocumentHighlightRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/DocumentLink.cs b/src/Protocol/Models/DocumentLink.cs deleted file mode 100644 index 00dd163bc..000000000 --- a/src/Protocol/Models/DocumentLink.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Diagnostics; -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A document link is a range in a text document that links to an internal or external resource, like another - /// text document or a web site. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - [Method(TextDocumentNames.DocumentLinkResolve, Direction.ClientToServer)] - public class DocumentLink : ICanBeResolved, IRequest - { - /// - /// The range this link applies to. - /// - public Range Range { get; set; } = null!; - - /// - /// The uri this link points to. If missing a resolve request is sent later. - /// - [Optional] - public DocumentUri? Target { get; set; } - - /// - /// A data entry field that is preserved on a document link between a - /// DocumentLinkRequest and a DocumentLinkResolveRequest. - /// - [Optional] - public JToken? Data { get; set; } - - /// - /// The tooltip text when you hover over this link. - /// - /// If a tooltip is provided, is will be displayed in a string that includes instructions on how to - /// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, - /// user settings, and localization. - /// - /// @since 3.15.0 - /// - [Optional] - public string? Tooltip { get; set; } - - private string DebuggerDisplay => $"{Range}{( Target is not null ? $" {Target}" : "" )}{( string.IsNullOrWhiteSpace(Tooltip) ? $" {Tooltip}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } - - /// - /// A document link is a range in a text document that links to an internal or external resource, like another - /// text document or a web site. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class DocumentLink : ICanBeResolved - where T : HandlerIdentity?, new() - { - /// - /// The range this link applies to. - /// - public Range Range { get; set; } = null!; - - /// - /// The uri this link points to. If missing a resolve request is sent later. - /// - [Optional] - public DocumentUri? Target { get; set; } - - /// - /// The tooltip text when you hover over this link. - /// - /// If a tooltip is provided, is will be displayed in a string that includes instructions on how to - /// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, - /// user settings, and localization. - /// - /// @since 3.15.0 - /// - [Optional] - public string? Tooltip { get; set; } - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - [Optional] - public T Data - { - get => ( (ICanBeResolved) this ).Data?.ToObject()!; - set => ( (ICanBeResolved) this ).Data = JToken.FromObject(value); - } - - JToken? ICanBeResolved.Data { get; set; } - - public static implicit operator DocumentLink(DocumentLink value) => new DocumentLink { - Data = ( (ICanBeResolved) value ).Data, - Range = value.Range, - Target = value.Target, - Tooltip = value.Tooltip, - }; - - public static implicit operator DocumentLink(DocumentLink value) - { - var item = new DocumentLink { - Range = value.Range, - Target = value.Target, - Tooltip = value.Tooltip, - }; - ( (ICanBeResolved) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => $"{Range}{( Target is not null ? $" {Target}" : "" )}{( string.IsNullOrWhiteSpace(Tooltip) ? $" {Tooltip}" : "" )}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/DocumentLinkContainer.cs b/src/Protocol/Models/DocumentLinkContainer.cs deleted file mode 100644 index 381093eb0..000000000 --- a/src/Protocol/Models/DocumentLinkContainer.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentLinkContainer : Container - { - public DocumentLinkContainer() : this(Enumerable.Empty()) - { - } - - public DocumentLinkContainer(IEnumerable items) : base(items) - { - } - - public DocumentLinkContainer(params DocumentLink[] items) : base(items) - { - } - - public static implicit operator DocumentLinkContainer(DocumentLink[] items) => new DocumentLinkContainer(items); - - public static implicit operator DocumentLinkContainer(Collection items) => new DocumentLinkContainer(items); - - public static implicit operator DocumentLinkContainer(List items) => new DocumentLinkContainer(items); - } - - public class DocumentLinkContainer : Container> where T : HandlerIdentity?, new() - { - public DocumentLinkContainer() : this(Enumerable.Empty>()) - { - } - - public DocumentLinkContainer(IEnumerable> items) : base(items) - { - } - - public DocumentLinkContainer(params DocumentLink[] items) : base(items) - { - } - - public static implicit operator DocumentLinkContainer(DocumentLink[] items) => new DocumentLinkContainer(items); - - public static implicit operator DocumentLinkContainer(Collection> items) => new DocumentLinkContainer(items); - - public static implicit operator DocumentLinkContainer(List> items) => new DocumentLinkContainer(items); - - public static implicit operator DocumentLinkContainer(DocumentLinkContainer container) => new DocumentLinkContainer(container.Select(z => (DocumentLink) z)); - } -} diff --git a/src/Protocol/Models/DocumentLinkParams.cs b/src/Protocol/Models/DocumentLinkParams.cs deleted file mode 100644 index 4fd3e3e10..000000000 --- a/src/Protocol/Models/DocumentLinkParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DocumentLink, Direction.ClientToServer)] - public class DocumentLinkParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams - { - /// - /// The document to provide document links for. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentLinkRegistrationOptions.cs b/src/Protocol/Models/DocumentLinkRegistrationOptions.cs deleted file mode 100644 index 695fa8440..000000000 --- a/src/Protocol/Models/DocumentLinkRegistrationOptions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentLinkRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// Document links have a resolve provider as well. - /// - [Optional] - public bool ResolveProvider { get; set; } - /// - /// Document link options - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// Document links have a resolve provider as well. - /// - [Optional] - public bool ResolveProvider { get; set; } - } - - class DocumentLinkRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public DocumentLinkRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.DocumentLinkProvider)) - { - _handlersManager = handlersManager; - } - - public override StaticOptions Convert(DocumentLinkRegistrationOptions source) => new StaticOptions { - ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IDocumentLinkResolveHandler)), - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } -} diff --git a/src/Protocol/Models/DocumentOnTypeFormattingParams.cs b/src/Protocol/Models/DocumentOnTypeFormattingParams.cs deleted file mode 100644 index 70c09817a..000000000 --- a/src/Protocol/Models/DocumentOnTypeFormattingParams.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using Newtonsoft.Json; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.OnTypeFormatting, Direction.ClientToServer)] - public class DocumentOnTypeFormattingParams : ITextDocumentIdentifierParams, IRequest - { - /// - /// The document to format. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The position at which this request was sent. - /// - public Position Position { get; set; } = null!; - - /// - /// The character that has been typed. - /// - [JsonProperty("ch")] - public string Character { get; set; } = null!; - - /// - /// The format options. - /// - public FormattingOptions Options { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/DocumentOnTypeFormattingRegistrationOptions.cs b/src/Protocol/Models/DocumentOnTypeFormattingRegistrationOptions.cs deleted file mode 100644 index e2e1ae82c..000000000 --- a/src/Protocol/Models/DocumentOnTypeFormattingRegistrationOptions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentOnTypeFormattingRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// A character on which formatting should be triggered, like `}`. - /// - public string FirstTriggerCharacter { get; set; } = null!; - - /// - /// More trigger characters. - /// - [Optional] - public Container? MoreTriggerCharacter { get; set; } - - /// - /// Format document on type options - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// A character on which formatting should be triggered, like `}`. - /// - public string FirstTriggerCharacter { get; set; } = null!; - - /// - /// More trigger characters. - /// - [Optional] - public Container? MoreTriggerCharacter { get; set; } - } - - class DocumentOnTypeFormattingRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - - public DocumentOnTypeFormattingRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DocumentOnTypeFormattingProvider)) - { - } - - public override StaticOptions Convert(DocumentOnTypeFormattingRegistrationOptions source) => - new StaticOptions { - FirstTriggerCharacter = source.FirstTriggerCharacter, - MoreTriggerCharacter = source.MoreTriggerCharacter, - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } -} diff --git a/src/Protocol/Models/DocumentRangeFormattingParams.cs b/src/Protocol/Models/DocumentRangeFormattingParams.cs deleted file mode 100644 index 709e2a2a9..000000000 --- a/src/Protocol/Models/DocumentRangeFormattingParams.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.RangeFormatting, Direction.ClientToServer)] - public class DocumentRangeFormattingParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams - { - /// - /// The document to format. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The range to format - /// - public Range Range { get; set; } = null!; - - /// - /// The format options - /// - public FormattingOptions Options { get; set; } = null!; - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentRangeFormattingRegistrationOptions.cs b/src/Protocol/Models/DocumentRangeFormattingRegistrationOptions.cs deleted file mode 100644 index ce1369eea..000000000 --- a/src/Protocol/Models/DocumentRangeFormattingRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentRangeFormattingRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions { } - - class DocumentRangeFormattingRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DocumentRangeFormattingRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DocumentRangeFormattingProvider)) - { - } - public override StaticOptions Convert(DocumentRangeFormattingRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/DocumentSymbol.cs b/src/Protocol/Models/DocumentSymbol.cs deleted file mode 100644 index c723e863e..000000000 --- a/src/Protocol/Models/DocumentSymbol.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be - /// hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range, - /// e.g. the range of an identifier. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class DocumentSymbol - { - /// - /// The name of this symbol. - /// - public string Name { get; set; } = null!; - - /// - /// More detail for this symbol, e.g the signature of a function. If not provided the - /// name is used. - /// - [Optional] - public string? Detail { get; set; } - - /// - /// The kind of this symbol. - /// - public SymbolKind Kind { get; set; } - - /// - /// Tags for this document symbol. - /// - /// @since 3.16.0 - Proposed state - /// - [Obsolete(Constants.Proposal)] - [Optional] - public Container? Tags { get; set; } - - /// - /// Indicates if this symbol is deprecated. - /// - [Optional] - public bool Deprecated { get; set; } - - /// - /// The range enclosing this symbol not including leading/trailing whitespace but everything else - /// like comments. This information is typically used to determine if the the clients cursor is - /// inside the symbol to reveal in the symbol in the UI. - /// - public Range Range { get; set; } = null!; - - /// - /// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. - /// Must be contained by the the `range`. - /// - public Range SelectionRange { get; set; } = null!; - - /// - /// Children of this symbol, e.g. properties of a class. - /// - [Optional] - public Container? Children { get; set; } - - private string DebuggerDisplay => $"[{Kind}] {Name} {{ range: {Range}, selection: {SelectionRange}, detail: {Detail ?? string.Empty} }}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/DocumentSymbolParams.cs b/src/Protocol/Models/DocumentSymbolParams.cs deleted file mode 100644 index 4061b293c..000000000 --- a/src/Protocol/Models/DocumentSymbolParams.cs +++ /dev/null @@ -1,23 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.DocumentSymbol, Direction.ClientToServer)] - public class DocumentSymbolParams : ITextDocumentIdentifierParams, IPartialItemsRequest, - IWorkDoneProgressParams - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/DocumentSymbolRegistrationOptions.cs b/src/Protocol/Models/DocumentSymbolRegistrationOptions.cs deleted file mode 100644 index cac2d58cf..000000000 --- a/src/Protocol/Models/DocumentSymbolRegistrationOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class DocumentSymbolRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// A human-readable string that is shown when multiple outlines trees - /// are shown for the same document. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public string? Label { get; set; } - - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// A human-readable string that is shown when multiple outlines trees - /// are shown for the same document. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public string? Label { get; set; } - } - - class DocumentSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public DocumentSymbolRegistrationOptionsConverter() : base(nameof(ServerCapabilities.DocumentSymbolProvider)) - { - } - - public override StaticOptions Convert(DocumentSymbolRegistrationOptions source) => - new StaticOptions { Label = source.Label, WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/ExecuteCommandParams.cs b/src/Protocol/Models/ExecuteCommandParams.cs deleted file mode 100644 index e89842246..000000000 --- a/src/Protocol/Models/ExecuteCommandParams.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] - public class ExecuteCommandParams : IRequest, IWorkDoneProgressParams, IExecuteCommandParams - { - /// - /// The identifier of the actual command handler. - /// - public string Command { get; set; } = null!; - - /// - /// Arguments that the command should be invoked with. - /// - [Optional] - public JArray? Arguments { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/ExecuteCommandRegistrationOptions.cs b/src/Protocol/Models/ExecuteCommandRegistrationOptions.cs deleted file mode 100644 index cf828482e..000000000 --- a/src/Protocol/Models/ExecuteCommandRegistrationOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Shared; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Execute command registration options. - /// - public class ExecuteCommandRegistrationOptions : WorkDoneProgressOptions, IRegistrationOptions - { - /// - /// The commands to be executed on the server - /// - public Container Commands { get; set; } = null!; - - /// - /// Execute command options. - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// The commands to be executed on the server - /// - public Container Commands { get; set; } = null!; - } - - class ExecuteCommandRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public ExecuteCommandRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.ExecuteCommandProvider)) - { - _handlersManager = handlersManager; - } - public override StaticOptions Convert(ExecuteCommandRegistrationOptions source) - { - var allRegistrationOptions = _handlersManager.Descriptors - .OfType() - .Where(z => z.HasRegistration) - .Select(z => z.RegistrationOptions) - .OfType() - .ToArray(); - return new StaticOptions { - Commands = allRegistrationOptions - .SelectMany(z => z.Commands) - .ToArray(), - WorkDoneProgress = allRegistrationOptions.Any(x => x.WorkDoneProgress) - }; - } - } - } -} diff --git a/src/Protocol/Models/ExitRequest.cs b/src/Protocol/Models/ExitRequest.cs deleted file mode 100644 index 9a3a301b1..000000000 --- a/src/Protocol/Models/ExitRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.Exit, Direction.ClientToServer)] - public class ExitParams : IRequest - { - public static ExitParams Instance { get; } = new ExitParams(); - } -} diff --git a/src/Protocol/Models/FoldingRange.cs b/src/Protocol/Models/FoldingRange.cs deleted file mode 100644 index b61468e5f..000000000 --- a/src/Protocol/Models/FoldingRange.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents a folding range. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class FoldingRange - { - /// - /// The zero-based line number from where the folded range starts. - /// - /// - /// TODO: UPDATE THIS next version - /// in the LSP spec - /// - public long StartLine { get; set; } - - /// - /// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. - /// - /// - /// TODO: UPDATE THIS next version - /// in the LSP spec - /// - [Optional] - public long? StartCharacter { get; set; } - - /// - /// The zero-based line number where the folded range ends. - /// - /// - /// TODO: UPDATE THIS next version - /// in the LSP spec - /// - public long EndLine { get; set; } - - /// - /// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. - /// - /// - /// TODO: UPDATE THIS next version - /// in the LSP spec - /// - [Optional] - public long? EndCharacter { get; set; } - - /// - /// Describes the kind of the folding range such as `comment' or 'region'. The kind - /// is used to categorize folding ranges and used by commands like 'Fold all comments'. See - /// [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. - /// - [Optional] - public FoldingRangeKind? Kind { get; set; } - - private string DebuggerDisplay => - $"[start: (line: {StartLine}{( StartCharacter.HasValue ? $", char: {StartCharacter}" : string.Empty )}), end: (line: {EndLine}, char: {( EndCharacter.HasValue ? $", char: {EndCharacter}" : string.Empty )})]"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/FoldingRangeKind.cs b/src/Protocol/Models/FoldingRangeKind.cs deleted file mode 100644 index e2fba0a00..000000000 --- a/src/Protocol/Models/FoldingRangeKind.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Runtime.Serialization; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Enum of known range kinds - /// - [JsonConverter(typeof(StringEnumConverter))] - public enum FoldingRangeKind - { - /// - /// Folding range for a comment - /// - [EnumMember(Value = "comment")] Comment, - - /// - /// Folding range for a imports or includes - /// - [EnumMember(Value = "imports")] Imports, - - /// - /// Folding range for a region (e.g. `#region`) - /// - [EnumMember(Value = "region")] Region - } -} diff --git a/src/Protocol/Models/FoldingRangeParam.cs b/src/Protocol/Models/FoldingRangeParam.cs deleted file mode 100644 index ffc0be0ba..000000000 --- a/src/Protocol/Models/FoldingRangeParam.cs +++ /dev/null @@ -1,22 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.FoldingRange, Direction.ClientToServer)] - public class FoldingRangeRequestParam : ITextDocumentIdentifierParams, IPartialItemsRequest?, FoldingRange>, IWorkDoneProgressParams - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/FoldingRangeRegistrationOptions.cs b/src/Protocol/Models/FoldingRangeRegistrationOptions.cs deleted file mode 100644 index 8d9ba000a..000000000 --- a/src/Protocol/Models/FoldingRangeRegistrationOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class FoldingRangeRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions - { - } - - class FoldingRangeRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public FoldingRangeRegistrationOptionsConverter() : base(nameof(ServerCapabilities.FoldingRangeProvider)) - { - } - - public override StaticOptions Convert(FoldingRangeRegistrationOptions source) => new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - DocumentSelector = source.DocumentSelector - }; - } - } -} diff --git a/src/Protocol/Models/Hover.cs b/src/Protocol/Models/Hover.cs deleted file mode 100644 index 4cf6a04cb..000000000 --- a/src/Protocol/Models/Hover.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The result of a hover request. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class Hover - { - /// - /// The hover's content - /// - public MarkedStringsOrMarkupContent Contents { get; set; } = null!; - - /// - /// An optional range is a range inside a text document - /// that is used to visualize a hover, e.g. by changing the background color. - /// - [Optional] - public Range? Range { get; set; } - - private string DebuggerDisplay => $"{Contents}{( Range is not null ? $" {Range}" : string.Empty )}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/HoverParams.cs b/src/Protocol/Models/HoverParams.cs deleted file mode 100644 index 3d19f8b58..000000000 --- a/src/Protocol/Models/HoverParams.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Hover, Direction.ClientToServer)] - public class HoverParams : WorkDoneTextDocumentPositionParams, IRequest - { - } -} diff --git a/src/Protocol/Models/HoverRegistrationOptions.cs b/src/Protocol/Models/HoverRegistrationOptions.cs deleted file mode 100644 index a1729cb2b..000000000 --- a/src/Protocol/Models/HoverRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class HoverRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions { } - - class HoverRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public HoverRegistrationOptionsConverter() : base(nameof(ServerCapabilities.HoverProvider)) - { - } - public override StaticOptions Convert(HoverRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/IInitializeParams.cs b/src/Protocol/Models/IInitializeParams.cs deleted file mode 100644 index e44ae31b8..000000000 --- a/src/Protocol/Models/IInitializeParams.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using MediatR; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public interface IInitializeParams : IWorkDoneProgressParams, IRequest - { - /// - /// The process Id of the parent process that started - /// the server. Is null if the process has not been started by another process. - /// If the parent process is not alive then the server should exit (see exit notification) its process. - /// - long? ProcessId { get; set; } - - /// - /// Information about the client - /// - /// @since 3.15.0 - /// - [DisallowNull] ClientInfo? ClientInfo { get; set; } - - /// - /// The rootPath of the workspace. Is null - /// if no folder is open. - /// - /// @deprecated in favour of rootUri. - /// - [DisallowNull] string? RootPath { get; set; } - - /// - /// The rootUri of the workspace. Is null if no - /// folder is open. If both `rootPath` and `rootUri` are set - /// `rootUri` wins. - /// - [DisallowNull] DocumentUri? RootUri { get; set; } - - /// - /// User provided initialization options. - /// - [DisallowNull] object? InitializationOptions { get; set; } - - /// - /// The capabilities provided by the client (editor or tool) - /// - [MaybeNull] TClientCapabilities Capabilities { get; set; } - - /// - /// The initial trace setting. If omitted trace is disabled ('off'). - /// - InitializeTrace Trace { get; set; } - - /// - /// The workspace folders configured in the client when the server starts. - /// This property is only available if the client supports workspace folders. - /// It can be `null` if the client supports workspace folders but none are - /// configured. - /// - /// Since 3.6.0 - /// - [DisallowNull] Container? WorkspaceFolders { get; set; } - } -} diff --git a/src/Protocol/Models/IWorkDoneProgressOptions.cs b/src/Protocol/Models/IWorkDoneProgressOptions.cs deleted file mode 100644 index 90d83ebb6..000000000 --- a/src/Protocol/Models/IWorkDoneProgressOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public interface IWorkDoneProgressOptions - { - [Optional] bool WorkDoneProgress { get; set; } - } -} diff --git a/src/Protocol/Models/IWorkDoneProgressParams.cs b/src/Protocol/Models/IWorkDoneProgressParams.cs deleted file mode 100644 index 3113459d0..000000000 --- a/src/Protocol/Models/IWorkDoneProgressParams.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public interface IWorkDoneProgressParams - { - /// - /// An optional token that a server can use to report work done progress. - /// - [Optional] - ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/ImplementationParams.cs b/src/Protocol/Models/ImplementationParams.cs deleted file mode 100644 index e1f84e577..000000000 --- a/src/Protocol/Models/ImplementationParams.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Implementation, Direction.ClientToServer)] - public class ImplementationParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/ImplementationRegistrationOptions.cs b/src/Protocol/Models/ImplementationRegistrationOptions.cs deleted file mode 100644 index 6874a48d8..000000000 --- a/src/Protocol/Models/ImplementationRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ImplementationRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions { } - - class ImplementationRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public ImplementationRegistrationOptionsConverter() : base(nameof(ServerCapabilities.ImplementationProvider)) - { - } - public override StaticOptions Convert(ImplementationRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/InitializeError.cs b/src/Protocol/Models/InitializeError.cs deleted file mode 100644 index 0037b3b83..000000000 --- a/src/Protocol/Models/InitializeError.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class InitializeError - { - /// - /// Indicates whether the client should retry to send the - /// initilize request after showing the message provided - /// in the ResponseError. - /// - public bool Retry { get; set; } - } -} diff --git a/src/Protocol/Models/InitializeParams.cs b/src/Protocol/Models/InitializeParams.cs deleted file mode 100644 index 4cd22840a..000000000 --- a/src/Protocol/Models/InitializeParams.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.Initialize, Direction.ClientToServer)] - public class InitializeParams : IInitializeParams - { - /// - /// The process Id of the parent process that started - /// the server. Is null if the process has not been started by another process. - /// If the parent process is not alive then the server should exit (see exit notification) its process. - /// - public long? ProcessId { get; set; } - - /// - /// Information about the client - /// - /// @since 3.15.0 - /// - [Optional] - [DisallowNull] - public ClientInfo? ClientInfo { get; set; } - - /// - /// The rootPath of the workspace. Is null - /// if no folder is open. - /// - /// @deprecated in favour of rootUri. - /// - [Optional] - [DisallowNull] - public string? RootPath - { - get => RootUri?.GetFileSystemPath(); - set { - if (!string.IsNullOrEmpty(value)) - { - RootUri = DocumentUri.FromFileSystemPath(value!); - } - } - } - - /// - /// The rootUri of the workspace. Is null if no - /// folder is open. If both `rootPath` and `rootUri` are set - /// `rootUri` wins. - /// - [DisallowNull] - public DocumentUri? RootUri { get; set; } - - /// - /// User provided initialization options. - /// - [DisallowNull] - public object? InitializationOptions { get; set; } - - /// - /// The capabilities provided by the client (editor or tool) - /// - [MaybeNull] - public ClientCapabilities Capabilities { get; set; } = null!; - - /// - /// The initial trace setting. If omitted trace is disabled ('off'). - /// - [Optional] - public InitializeTrace Trace { get; set; } = InitializeTrace.Off; - - /// - /// The workspace folders configured in the client when the server starts. - /// This property is only available if the client supports workspace folders. - /// It can be `null` if the client supports workspace folders but none are - /// configured. - /// - /// Since 3.6.0 - /// - [MaybeNull] - public Container? WorkspaceFolders { get; set; } - - /// - [Optional] - [MaybeNull] - public ProgressToken? WorkDoneToken { get; set; } - - /// - /// The locale the client is currently showing the user interface - /// in. This must not necessarily be the locale of the operating - /// system. - /// - /// Uses IETF language tags as the value's syntax - /// (See https://en.wikipedia.org/wiki/IETF_language_tag) - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public string? Locale { get; set; } - - public InitializeParams() - { - } - - internal InitializeParams(IInitializeParams @params, ClientCapabilities clientCapabilities) - { - ProcessId = @params.ProcessId; - Trace = @params.Trace; - Capabilities = clientCapabilities; - ClientInfo = @params.ClientInfo!; - InitializationOptions = @params.InitializationOptions!; - RootUri = @params.RootUri!; - WorkspaceFolders = @params.WorkspaceFolders!; - WorkDoneToken = @params.WorkDoneToken!; - } - } -} diff --git a/src/Protocol/Models/InitializeResult.cs b/src/Protocol/Models/InitializeResult.cs deleted file mode 100644 index 1b546e8a1..000000000 --- a/src/Protocol/Models/InitializeResult.cs +++ /dev/null @@ -1,21 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class InitializeResult - { - /// - /// The capabilities the language server provides. - /// - public ServerCapabilities Capabilities { get; set; } = null!; - - /// - /// Information about the server. - /// - /// @since 3.15.0 - /// - [Optional] - public ServerInfo? ServerInfo { get; set; } - } -} diff --git a/src/Protocol/Models/InitializeTrace.cs b/src/Protocol/Models/InitializeTrace.cs deleted file mode 100644 index 06ccd7a0f..000000000 --- a/src/Protocol/Models/InitializeTrace.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Runtime.Serialization; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(StringEnumConverter))] - public enum InitializeTrace - { - [EnumMember(Value = "off")] Off, - [EnumMember(Value = "messages")] Messages, - [EnumMember(Value = "verbose")] Verbose - } -} diff --git a/src/Protocol/Models/InitializedParams.cs b/src/Protocol/Models/InitializedParams.cs deleted file mode 100644 index a3cdc9068..000000000 --- a/src/Protocol/Models/InitializedParams.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.Initialized, Direction.ClientToServer)] - public class InitializedParams : IRequest - { - } -} diff --git a/src/Protocol/Models/InternalInitializeParams.cs b/src/Protocol/Models/InternalInitializeParams.cs deleted file mode 100644 index 416c56aa6..000000000 --- a/src/Protocol/Models/InternalInitializeParams.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - internal class InternalInitializeParams : IInitializeParams - { - /// - /// The process Id of the parent process that started - /// the server. Is null if the process has not been started by another process. - /// If the parent process is not alive then the server should exit (see exit notification) its process. - /// - public long? ProcessId { get; set; } - - /// - /// Information about the client - /// - /// @since 3.15.0 - /// - [Optional] - public ClientInfo? ClientInfo { get; set; } - - /// - /// The rootPath of the workspace. Is null - /// if no folder is open. - /// - /// @deprecated in favour of rootUri. - /// - [Optional] - public string? RootPath - { - get => RootUri.GetFileSystemPath(); - set => RootUri = (value == null ? null : DocumentUri.FromFileSystemPath(value))!; - } - - /// - /// The rootUri of the workspace. Is null if no - /// folder is open. If both `rootPath` and `rootUri` are set - /// `rootUri` wins. - /// - public DocumentUri RootUri { get; set; } = null!; - - /// - /// User provided initialization options. - /// - public object? InitializationOptions { get; set; } - - /// - /// The capabilities provided by the client (editor or tool) - /// - public JObject Capabilities { get; set; } = null!; - - /// - /// The initial trace setting. If omitted trace is disabled ('off'). - /// - [Optional] - public InitializeTrace Trace { get; set; } = InitializeTrace.Off; - - /// - /// The workspace folders configured in the client when the server starts. - /// This property is only available if the client supports workspace folders. - /// It can be `null` if the client supports workspace folders but none are - /// configured. - /// - /// Since 3.6.0 - /// - public Container? WorkspaceFolders { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/Location.cs b/src/Protocol/Models/Location.cs index e3a728653..6ceb2d690 100644 --- a/src/Protocol/Models/Location.cs +++ b/src/Protocol/Models/Location.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] public class Location : IEquatable { /// diff --git a/src/Protocol/Models/LocationContainer.cs b/src/Protocol/Models/LocationContainer.cs deleted file mode 100644 index c3e947811..000000000 --- a/src/Protocol/Models/LocationContainer.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class LocationContainer : Container - { - public LocationContainer() : this(Enumerable.Empty()) - { - } - - public LocationContainer(IEnumerable items) : base(items) - { - } - - public LocationContainer(params Location[] items) : base(items) - { - } - - public static implicit operator LocationContainer(Location[] items) => new LocationContainer(items); - - public static implicit operator LocationContainer(Collection items) => new LocationContainer(items); - - public static implicit operator LocationContainer(List items) => new LocationContainer(items); - } -} diff --git a/src/Protocol/Models/LocationOrLocationLink.cs b/src/Protocol/Models/LocationOrLocationLink.cs index 2180aba9c..916d2465d 100644 --- a/src/Protocol/Models/LocationOrLocationLink.cs +++ b/src/Protocol/Models/LocationOrLocationLink.cs @@ -1,10 +1,12 @@ using Newtonsoft.Json; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [JsonConverter(typeof(LocationOrLocationLinkConverter))] - public struct LocationOrLocationLink + [GenerateContainer("LocationOrLocationLinks")] + public class LocationOrLocationLink { public LocationOrLocationLink(Location location) { @@ -28,4 +30,7 @@ public LocationOrLocationLink(LocationLink locationLink) public static implicit operator LocationOrLocationLink(LocationLink locationLink) => new LocationOrLocationLink(locationLink); } + + [JsonConverter(typeof(LocationOrLocationLinksConverter))] + public partial class LocationOrLocationLinks { } } diff --git a/src/Protocol/Models/LocationOrLocationLinks.cs b/src/Protocol/Models/LocationOrLocationLinks.cs deleted file mode 100644 index 3e271c650..000000000 --- a/src/Protocol/Models/LocationOrLocationLinks.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(LocationOrLocationLinksConverter))] - public class LocationOrLocationLinks : Container - { - public LocationOrLocationLinks() : this(Enumerable.Empty()) - { - } - - public LocationOrLocationLinks(IEnumerable items) : base(items) - { - } - - public LocationOrLocationLinks(params LocationOrLocationLink[] items) : base(items) - { - } - - public static implicit operator LocationOrLocationLinks(LocationOrLocationLink[] items) => new LocationOrLocationLinks(items); - - public static implicit operator LocationOrLocationLinks(Collection items) => new LocationOrLocationLinks(items); - - public static implicit operator LocationOrLocationLinks(List items) => new LocationOrLocationLinks(items); - } -} diff --git a/src/Protocol/Models/LogMessageParams.cs b/src/Protocol/Models/LogMessageParams.cs deleted file mode 100644 index 2a7c5bb96..000000000 --- a/src/Protocol/Models/LogMessageParams.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WindowNames.LogMessage, Direction.ServerToClient)] - public class LogMessageParams : IRequest - { - /// - /// The message type. See {@link MessageType} - /// - public MessageType Type { get; set; } - - /// - /// The actual message - /// - public string Message { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/LogTraceParams.cs b/src/Protocol/Models/LogTraceParams.cs deleted file mode 100644 index 1e5f51ebc..000000000 --- a/src/Protocol/Models/LogTraceParams.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.LogTrace, Direction.ServerToClient)] - public class LogTraceParams : IRequest - { - /// - /// The message to be logged. - /// - public string Message { get; set; } = null!; - - /// - /// Additional information that can be computed if the `trace` configuration is set to `'verbose'` - /// - [Optional] - public string? Verbose { get; set; } - } -} diff --git a/src/Protocol/Models/MessageActionItem.cs b/src/Protocol/Models/MessageActionItem.cs deleted file mode 100644 index f8db300e6..000000000 --- a/src/Protocol/Models/MessageActionItem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class MessageActionItem - { - /// - /// A short title like 'Retry', 'Open Log' etc. - /// - public string Title { get; set; } = null!; - - /// - /// Extension data that may contain additional properties based on - /// - [JsonExtensionData] - public IDictionary ExtensionData { get; set; } = new Dictionary(); - - private string DebuggerDisplay => Title; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/OnTypeRenameParams.cs b/src/Protocol/Models/OnTypeRenameParams.cs deleted file mode 100644 index 09488cb40..000000000 --- a/src/Protocol/Models/OnTypeRenameParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Parallel] - [Method(TextDocumentNames.OnTypeRename, Direction.ClientToServer)] - public class OnTypeRenameParams : WorkDoneTextDocumentPositionParams, IRequest - { - } -} diff --git a/src/Protocol/Models/OnTypeRenameRanges.cs b/src/Protocol/Models/OnTypeRenameRanges.cs deleted file mode 100644 index 6138d1143..000000000 --- a/src/Protocol/Models/OnTypeRenameRanges.cs +++ /dev/null @@ -1,21 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class OnTypeRenameRanges - { - /// - /// A list of ranges that can be renamed together. The ranges must have - /// identical length and contain identical text content. The ranges cannot overlap. - /// - public Container Ranges { get; set; } = null!; - - /// - /// An optional word pattern (regular expression) that describes valid contents for - /// the given ranges. If no pattern is provided, the client configuration's word - /// pattern will be used. - /// - [Optional] - public string? WordPattern { get; set; } - } -} \ No newline at end of file diff --git a/src/Protocol/Models/OnTypeRenameRegistrationOptions.cs b/src/Protocol/Models/OnTypeRenameRegistrationOptions.cs deleted file mode 100644 index c1132373c..000000000 --- a/src/Protocol/Models/OnTypeRenameRegistrationOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class OnTypeRenameRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions - { - } - - class OnTypeRenameRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public OnTypeRenameRegistrationOptionsConverter() : base(nameof(ServerCapabilities.OnTypeRenameProvider)) - { - } - - public override StaticOptions Convert(OnTypeRenameRegistrationOptions source) => new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - DocumentSelector = source.DocumentSelector - }; - } - } -} diff --git a/src/Protocol/Models/ParameterInformation.cs b/src/Protocol/Models/ParameterInformation.cs deleted file mode 100644 index bb9ea88d7..000000000 --- a/src/Protocol/Models/ParameterInformation.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents a parameter of a callable-signature. A parameter can - /// have a label and a doc-comment. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class ParameterInformation - { - /// - /// The label of this parameter. Will be shown in - /// the UI. - /// - public ParameterInformationLabel Label { get; set; } = null!; - - /// - /// The human-readable doc-comment of this parameter. Will be shown - /// in the UI but can be omitted. - /// - [Optional] - public StringOrMarkupContent? Documentation { get; set; } - - private string DebuggerDisplay => $"{Label}{( Documentation != null ? $" {Documentation}" : string.Empty )}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/ParameterInformationLabel.cs b/src/Protocol/Models/ParameterInformationLabel.cs deleted file mode 100644 index 24cb5f7f3..000000000 --- a/src/Protocol/Models/ParameterInformationLabel.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Diagnostics; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(ParameterInformationLabelConverter))] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class ParameterInformationLabel - { - public ParameterInformationLabel((int start, int end) range) => Range = range; - - public ParameterInformationLabel(string label) => Label = label; - - public (int start, int end) Range { get; } - public bool IsRange => Label == null; - public string? Label { get; } - public bool IsLabel => Label != null; - - public static implicit operator ParameterInformationLabel(string label) => new ParameterInformationLabel(label); - - public static implicit operator ParameterInformationLabel((int start, int end) range) => new ParameterInformationLabel(range); - - private string DebuggerDisplay => IsRange ? $"(start: {Range.start}, end: {Range.end})" : IsLabel ? Label! : string.Empty; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/PlaceholderRange.cs b/src/Protocol/Models/PlaceholderRange.cs deleted file mode 100644 index 8ae305eb8..000000000 --- a/src/Protocol/Models/PlaceholderRange.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class PlaceholderRange - { - public Range Range { get; set; } = null!; - public string Placeholder { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/PrepareRenameParams.cs b/src/Protocol/Models/PrepareRenameParams.cs deleted file mode 100644 index 23fdd55a7..000000000 --- a/src/Protocol/Models/PrepareRenameParams.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.PrepareRename, Direction.ClientToServer)] - public class PrepareRenameParams : TextDocumentPositionParams, IRequest - { - } -} diff --git a/src/Protocol/Models/ProgressParams.cs b/src/Protocol/Models/ProgressParams.cs deleted file mode 100644 index 454f36326..000000000 --- a/src/Protocol/Models/ProgressParams.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.Progress, Direction.Bidirectional)] - public class ProgressParams : IRequest - { - public static ProgressParams Create(ProgressToken token, T value, JsonSerializer jsonSerializer) => - new ProgressParams { - Token = token, - Value = JToken.FromObject(value, jsonSerializer) - }; - - /// - /// The progress token provided by the client or server. - /// - public ProgressToken Token { get; set; } = null!; - - /// - /// The progress data. - /// - public JToken Value { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/ProgressToken.cs b/src/Protocol/Models/ProgressToken.cs deleted file mode 100644 index 1e71a8bd3..000000000 --- a/src/Protocol/Models/ProgressToken.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(ProgressTokenConverter))] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class ProgressToken : IEquatable, IEquatable, IEquatable - { - private long? _long; - private string? _string; - - public ProgressToken(long value) - { - _long = value; - _string = null; - } - - public ProgressToken(string value) - { - _long = null; - _string = value; - } - - public bool IsLong => _long.HasValue; - - public long Long - { - get => _long ?? 0; - set { - String = null; - _long = value; - } - } - - public bool IsString => _string != null; - - public string? String - { - get => _string; - set { - _string = value; - _long = null; - } - } - - public static implicit operator ProgressToken(long value) => new ProgressToken(value); - - public static implicit operator ProgressToken(string value) => new ProgressToken(value); - - public ProgressParams Create(T value, JsonSerializer jsonSerializer) => ProgressParams.Create(this, value, jsonSerializer); - - public override bool Equals(object obj) => - obj is ProgressToken token && - Equals(token); - - public override int GetHashCode() - { - var hashCode = 1456509845; - hashCode = hashCode * -1521134295 + IsLong.GetHashCode(); - hashCode = hashCode * -1521134295 + Long.GetHashCode(); - hashCode = hashCode * -1521134295 + IsString.GetHashCode(); - if (String != null) hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(String); - return hashCode; - } - - public bool Equals(ProgressToken other) => - IsLong == other.IsLong && - Long == other.Long && - IsString == other.IsString && - String == other.String; - - public bool Equals(long other) => IsLong && Long == other; - - public bool Equals(string other) => IsString && String == other; - - private string DebuggerDisplay => IsString ? String! : IsLong ? Long.ToString() : ""; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyIncomingCall.cs b/src/Protocol/Models/Proposals/CallHierarchyIncomingCall.cs deleted file mode 100644 index 39649c4ac..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyIncomingCall.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Represents an incoming call, e.g. a caller of a method or constructor. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class CallHierarchyIncomingCall - { - /// - /// The item that makes the call. - /// - public CallHierarchyItem From { get; set; } = null!; - - /// - /// The range at which at which the calls appears. This is relative to the caller - /// denoted by [`this.from`](#CallHierarchyIncomingCall.from). - /// - public Container FromRanges { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyIncomingCallsParams.cs b/src/Protocol/Models/Proposals/CallHierarchyIncomingCallsParams.cs deleted file mode 100644 index 1862a51dd..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyIncomingCallsParams.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// The parameter of a `callHierarchy/incomingCalls` request. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.CallHierarchyIncoming, Direction.ClientToServer)] - public class CallHierarchyIncomingCallsParams : IWorkDoneProgressParams, ICanBeResolved, IPartialItemsRequest?, CallHierarchyIncomingCall> - { - public CallHierarchyItem Item { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - JToken? ICanBeResolved.Data - { - get => ( (ICanBeResolved) Item )?.Data; - set { - if (Item != null) ( (ICanBeResolved) Item ).Data = value; - } - } - } - - /// - /// The parameter of a `callHierarchy/incomingCalls` request. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.CallHierarchyIncoming, Direction.ClientToServer)] - public class CallHierarchyIncomingCallsParams : IWorkDoneProgressParams, ICanBeResolved, - IPartialItemsRequest?, CallHierarchyIncomingCall> where T : HandlerIdentity?, new() - { - public CallHierarchyItem Item { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - JToken? ICanBeResolved.Data - { - get => ( (ICanBeResolved) Item )?.Data; - set { - if (Item != null) ( (ICanBeResolved) Item ).Data = value; - } - } - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyItem.cs b/src/Protocol/Models/Proposals/CallHierarchyItem.cs deleted file mode 100644 index 87e3c1c11..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyItem.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Represents programming constructs like functions or constructors in the context - /// of call hierarchy. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CallHierarchyItem : ICanBeResolved - { - /// - /// The name of this item. - /// - public string Name { get; set; } = null!; - - /// - /// The kind of this item. - /// - public SymbolKind Kind { get; set; } - - /// - /// Tags for this item. - /// - [Optional] - public Container? Tags { get; set; } - - /// - /// More detail for this item, e.g. the signature of a function. - /// - [Optional] - public string? Detail { get; set; } - - /// - /// The resource identifier of this item. - /// - public DocumentUri Uri { get; set; } = null!; - - /// - /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. - /// - public Range Range { get; set; } = null!; - - /// - /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. - /// Must be contained by the [`range`](#CallHierarchyItem.range). - /// - public Range SelectionRange { get; set; } = null!; - - /// - /// A data entry field that is preserved between a call hierarchy prepare and - /// incoming calls or outgoing calls requests. - /// - [Optional] - public JToken? Data { get; set; } - - private string DebuggerDisplay => - $"[{Kind.ToString()}] " + - $"{Name} " + - $"@ {Uri} " + - $"{Range}"; - - /// - public override string ToString() => DebuggerDisplay; - } - - /// - /// Represents programming constructs like functions or constructors in the context - /// of call hierarchy. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class CallHierarchyItem : ICanBeResolved - where T : HandlerIdentity?, new() - { - /// - /// The name of this item. - /// - public string Name { get; set; } = null!; - - /// - /// The kind of this item. - /// - public SymbolKind Kind { get; set; } - - /// - /// Tags for this item. - /// - [Optional] - public Container? Tags { get; set; } - - /// - /// More detail for this item, e.g. the signature of a function. - /// - [Optional] - public string? Detail { get; set; } - - /// - /// The resource identifier of this item. - /// - public DocumentUri Uri { get; set; } = null!; - - /// - /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. - /// - public Range Range { get; set; } = null!; - - /// - /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. - /// Must be contained by the [`range`](#CallHierarchyItem.range). - /// - public Range SelectionRange { get; set; } = null!; - - /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. - /// - public T Data - { - get => ( (ICanBeResolved) this ).Data?.ToObject()!; - set => ( (ICanBeResolved) this ).Data = JToken.FromObject(value); - } - - JToken? ICanBeResolved.Data { get; set; } - - public static implicit operator CallHierarchyItem(CallHierarchyItem value) => new CallHierarchyItem { - Data = ( (ICanBeResolved) value ).Data, - Detail = value.Detail, - Kind = value.Kind, - Name = value.Name, - Range = value.Range, - SelectionRange = value.SelectionRange, - Tags = value.Tags, - Uri = value.Uri - }; - - public static implicit operator CallHierarchyItem(CallHierarchyItem value) - { - var item = new CallHierarchyItem { - Detail = value.Detail, - Kind = value.Kind, - Name = value.Name, - Range = value.Range, - SelectionRange = value.SelectionRange, - Tags = value.Tags, - Uri = value.Uri - }; - ( (ICanBeResolved) item ).Data = value.Data; - return item; - } - - private string DebuggerDisplay => - $"[{Kind.ToString()}] " + - $"{Name} " + - $"@ {Uri} " + - $"{Range}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyOutgoingCall.cs b/src/Protocol/Models/Proposals/CallHierarchyOutgoingCall.cs deleted file mode 100644 index 3da03da45..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyOutgoingCall.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class CallHierarchyOutgoingCall - { - /// - /// The item that is called. - /// - public CallHierarchyItem To { get; set; } = null!; - - /// - /// The range at which this item is called. This is the range relative to the caller, e.g the item - /// passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls) - /// and not [`this.to`](#CallHierarchyOutgoingCall.to). - /// - public Container FromRanges { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyOutgoingCallsParams.cs b/src/Protocol/Models/Proposals/CallHierarchyOutgoingCallsParams.cs deleted file mode 100644 index 2b51c80d4..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyOutgoingCallsParams.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// The parameter of a `callHierarchy/outgoingCalls` request. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.CallHierarchyOutgoing, Direction.ClientToServer)] - public class CallHierarchyOutgoingCallsParams : IWorkDoneProgressParams, ICanBeResolved, IPartialItemsRequest?, CallHierarchyOutgoingCall> - { - public CallHierarchyItem Item { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - JToken? ICanBeResolved.Data - { - get => ( (ICanBeResolved) Item )?.Data; - set { - if (Item != null) ( (ICanBeResolved) Item ).Data = value; - } - } - } - - /// - /// The parameter of a `callHierarchy/outgoingCalls` request. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.CallHierarchyOutgoing, Direction.ClientToServer)] - public class CallHierarchyOutgoingCallsParams : IWorkDoneProgressParams, ICanBeResolved, IPartialItemsRequest?, CallHierarchyOutgoingCall> where T : HandlerIdentity?, new() - { - public CallHierarchyItem Item { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - JToken? ICanBeResolved.Data - { - get => ( (ICanBeResolved) Item )?.Data; - set { - if (Item != null) ( (ICanBeResolved) Item ).Data = value; - } - } - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyPrepareParams.cs b/src/Protocol/Models/Proposals/CallHierarchyPrepareParams.cs deleted file mode 100644 index 3069657d8..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyPrepareParams.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// The parameter of a `textDocument/prepareCallHierarchy` request. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.PrepareCallHierarchy, Direction.ClientToServer)] - public class CallHierarchyPrepareParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest?, CallHierarchyItem> - { - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/CallHierarchyRegistrationOptions.cs b/src/Protocol/Models/Proposals/CallHierarchyRegistrationOptions.cs deleted file mode 100644 index 8da120783..000000000 --- a/src/Protocol/Models/Proposals/CallHierarchyRegistrationOptions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Call hierarchy options used during static or dynamic registration. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class CallHierarchyRegistrationOptions : StaticWorkDoneTextDocumentRegistrationOptions - { - /// - /// Call hierarchy options used during static registration. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class StaticOptions : WorkDoneProgressOptions - { - } - - class CallHierarchyRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public CallHierarchyRegistrationOptionsConverter() : base(nameof(ServerCapabilities.CallHierarchyProvider)) - { - } - public override StaticOptions Convert(CallHierarchyRegistrationOptions source) - { - return new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } - } -} diff --git a/src/Protocol/Models/Proposals/CodeLensRefreshParams.cs b/src/Protocol/Models/Proposals/CodeLensRefreshParams.cs deleted file mode 100644 index c3fe2a568..000000000 --- a/src/Protocol/Models/Proposals/CodeLensRefreshParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] - public class CodeLensRefreshParams : IRequest { } -} diff --git a/src/Protocol/Models/Proposals/ISemanticTokenResult.cs b/src/Protocol/Models/Proposals/ISemanticTokenResult.cs deleted file mode 100644 index 32bd39062..000000000 --- a/src/Protocol/Models/Proposals/ISemanticTokenResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - public interface ISemanticTokenResult - { - /// - /// An optional result id. If provided and clients support delta updating - /// the client will include the result id in the next semantic token request. - /// A server can then instead of computing all semantic tokens again simply - /// send a delta. - /// - [Optional] - public string? ResultId { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/Moniker.cs b/src/Protocol/Models/Proposals/Moniker.cs deleted file mode 100644 index 07f8a75d4..000000000 --- a/src/Protocol/Models/Proposals/Moniker.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Moniker definition to match LSIF 0.5 moniker definition. - /// - [Obsolete(Constants.Proposal)] - public class Moniker - { - /// - /// The scheme of the moniker. For example tsc or .Net - /// - public string Scheme { get; set; } = null!; - - /// - /// The identifier of the moniker. The value is opaque in LSIF however - /// schema owners are allowed to define the structure if they want. - /// - public string Identifier { get; set; } = null!; - - /// - /// The scope in which the moniker is unique - /// - public UniquenessLevel Unique { get; set; } - - /// - /// The moniker kind if known. - /// - [Optional] - public MonikerKind Kind { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/MonikerKind.cs b/src/Protocol/Models/Proposals/MonikerKind.cs deleted file mode 100644 index 487929845..000000000 --- a/src/Protocol/Models/Proposals/MonikerKind.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Diagnostics; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Moniker uniqueness level to define scope of the moniker. - /// - [DebuggerDisplay("{" + nameof(_value) + "}")] - [JsonConverter(typeof(EnumLikeStringConverter))] - public readonly struct MonikerKind : IEquatable, IEnumLikeString - { - /// - /// The moniker represent a symbol that is imported into a project - /// - public static readonly MonikerKind Import = new MonikerKind("import"); - - /// - /// The moniker represents a symbol that is exported from a project - /// - public static readonly MonikerKind Export = new MonikerKind("export"); - - /// - /// The moniker represents a symbol that is local to a project (e.g. a local - /// variable of a function, a class not visible outside the project, ...) - /// - public static readonly MonikerKind Local = new MonikerKind("local"); - - private readonly string? _value; - - public MonikerKind(string kind) => _value = kind; - - public static implicit operator MonikerKind(string kind) => new MonikerKind(kind); - - public static implicit operator string(MonikerKind kind) => kind._value ?? string.Empty; - - /// - public override string ToString() => _value ?? string.Empty; - - public bool Equals(MonikerKind other) => _value == other._value; - - public override bool Equals(object obj) => obj is MonikerKind other && Equals(other); - - public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; - - public static bool operator ==(MonikerKind left, MonikerKind right) => left.Equals(right); - - public static bool operator !=(MonikerKind left, MonikerKind right) => !left.Equals(right); - } -} \ No newline at end of file diff --git a/src/Protocol/Models/Proposals/MonikerParams.cs b/src/Protocol/Models/Proposals/MonikerParams.cs deleted file mode 100644 index 31dbccead..000000000 --- a/src/Protocol/Models/Proposals/MonikerParams.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// Language Server Index Format (LSIF) introduced the concept of symbol monikers to help associate symbols across different indexes. - /// This request adds capability for LSP server implementations to provide the same symbol moniker information given a text document - /// position. Clients can utilize this method to get the moniker at the current location in a file user is editing and do further - /// code navigation queries in other services that rely on LSIF indexes and link symbols together. - /// - /// The `textDocument/moniker` request is sent from the client to the server to get the symbol monikers for a given text document - /// position. An array of Moniker types is returned as response to indicate possible monikers at the given location. If no monikers - /// can be calculated, an empty array or `null` should be returned. - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.Moniker, Direction.ClientToServer)] - public class MonikerParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest?, Moniker> - { - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/MonikerRegistrationOptions.cs b/src/Protocol/Models/Proposals/MonikerRegistrationOptions.cs deleted file mode 100644 index bb6e61cad..000000000 --- a/src/Protocol/Models/Proposals/MonikerRegistrationOptions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - public class MonikerRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// Code Lens options. - /// - public class StaticOptions : WorkDoneProgressOptions - { - } - - class MonikerRegistrationOptionsOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public MonikerRegistrationOptionsOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.MonikerProvider)) - { - _handlersManager = handlersManager; - } - public override StaticOptions Convert(MonikerRegistrationOptions source) - { - return new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokenFormat.cs b/src/Protocol/Models/Proposals/SemanticTokenFormat.cs deleted file mode 100644 index d3ea9de36..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokenFormat.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// The protocol defines an additional token format capability to allow future extensions of the format. - /// The only format that is currently specified is `relative` expressing that the tokens are described using relative positions. - /// - /// @since 3.16.0 - /// - [JsonConverter(typeof(EnumLikeStringConverter))] - [Obsolete(Constants.Proposal)] - [DebuggerDisplay("{_value}")] - public readonly struct SemanticTokenFormat : IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = - new Lazy>( - () => { - return typeof(SemanticTokenFormat) - .GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(z => z.GetValue(null)) - .Cast() - .ToArray(); - } - ); - - public static IEnumerable Defaults => _defaults.Value; - - public static readonly SemanticTokenFormat Relative = new SemanticTokenFormat("relative"); - - private readonly string _value; - - public SemanticTokenFormat(string modifier) => _value = modifier; - - public static implicit operator SemanticTokenFormat(string kind) => new SemanticTokenFormat(kind); - - public static implicit operator string(SemanticTokenFormat kind) => kind._value; - - public override string ToString() => _value; - public bool Equals(SemanticTokenFormat other) => _value == other._value; - - public override bool Equals(object obj) => obj is SemanticTokenFormat other && Equals(other); - - public override int GetHashCode() => _value.GetHashCode(); - - public static bool operator ==(SemanticTokenFormat left, SemanticTokenFormat right) => left.Equals(right); - - public static bool operator !=(SemanticTokenFormat left, SemanticTokenFormat right) => !left.Equals(right); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs b/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs deleted file mode 100644 index 168319fb4..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokenModifiers.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// A set of predefined token modifiers. This set is not fixed - /// an clients can specify additional token types via the - /// corresponding client capabilities. - /// - /// @since 3.16.0 - /// - [JsonConverter(typeof(EnumLikeStringConverter))] - [Obsolete(Constants.Proposal)] - [DebuggerDisplay("{_value}")] - public readonly struct SemanticTokenModifier : IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = - new Lazy>( - () => { - return typeof(SemanticTokenModifier) - .GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(z => z.GetValue(null)) - .Cast() - .ToArray(); - } - ); - - public static IEnumerable Defaults => _defaults.Value; - - public static readonly SemanticTokenModifier Documentation = new SemanticTokenModifier("documentation"); - public static readonly SemanticTokenModifier Declaration = new SemanticTokenModifier("declaration"); - public static readonly SemanticTokenModifier Definition = new SemanticTokenModifier("definition"); - public static readonly SemanticTokenModifier Static = new SemanticTokenModifier("static"); - public static readonly SemanticTokenModifier Async = new SemanticTokenModifier("async"); - public static readonly SemanticTokenModifier Abstract = new SemanticTokenModifier("abstract"); - public static readonly SemanticTokenModifier Deprecated = new SemanticTokenModifier("deprecated"); - public static readonly SemanticTokenModifier Readonly = new SemanticTokenModifier("readonly"); - public static readonly SemanticTokenModifier Modification = new SemanticTokenModifier("modification"); - public static readonly SemanticTokenModifier DefaultLibrary = new SemanticTokenModifier("defaultLibrary"); - - private readonly string _value; - - public SemanticTokenModifier(string modifier) => _value = modifier; - - public static implicit operator SemanticTokenModifier(string kind) => new SemanticTokenModifier(kind); - - public static implicit operator string(SemanticTokenModifier kind) => kind._value; - - public override string ToString() => _value; - public bool Equals(SemanticTokenModifier other) => _value == other._value; - - public override bool Equals(object obj) => obj is SemanticTokenModifier other && Equals(other); - - public override int GetHashCode() => _value.GetHashCode(); - - public static bool operator ==(SemanticTokenModifier left, SemanticTokenModifier right) => left.Equals(right); - - public static bool operator !=(SemanticTokenModifier left, SemanticTokenModifier right) => !left.Equals(right); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokenTypes.cs b/src/Protocol/Models/Proposals/SemanticTokenTypes.cs deleted file mode 100644 index 5c51e74b1..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokenTypes.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// A set of predefined token types. This set is not fixed - /// an clients can specify additional token types via the - /// corresponding client capabilities. - /// - /// @since 3.16.0 - /// - [JsonConverter(typeof(EnumLikeStringConverter))] - [Obsolete(Constants.Proposal)] - [DebuggerDisplay("{_value}")] - public readonly struct SemanticTokenType : IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = - new Lazy>( - () => { - return typeof(SemanticTokenType) - .GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(z => z.GetValue(null)) - .Cast() - .ToArray(); - } - ); - - public static IEnumerable Defaults => _defaults.Value; - - public static readonly SemanticTokenType Comment = new SemanticTokenType("comment"); - public static readonly SemanticTokenType Keyword = new SemanticTokenType("keyword"); - public static readonly SemanticTokenType String = new SemanticTokenType("string"); - public static readonly SemanticTokenType Number = new SemanticTokenType("number"); - public static readonly SemanticTokenType Regexp = new SemanticTokenType("regexp"); - public static readonly SemanticTokenType Operator = new SemanticTokenType("operator"); - public static readonly SemanticTokenType Namespace = new SemanticTokenType("namespace"); - public static readonly SemanticTokenType Type = new SemanticTokenType("type"); - public static readonly SemanticTokenType Struct = new SemanticTokenType("struct"); - public static readonly SemanticTokenType Class = new SemanticTokenType("class"); - public static readonly SemanticTokenType Interface = new SemanticTokenType("interface"); - public static readonly SemanticTokenType Enum = new SemanticTokenType("enum"); - public static readonly SemanticTokenType TypeParameter = new SemanticTokenType("typeParameter"); - public static readonly SemanticTokenType Function = new SemanticTokenType("function"); - public static readonly SemanticTokenType Member = new SemanticTokenType("member"); - public static readonly SemanticTokenType Property = new SemanticTokenType("property"); - public static readonly SemanticTokenType Macro = new SemanticTokenType("macro"); - public static readonly SemanticTokenType Variable = new SemanticTokenType("variable"); - public static readonly SemanticTokenType Parameter = new SemanticTokenType("parameter"); - public static readonly SemanticTokenType Label = new SemanticTokenType("label"); - public static readonly SemanticTokenType Modifier = new SemanticTokenType("modifier"); - public static readonly SemanticTokenType Event = new SemanticTokenType("event"); - public static readonly SemanticTokenType EnumMember = new SemanticTokenType("enumMember"); - - private readonly string _value; - - public SemanticTokenType(string type) => _value = type; - - public static implicit operator SemanticTokenType(string kind) => new SemanticTokenType(kind); - - public static implicit operator string(SemanticTokenType kind) => kind._value; - - public override string ToString() => _value; - public bool Equals(SemanticTokenType other) => _value == other._value; - - public override bool Equals(object obj) => obj is SemanticTokenType other && Equals(other); - - public override int GetHashCode() => _value.GetHashCode(); - - public static bool operator ==(SemanticTokenType left, SemanticTokenType right) => left.Equals(right); - - public static bool operator !=(SemanticTokenType left, SemanticTokenType right) => !left.Equals(right); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokens.cs b/src/Protocol/Models/Proposals/SemanticTokens.cs deleted file mode 100644 index c9e0386a9..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokens.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Immutable; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokens : ISemanticTokenResult - { - public SemanticTokens() - { - - } - - public SemanticTokens(SemanticTokensPartialResult partialResult) - { - Data = partialResult.Data; - } - - /// - /// An optional result id. If provided and clients support delta updating - /// the client will include the result id in the next semantic token request. - /// A server can then instead of computing all semantic tokens again simply - /// send a delta. - /// - [Optional] - public string? ResultId { get; set; } - - /// - /// The actual tokens. For a detailed description about how the data is - /// structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 - /// - /// - /// in the LSP spec - /// - public ImmutableArray Data { get; set; } = ImmutableArray.Empty; - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensDelta.cs b/src/Protocol/Models/Proposals/SemanticTokensDelta.cs deleted file mode 100644 index 9f2a867d3..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensDelta.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensDelta : ISemanticTokenResult - { - public SemanticTokensDelta() - { - - } - - public SemanticTokensDelta(SemanticTokensDeltaPartialResult partialResult) - { - Edits = partialResult.Edits; - } - - /// - /// An optional result id. If provided and clients support delta updating - /// the client will include the result id in the next semantic token request. - /// A server can then instead of computing all semantic tokens again simply - /// send a delta. - /// - [Optional] - public string? ResultId { get; set; } - - /// - /// For a detailed description how these edits are structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131 - /// - public Container Edits { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs b/src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs deleted file mode 100644 index f0177a2d5..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensDeltaParams.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.SemanticTokensFullDelta, Direction.ClientToServer)] - public class SemanticTokensDeltaParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, - IPartialItemRequest - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The previous result id. - /// - public string PreviousResultId { get; set; } = null!; - - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs deleted file mode 100644 index b0fbc2b09..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensDeltaPartialResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensDeltaPartialResult - { - /// - /// The actual tokens. For a detailed description about how the data is - /// structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 - /// - public Container Edits { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensEdit.cs b/src/Protocol/Models/Proposals/SemanticTokensEdit.cs deleted file mode 100644 index 6db64e1b1..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensEdit.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Immutable; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensEdit - { - /// - /// The start index of the edit - /// - /// - /// in the LSP spec - /// - public int Start { get; set; } - - /// - /// The number of items to delete - /// - /// - /// in the LSP spec - /// - public int DeleteCount { get; set; } - - /// - /// The actual tokens. For a detailed description about how the data is - /// structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 - /// - /// - /// in the LSP spec - /// - [Optional] - public ImmutableArray? Data { get; set; } = ImmutableArray.Empty; - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs b/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs deleted file mode 100644 index 28effe4cb..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensFullOrDelta.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - [JsonConverter(typeof(SemanticTokensFullOrDeltaConverter))] - public struct SemanticTokensFullOrDelta - { - public SemanticTokensFullOrDelta(SemanticTokensDelta delta) - { - Delta = delta; - Full = null; - } - - public SemanticTokensFullOrDelta(SemanticTokens full) - { - Delta = null; - Full = full; - } - - public SemanticTokensFullOrDelta(SemanticTokensFullOrDeltaPartialResult partialResult) - { - Full = null; - Delta = null; - - if (partialResult.IsDelta) - { - Delta = new SemanticTokensDelta(partialResult.Delta!) { - Edits = partialResult.Delta!.Edits - }; - } - - if (partialResult.IsFull) - { - Full = new SemanticTokens(partialResult.Full!); - } - } - - public bool IsFull => Full != null; - public SemanticTokens? Full { get; } - - public bool IsDelta => Delta != null; - public SemanticTokensDelta? Delta { get; } - - public static implicit operator SemanticTokensFullOrDelta(SemanticTokensDelta semanticTokensDelta) => new SemanticTokensFullOrDelta(semanticTokensDelta); - - public static implicit operator SemanticTokensFullOrDelta(SemanticTokens semanticTokens) => new SemanticTokensFullOrDelta(semanticTokens); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs deleted file mode 100644 index b4313ca02..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensFullOrDeltaPartialResult.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - [JsonConverter(typeof(SemanticTokensFullOrDeltaPartialResultConverter))] - public struct SemanticTokensFullOrDeltaPartialResult - { - public SemanticTokensFullOrDeltaPartialResult( - SemanticTokensPartialResult full - ) - { - Full = full; - Delta = null; - } - - public SemanticTokensFullOrDeltaPartialResult( - SemanticTokensDeltaPartialResult delta - ) - { - Full = null; - Delta = delta; - } - - public bool IsDelta => Delta != null; - public SemanticTokensDeltaPartialResult? Delta { get; } - - public bool IsFull => Full != null; - public SemanticTokensPartialResult? Full { get; } - - public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensPartialResult semanticTokensPartialResult) => - new SemanticTokensFullOrDeltaPartialResult(semanticTokensPartialResult); - - public static implicit operator SemanticTokensFullOrDeltaPartialResult(SemanticTokensDeltaPartialResult semanticTokensDeltaPartialResult) => - new SemanticTokensFullOrDeltaPartialResult(semanticTokensDeltaPartialResult); - - public static implicit operator SemanticTokensFullOrDelta(SemanticTokensFullOrDeltaPartialResult semanticTokensDeltaPartialResult) => - new SemanticTokensFullOrDelta(semanticTokensDeltaPartialResult); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensLegend.cs b/src/Protocol/Models/Proposals/SemanticTokensLegend.cs deleted file mode 100644 index 0676d6c58..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensLegend.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensLegend - { - private ImmutableDictionary? _tokenModifiersData; - private ImmutableDictionary? _tokenTypesData; - - /// - /// The token types a server uses. - /// - public Container TokenTypes { get; set; } = new Container(SemanticTokenType.Defaults); - - /// - /// The token modifiers a server uses. - /// - public Container TokenModifiers { get; set; } = new Container(SemanticTokenModifier.Defaults); - - public int GetTokenTypeIdentity(string tokenType) - { - EnsureTokenTypes(); - if (string.IsNullOrWhiteSpace(tokenType)) return 0; - return _tokenTypesData != null && _tokenTypesData.TryGetValue(tokenType, out var tokenTypeNumber) ? tokenTypeNumber : 0; - } - - public int GetTokenTypeIdentity(SemanticTokenType? tokenType) - { - EnsureTokenTypes(); - if (!tokenType.HasValue) return 0; - if (string.IsNullOrWhiteSpace(tokenType.Value)) return 0; - return _tokenTypesData != null && _tokenTypesData.TryGetValue(tokenType.Value, out var tokenTypeNumber) ? tokenTypeNumber : 0; - } - - public int GetTokenModifiersIdentity(params string[]? tokenModifiers) - { - EnsureTokenModifiers(); - if (tokenModifiers == null) return 0; - return tokenModifiers - .Where(z => !string.IsNullOrWhiteSpace(z)) - .Aggregate( - 0, - (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) - ? acc + tokenModifer - : acc - ); - } - - public int GetTokenModifiersIdentity(IEnumerable? tokenModifiers) - { - EnsureTokenModifiers(); - if (tokenModifiers == null) return 0; - return tokenModifiers - .Where(z => !string.IsNullOrWhiteSpace(z)) - .Aggregate( - 0, - (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) - ? acc + tokenModifer - : acc - ); - } - - public int GetTokenModifiersIdentity(params SemanticTokenModifier[]? tokenModifiers) - { - EnsureTokenModifiers(); - if (tokenModifiers == null) return 0; - return tokenModifiers - .Where(z => !string.IsNullOrWhiteSpace(z)) - .Aggregate( - 0, - (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) - ? acc + tokenModifer - : acc - ); - } - - public int GetTokenModifiersIdentity(IEnumerable? tokenModifiers) - { - EnsureTokenModifiers(); - if (tokenModifiers == null) return 0; - return tokenModifiers - .Where(z => !string.IsNullOrWhiteSpace(z)) - .Aggregate( - 0, - (acc, value) => _tokenModifiersData != null && _tokenModifiersData.TryGetValue(value, out var tokenModifer) - ? acc + tokenModifer - : acc - ); - } - - private void EnsureTokenTypes() => - _tokenTypesData ??= TokenTypes - .Select( - (value, index) => ( - value: new SemanticTokenType(value), - index - ) - ) - .Where(z => !string.IsNullOrWhiteSpace(z.value)) - .ToImmutableDictionary(z => z.value, z => z.index); - - private void EnsureTokenModifiers() => - _tokenModifiersData ??= TokenModifiers - .Select( - (value, index) => ( - value: new SemanticTokenModifier(value), - index - ) - ) - .Where(z => !string.IsNullOrWhiteSpace(z.value)) - .ToImmutableDictionary(z => z.value, z => Convert.ToInt32(Math.Pow(2, z.index))); - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensParams.cs b/src/Protocol/Models/Proposals/SemanticTokensParams.cs deleted file mode 100644 index cfda3f67b..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.SemanticTokensFull, Direction.ClientToServer)] - public class SemanticTokensParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, - IPartialItemRequest - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs b/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs deleted file mode 100644 index 1f47e2b0b..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensPartialResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Immutable; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class SemanticTokensPartialResult - { - /// - /// The actual tokens. For a detailed description about how the data is - /// structured pls see - /// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 - /// - public ImmutableArray Data { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensRangeParams.cs b/src/Protocol/Models/Proposals/SemanticTokensRangeParams.cs deleted file mode 100644 index 033c8b051..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensRangeParams.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - [Method(TextDocumentNames.SemanticTokensRange, Direction.ClientToServer)] - public class SemanticTokensRangeParams : IWorkDoneProgressParams, ITextDocumentIdentifierParams, - IPartialItemRequest - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The range the semantic tokens are requested for. - /// - public Range Range { get; set; } = null!; - - public ProgressToken? WorkDoneToken { get; set; } - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensRefreshParams.cs b/src/Protocol/Models/Proposals/SemanticTokensRefreshParams.cs deleted file mode 100644 index f3f025c6b..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensRefreshParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(WorkspaceNames.SemanticTokensRefresh, Direction.ServerToClient)] - public class SemanticTokensRefreshParams : IRequest { } -} diff --git a/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs b/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs deleted file mode 100644 index 28c072ce8..000000000 --- a/src/Protocol/Models/Proposals/SemanticTokensRegistrationOptions.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - [Obsolete(Constants.Proposal)] - [RegistrationName(TextDocumentNames.SemanticTokensRegistration)] - public class SemanticTokensRegistrationOptions : StaticWorkDoneTextDocumentRegistrationOptions - { - /// - /// The legend used by the server - /// - public SemanticTokensLegend Legend { get; set; } = null!; - - /// - /// Server supports providing semantic tokens for a specific range - /// of a document. - /// - [Optional] - public BooleanOr? Range { get; set; } - - /// - /// Server supports providing semantic tokens for a full document. - /// - [Optional] - public BooleanOr? Full { get; set; } - - /// - /// Call hierarchy options used during static registration. - /// - /// @since 3.16.0 - /// - [Obsolete(Constants.Proposal)] - public class StaticOptions : WorkDoneProgressOptions, IStaticRegistrationOptions - { - /// - /// The legend used by the server - /// - public SemanticTokensLegend Legend { get; set; } = null!; - - /// - /// Server supports providing semantic tokens for a specific range - /// of a document. - /// - [Optional] - public BooleanOr? Range { get; set; } - - /// - /// Server supports providing semantic tokens for a full document. - /// - [Optional] - public BooleanOr? Full { get; set; } - - public string? Id { get; set; } - } - - class SemanticTokensRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public SemanticTokensRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.SemanticTokensProvider)) - { - _handlersManager = handlersManager; - } - public override StaticOptions Convert(SemanticTokensRegistrationOptions source) - { - var result = new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - Legend = source.Legend, - Full = source.Full, - Range = source.Range - }; - if (result.Full != null && result.Full?.Value.Delta != true) - { - var edits = _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ISemanticTokensDeltaHandler)); - if (edits) - { - result.Full = new BooleanOr( - new SemanticTokensCapabilityRequestFull { - Delta = true - } - ); - } - } - - return result; - } - } - } -} diff --git a/src/Protocol/Models/Proposals/UniquenessLevel.cs b/src/Protocol/Models/Proposals/UniquenessLevel.cs deleted file mode 100644 index ff2b50b7a..000000000 --- a/src/Protocol/Models/Proposals/UniquenessLevel.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Diagnostics; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals -{ - /// - /// A set of predefined code action kinds - /// - [DebuggerDisplay("{" + nameof(_value) + "}")] - [JsonConverter(typeof(EnumLikeStringConverter))] - public readonly struct UniquenessLevel : IEquatable, IEnumLikeString - { - /// - /// The moniker is only unique inside a document - /// - public static readonly UniquenessLevel Document = new UniquenessLevel("document"); - - /// - /// The moniker is unique inside a project for which a dump got created - /// - public static readonly UniquenessLevel Project = new UniquenessLevel("project"); - - /// - /// The moniker is unique inside the group to which a project belongs - /// - public static readonly UniquenessLevel Group = new UniquenessLevel("group"); - - /// - /// The moniker is unique inside the moniker scheme. - /// - public static readonly UniquenessLevel Scheme = new UniquenessLevel("scheme"); - - /// - /// The moniker is globally unique - /// - public static readonly UniquenessLevel Global = new UniquenessLevel("global"); - - private readonly string? _value; - - public UniquenessLevel(string kind) => _value = kind; - - public static implicit operator UniquenessLevel(string kind) => new UniquenessLevel(kind); - - public static implicit operator string(UniquenessLevel kind) => kind._value ?? string.Empty; - - /// - public override string ToString() => _value ?? string.Empty; - - public bool Equals(UniquenessLevel other) => _value == other._value; - - public override bool Equals(object obj) => obj is UniquenessLevel other && Equals(other); - - public override int GetHashCode() => _value != null ? _value.GetHashCode() : 0; - - public static bool operator ==(UniquenessLevel left, UniquenessLevel right) => left.Equals(right); - - public static bool operator !=(UniquenessLevel left, UniquenessLevel right) => !left.Equals(right); - } -} \ No newline at end of file diff --git a/src/Protocol/Models/PublishDiagnosticsParams.cs b/src/Protocol/Models/PublishDiagnosticsParams.cs deleted file mode 100644 index 11826c7ce..000000000 --- a/src/Protocol/Models/PublishDiagnosticsParams.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.PublishDiagnostics, Direction.ServerToClient)] - public class PublishDiagnosticsParams : IRequest - { - /// - /// The URI for which diagnostic information is reported. - /// - public DocumentUri Uri { get; set; } = null!; - - /// - /// Optional the version number of the document the diagnostics are published for. - /// - /// @since 3.15.0 - /// - /// - /// in the LSP spec - /// - [Optional] - public int? Version { get; set; } - - /// - /// An array of diagnostic information items. - /// - public Container Diagnostics { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/RangeOrPlaceholderRange.cs b/src/Protocol/Models/RangeOrPlaceholderRange.cs deleted file mode 100644 index 9cebc79f3..000000000 --- a/src/Protocol/Models/RangeOrPlaceholderRange.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(RangeOrPlaceholderRangeConverter))] - public class RangeOrPlaceholderRange - { - private RenameDefaultBehavior? _renameDefaultBehavior; - private Range? _range; - private PlaceholderRange? _placeholderRange; - - public RangeOrPlaceholderRange(Range value) - { - _range = value; - } - - public RangeOrPlaceholderRange(PlaceholderRange value) - { - _placeholderRange = value; - } - - public RangeOrPlaceholderRange(RenameDefaultBehavior renameDefaultBehavior) - { - _renameDefaultBehavior = renameDefaultBehavior; - } - - public bool IsPlaceholderRange => _placeholderRange != null; - - public PlaceholderRange? PlaceholderRange - { - get => _placeholderRange; - set { - _placeholderRange = value; - _renameDefaultBehavior = default; - _range = null; - } - } - - public bool IsRange => _range is not null; - - public Range? Range - { - get => _range; - set { - _placeholderRange = default; - _renameDefaultBehavior = default; - _range = value; - } - } - - public bool IsDefaultBehavior => _renameDefaultBehavior is not null; - - public RenameDefaultBehavior? DefaultBehavior - { - get => _renameDefaultBehavior; - set { - _placeholderRange = default; - _renameDefaultBehavior = value; - _range = default; - } - } - - public object? RawValue - { - get { - if (IsPlaceholderRange) return PlaceholderRange; - if (IsRange) return Range; - if (IsDefaultBehavior) return DefaultBehavior; - return default; - } - } - - public static implicit operator RangeOrPlaceholderRange(PlaceholderRange value) => new RangeOrPlaceholderRange(value); - - public static implicit operator RangeOrPlaceholderRange(Range value) => new RangeOrPlaceholderRange(value); - } -} diff --git a/src/Protocol/Models/ReferenceContext.cs b/src/Protocol/Models/ReferenceContext.cs deleted file mode 100644 index 1c28399a9..000000000 --- a/src/Protocol/Models/ReferenceContext.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ReferenceContext - { - /// - /// Include the declaration of the current symbol. - /// - public bool IncludeDeclaration { get; set; } - } -} diff --git a/src/Protocol/Models/ReferenceParams.cs b/src/Protocol/Models/ReferenceParams.cs deleted file mode 100644 index dfed39d69..000000000 --- a/src/Protocol/Models/ReferenceParams.cs +++ /dev/null @@ -1,15 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.References, Direction.ClientToServer)] - public class ReferenceParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - public ReferenceContext Context { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/ReferenceRegistrationOptions.cs b/src/Protocol/Models/ReferenceRegistrationOptions.cs deleted file mode 100644 index 1a78689a9..000000000 --- a/src/Protocol/Models/ReferenceRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class ReferenceRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions { } - - class ReferenceRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public ReferenceRegistrationOptionsConverter() : base(nameof(ServerCapabilities.ReferencesProvider)) - { - } - public override StaticOptions Convert(ReferenceRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/Registration.cs b/src/Protocol/Models/Registration.cs deleted file mode 100644 index 3d720cfb6..000000000 --- a/src/Protocol/Models/Registration.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Net.NetworkInformation; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// General paramters to to regsiter for a capability. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class Registration - { - /// - /// The id used to register the request. The id can be used to deregister - /// the request again. - /// - public string Id { get; set; } = null!; - - /// - /// The method / capability to register for. - /// - public string Method { get; set; } = null!; - - /// - /// Options necessary for the registration. - /// - [Optional] - public object? RegisterOptions { get; set; } - - private string DebuggerDisplay => $"[{Id}] {( RegisterOptions is ITextDocumentRegistrationOptions td ? $"{td.DocumentSelector}" : string.Empty )} {Method}"; - - /// - public override string ToString() => DebuggerDisplay; - - public class TextDocumentComparer : IEqualityComparer - { - public bool Equals(Registration? x, Registration? y) - { - if (ReferenceEquals(x, y)) return true; - if (ReferenceEquals(x, null)) return false; - if (ReferenceEquals(y, null)) return false; - if (x.GetType() != y.GetType()) return false; - if (x.RegisterOptions is ITextDocumentRegistrationOptions xTdro && y.RegisterOptions is ITextDocumentRegistrationOptions yTdro) - { - // Id doesn't matter if they target the same text document - // this is arbitrary but should be good in most cases. - return ( x.Id == y.Id || xTdro.DocumentSelector == yTdro.DocumentSelector ) && x.Method == y.Method; - } - - return x.Id == y.Id && x.Method == y.Method; - } - - public int GetHashCode(Registration? obj) - { - unchecked - { - if (obj!.RegisterOptions is ITextDocumentRegistrationOptions tdro) - { - var hashCode = obj.Method.GetHashCode(); - return ( hashCode * 397 ) ^ ( tdro.DocumentSelector != null ? tdro.DocumentSelector.GetHashCode() : 0 ); - } - else - { - var hashCode = obj!.Id.GetHashCode(); - hashCode = ( hashCode * 397 ) ^ obj.Method.GetHashCode(); - return ( hashCode * 397 ) ^ ( obj.RegisterOptions != null ? obj.RegisterOptions.GetHashCode() : 0 ); - } - } - } - } - } -} diff --git a/src/Protocol/Models/RegistrationContainer.cs b/src/Protocol/Models/RegistrationContainer.cs deleted file mode 100644 index 0ea0cbafd..000000000 --- a/src/Protocol/Models/RegistrationContainer.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class RegistrationContainer : Container - { - public RegistrationContainer() : this(Enumerable.Empty()) - { - } - - public RegistrationContainer(IEnumerable items) : base(items) - { - } - - public RegistrationContainer(params Registration[] items) : base(items) - { - } - - - public static implicit operator RegistrationContainer(Registration[] items) => new RegistrationContainer(items); - - public static implicit operator RegistrationContainer(Collection items) => new RegistrationContainer(items); - - public static implicit operator RegistrationContainer(List items) => new RegistrationContainer(items); - } -} diff --git a/src/Protocol/Models/RegistrationParams.cs b/src/Protocol/Models/RegistrationParams.cs deleted file mode 100644 index 6d9e7efc4..000000000 --- a/src/Protocol/Models/RegistrationParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] - public class RegistrationParams : IRequest - { - public RegistrationContainer Registrations { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/RenameDefaultBehavior.cs b/src/Protocol/Models/RenameDefaultBehavior.cs deleted file mode 100644 index 20e7b5956..000000000 --- a/src/Protocol/Models/RenameDefaultBehavior.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class RenameDefaultBehavior - { - public bool DefaultBehavior { get; set; } - } -} diff --git a/src/Protocol/Models/RenameParams.cs b/src/Protocol/Models/RenameParams.cs deleted file mode 100644 index 884fa804e..000000000 --- a/src/Protocol/Models/RenameParams.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.Rename, Direction.ClientToServer)] - public class RenameParams : ITextDocumentIdentifierParams, IRequest, IWorkDoneProgressParams - { - /// - /// The document to format. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The position at which this request was sent. - /// - public Position Position { get; set; } = null!; - - /// - /// The new name of the symbol. If the given name is not valid the - /// request must return a [ResponseError](#ResponseError) with an - /// appropriate message set. - /// - public string NewName { get; set; } = null!; - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/RenameRegistrationOptions.cs b/src/Protocol/Models/RenameRegistrationOptions.cs deleted file mode 100644 index 117c747a9..000000000 --- a/src/Protocol/Models/RenameRegistrationOptions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class RenameRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// Renames should be checked and tested before being executed. - /// - [Optional] - public bool PrepareProvider { get; set; } - - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// Renames should be checked and tested before being executed. - /// - [Optional] - public bool PrepareProvider { get; set; } - } - - class RenameRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - private readonly IHandlersManager _handlersManager; - - public RenameRegistrationOptionsConverter(IHandlersManager handlersManager) : base(nameof(ServerCapabilities.RenameProvider)) - { - _handlersManager = handlersManager; - } - public override StaticOptions Convert(RenameRegistrationOptions source) => new StaticOptions { - PrepareProvider = source.PrepareProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IPrepareRenameHandler)), - WorkDoneProgress = source.WorkDoneProgress - }; - } - } -} diff --git a/src/Protocol/Models/SelectionRange.cs b/src/Protocol/Models/SelectionRange.cs deleted file mode 100644 index d4948e8ab..000000000 --- a/src/Protocol/Models/SelectionRange.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Diagnostics; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class SelectionRange - { - /// - /// The [range](#Range) of this selection range. - /// - public Range Range { get; set; } = null!; - - /// - /// The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. - /// - public SelectionRange Parent { get; set; } = null!; - - private string DebuggerDisplay => $"{Range} {{{Parent}}}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/SelectionRangeParams.cs b/src/Protocol/Models/SelectionRangeParams.cs deleted file mode 100644 index 9c03e67fc..000000000 --- a/src/Protocol/Models/SelectionRangeParams.cs +++ /dev/null @@ -1,27 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.SelectionRange, Direction.ClientToServer)] - public class SelectionRangeParams : ITextDocumentIdentifierParams, IPartialItemsRequest?, SelectionRange>, IWorkDoneProgressParams - { - /// - /// The text document. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The positions inside the text document. - /// - public Container Positions { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/SelectionRangeRegistrationOptions.cs b/src/Protocol/Models/SelectionRangeRegistrationOptions.cs deleted file mode 100644 index 0afc70a76..000000000 --- a/src/Protocol/Models/SelectionRangeRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class SelectionRangeRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions { } - - class SelectionRangeRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public SelectionRangeRegistrationOptionsConverter() : base(nameof(ServerCapabilities.SelectionRangeProvider)) - { - } - public override StaticOptions Convert(SelectionRangeRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Models/SetTraceParams.cs b/src/Protocol/Models/SetTraceParams.cs deleted file mode 100644 index 2b3ddceb7..000000000 --- a/src/Protocol/Models/SetTraceParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.SetTrace, Direction.ClientToServer)] - public class SetTraceParams : IRequest - { - /// - /// The new value that should be assigned to the trace setting. - /// - public InitializeTrace Value { get; set; } - } -} diff --git a/src/Protocol/Models/ShowDocumentParams.cs b/src/Protocol/Models/ShowDocumentParams.cs deleted file mode 100644 index 99c383d3e..000000000 --- a/src/Protocol/Models/ShowDocumentParams.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Params to show a document. - /// - /// @since 3.16.0 - proposed state - /// - [Parallel] - [Method(WindowNames.ShowDocument, Direction.ServerToClient)] - public class ShowDocumentParams : IRequest - { - /// - /// The document uri to show. - /// - public DocumentUri Uri { get; set; } = null!; - - /// - /// Indicates to show the resource in an external program. - /// To show for example `https://code.visualstudio.com/` - /// in the default WEB browser set `external` to `true`. - /// - [Optional] - public bool? External { get; set; } - - /// - /// An optional property to indicate whether the editor - /// showing the document should take focus or not. - /// Clients might ignore this property if an external - /// program is started. - /// - [Optional] - public bool? TakeFocus { get; set; } - - /// - /// An optional selection range if the document is a text - /// document. Clients might ignore the property if an - /// external program is started or the file is not a text - /// file. - /// - [Optional] - public Range? Selection { get; set; } - } -} diff --git a/src/Protocol/Models/ShowDocumentResult.cs b/src/Protocol/Models/ShowDocumentResult.cs deleted file mode 100644 index af366230d..000000000 --- a/src/Protocol/Models/ShowDocumentResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The result of an show document request. - /// - /// @since 3.16.0 - proposed state - /// - public class ShowDocumentResult - { - /// - /// A boolean indicating if the show was successful. - /// - public bool Success { get; set; } - } -} \ No newline at end of file diff --git a/src/Protocol/Models/ShowMessageParams.cs b/src/Protocol/Models/ShowMessageParams.cs deleted file mode 100644 index f4caf80ab..000000000 --- a/src/Protocol/Models/ShowMessageParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The show message notification is sent from a server to a client to ask the client to display a particular message in the user interface. - /// - [Method(WindowNames.ShowMessage, Direction.ServerToClient)] - public class ShowMessageParams : IRequest - { - /// - /// The message type. See {@link MessageType}. - /// - public MessageType Type { get; set; } - - /// - /// The actual message. - /// - public string Message { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/ShowMessageRequestParams.cs b/src/Protocol/Models/ShowMessageRequestParams.cs deleted file mode 100644 index 8d8d8c826..000000000 --- a/src/Protocol/Models/ShowMessageRequestParams.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The show message request is sent from a server to a client to ask the client to display a particular message in the user interface. In addition to the show message notification - /// the request allows to pass actions and to wait for an answer from the client. - /// - [Method(WindowNames.ShowMessageRequest, Direction.ServerToClient)] - public class ShowMessageRequestParams : IRequest - { - /// - /// The message type. See {@link MessageType} - /// - public MessageType Type { get; set; } - - /// - /// The actual message - /// - public string Message { get; set; } = null!; - - /// - /// The message action items to present. - /// - [Optional] - public Container? Actions { get; set; } - } -} diff --git a/src/Protocol/Models/ShutdownParams.cs b/src/Protocol/Models/ShutdownParams.cs deleted file mode 100644 index d240a9d14..000000000 --- a/src/Protocol/Models/ShutdownParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(GeneralNames.Shutdown, Direction.ClientToServer)] - public class ShutdownParams : IRequest - { - public static ShutdownParams Instance { get; } = new ShutdownParams(); - } -} diff --git a/src/Protocol/Models/SignatureHelp.cs b/src/Protocol/Models/SignatureHelp.cs deleted file mode 100644 index 83236e23e..000000000 --- a/src/Protocol/Models/SignatureHelp.cs +++ /dev/null @@ -1,29 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Signature help represents the signature of something - /// callable. There can be multiple signature but only one - /// active and only one active parameter. - /// - public class SignatureHelp - { - /// - /// One or more signatures. - /// - public Container Signatures { get; set; } = new Container(); - - /// - /// The active signature. - /// - [Optional] - public int? ActiveSignature { get; set; } - - /// - /// The active parameter of the active signature. - /// - [Optional] - public int? ActiveParameter { get; set; } - } -} diff --git a/src/Protocol/Models/SignatureHelpContext.cs b/src/Protocol/Models/SignatureHelpContext.cs deleted file mode 100644 index 8c6d07996..000000000 --- a/src/Protocol/Models/SignatureHelpContext.cs +++ /dev/null @@ -1,42 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Additional information about the context in which a signature help request was triggered. - /// - /// @since 3.15.0 - /// - public class SignatureHelpContext - { - /// - /// Action that caused signature help to be triggered. - /// - public SignatureHelpTriggerKind TriggerKind { get; set; } - - /// - /// Character that caused signature help to be triggered. - /// - /// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` - /// - [Optional] - public string? TriggerCharacter { get; set; } - - /// - /// `true` if signature help was already showing when it was triggered. - /// - /// Retriggers occur when the signature help is already active and can be caused by actions such as - /// typing a trigger character, a cursor move, or document content changes. - /// - public bool IsRetrigger { get; set; } - - /// - /// The currently active `SignatureHelp`. - /// - /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on - /// the user navigating through available signatures. - /// - [Optional] - public SignatureHelp? ActiveSignatureHelp { get; set; } - } -} diff --git a/src/Protocol/Models/SignatureHelpParams.cs b/src/Protocol/Models/SignatureHelpParams.cs deleted file mode 100644 index 8a66527c2..000000000 --- a/src/Protocol/Models/SignatureHelpParams.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.SignatureHelp, Direction.ClientToServer)] - public class SignatureHelpParams : WorkDoneTextDocumentPositionParams, IRequest - { - /// - /// The signature help context. This is only available if the client specifies - /// to send this using the client capability `textDocument.signatureHelp.contextSupport === true` - /// - /// @since 3.15.0 - /// - public SignatureHelpContext Context { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/SignatureHelpRegistrationOptions.cs b/src/Protocol/Models/SignatureHelpRegistrationOptions.cs deleted file mode 100644 index 43877c96f..000000000 --- a/src/Protocol/Models/SignatureHelpRegistrationOptions.cs +++ /dev/null @@ -1,62 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class SignatureHelpRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - /// - /// The characters that trigger signature help - /// automatically. - /// - [Optional] - public Container? TriggerCharacters { get; set; } - - /// - /// List of characters that re-trigger signature help. - /// - /// These trigger characters are only active when signature help is already showing. All trigger characters - /// are also counted as re-trigger characters. - /// - /// @since 3.15.0 - /// - [Optional] - public Container? RetriggerCharacters { get; set; } - - /// - /// Signature help options. - /// - public class StaticOptions : WorkDoneProgressOptions - { - /// - /// The characters that trigger signature help - /// automatically. - /// - [Optional] - public Container? TriggerCharacters { get; set; } - - /// - /// List of characters that re-trigger signature help. - /// - /// These trigger characters are only active when signature help is already showing. All trigger characters - /// are also counted as re-trigger characters. - /// - /// @since 3.15.0 - /// - [Optional] - public Container? RetriggerCharacters { get; set; } - } - - class SignatureHelpRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public SignatureHelpRegistrationOptionsConverter() : base(nameof(ServerCapabilities.SignatureHelpProvider)) - { - } - public override StaticOptions Convert(SignatureHelpRegistrationOptions source) => new StaticOptions { - TriggerCharacters = source.TriggerCharacters, - RetriggerCharacters = source.RetriggerCharacters, - WorkDoneProgress = source.WorkDoneProgress - }; - } - } -} diff --git a/src/Protocol/Models/SignatureHelpTriggerKind.cs b/src/Protocol/Models/SignatureHelpTriggerKind.cs deleted file mode 100644 index e47876e70..000000000 --- a/src/Protocol/Models/SignatureHelpTriggerKind.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// How a signature help was triggered. - /// - /// @since 3.15.0 - /// - [JsonConverter(typeof(NumberEnumConverter))] - public enum SignatureHelpTriggerKind - { - /// - /// Signature help was invoked manually by the user or by a command. - /// - Invoked = 1, - - /// - /// Signature help was triggered by a trigger character. - /// - TriggerCharacter = 2, - - /// - /// Signature help was triggered by the cursor moving or by the document content changing. - /// - ContentChange = 3, - } -} diff --git a/src/Protocol/Models/SignatureInformation.cs b/src/Protocol/Models/SignatureInformation.cs deleted file mode 100644 index d5d4bff05..000000000 --- a/src/Protocol/Models/SignatureInformation.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Represents the signature of something callable. A signature - /// can have a label, like a function-name, a doc-comment, and - /// a set of parameters. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class SignatureInformation - { - /// - /// The label of this signature. Will be shown in - /// the UI. - /// - public string Label { get; set; } = null!; - - /// - /// The human-readable doc-comment of this signature. Will be shown - /// in the UI but can be omitted. - /// - [Optional] - public StringOrMarkupContent? Documentation { get; set; } - - /// - /// The parameters of this signature. - /// - [Optional] - public Container? Parameters { get; set; } - - /// - /// The index of the active parameter. - /// - /// If provided, this is used in place of `SignatureHelp.activeParameter`. - /// - /// @since 3.16.0 - proposed state - /// - [Optional] - public int? ActiveParameter { get; set; } - - private string DebuggerDisplay => $"{Label}{Documentation?.ToString() ?? ""}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/StaticRegistrationOptions.cs b/src/Protocol/Models/StaticRegistrationOptions.cs deleted file mode 100644 index c34d947b0..000000000 --- a/src/Protocol/Models/StaticRegistrationOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class StaticRegistrationOptions : IStaticRegistrationOptions - { - /// - /// The id used to register the request. The id can be used to deregister the request again. See also Registration#id. - /// - [Optional] - public string? Id { get; set; } - } -} diff --git a/src/Protocol/Models/StaticTextDocumentRegistrationOptions.cs b/src/Protocol/Models/StaticTextDocumentRegistrationOptions.cs deleted file mode 100644 index b6fce0922..000000000 --- a/src/Protocol/Models/StaticTextDocumentRegistrationOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Static registration options to be returned in the initialize request. - /// - public class StaticTextDocumentRegistrationOptions : TextDocumentRegistrationOptions, IStaticRegistrationOptions - { - /// - /// The id used to register the request. The id can be used to deregister the request again. See also Registration#id. - /// - [Optional] - public string? Id { get; set; } - } -} diff --git a/src/Protocol/Models/StaticWorkDoneTextDocumentRegistrationOptions.cs b/src/Protocol/Models/StaticWorkDoneTextDocumentRegistrationOptions.cs deleted file mode 100644 index a1352398d..000000000 --- a/src/Protocol/Models/StaticWorkDoneTextDocumentRegistrationOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Static registration options to be returned in the initialize request. - /// - public class StaticWorkDoneTextDocumentRegistrationOptions : StaticTextDocumentRegistrationOptions, IWorkDoneProgressOptions - { - /// - [Optional] - public bool WorkDoneProgress { get; set; } - } -} diff --git a/src/Protocol/Models/SymbolInformation.cs b/src/Protocol/Models/SymbolInformation.cs deleted file mode 100644 index cc5dbad4b..000000000 --- a/src/Protocol/Models/SymbolInformation.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Diagnostics; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class SymbolInformation - { - /// - /// The name of this symbol. - /// - public string Name { get; set; } = null!; - - /// - /// The kind of this symbol. - /// - public SymbolKind Kind { get; set; } - - /// - /// Tags for this completion item. - /// - /// @since 3.16.0 - Proposed state - /// - [Obsolete(Constants.Proposal)] - [Optional] - public Container? Tags { get; set; } - - /// - /// Indicates if this item is deprecated. - /// - [Optional] - public bool Deprecated { get; set; } - - /// - /// The location of this symbol. - /// - public Location Location { get; set; } = null!; - - /// - /// The name of the symbol containing this symbol. - /// - [Optional] - public string? ContainerName { get; set; } - - private string DebuggerDisplay => $"[{Kind}@{Location}] {Name}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/SymbolInformationOrDocumentSymbol.cs b/src/Protocol/Models/SymbolInformationOrDocumentSymbol.cs deleted file mode 100644 index 284c6ed4d..000000000 --- a/src/Protocol/Models/SymbolInformationOrDocumentSymbol.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Diagnostics; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [JsonConverter(typeof(SymbolInformationOrDocumentSymbolConverter))] - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public struct SymbolInformationOrDocumentSymbol - { - public SymbolInformationOrDocumentSymbol(DocumentSymbol documentSymbol) - { - DocumentSymbol = documentSymbol; - SymbolInformation = default; - } - - public SymbolInformationOrDocumentSymbol(SymbolInformation symbolInformation) - { - DocumentSymbol = default; - SymbolInformation = symbolInformation; - } - - public bool IsDocumentSymbolInformation => SymbolInformation != null; - public SymbolInformation? SymbolInformation { get; } - - public bool IsDocumentSymbol => DocumentSymbol != null; - public DocumentSymbol? DocumentSymbol { get; } - - public static SymbolInformationOrDocumentSymbol Create(SymbolInformation value) => value; - - public static SymbolInformationOrDocumentSymbol Create(DocumentSymbol value) => value; - - public static implicit operator SymbolInformationOrDocumentSymbol(SymbolInformation value) => new SymbolInformationOrDocumentSymbol(value); - - public static implicit operator SymbolInformationOrDocumentSymbol(DocumentSymbol value) => new SymbolInformationOrDocumentSymbol(value); - - private string DebuggerDisplay => IsDocumentSymbol ? DocumentSymbol!.ToString() : IsDocumentSymbolInformation ? SymbolInformation!.ToString() : string.Empty; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/SymbolInformationOrDocumentSymbolContainer.cs b/src/Protocol/Models/SymbolInformationOrDocumentSymbolContainer.cs deleted file mode 100644 index f441ae94f..000000000 --- a/src/Protocol/Models/SymbolInformationOrDocumentSymbolContainer.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class SymbolInformationOrDocumentSymbolContainer : Container - { - public SymbolInformationOrDocumentSymbolContainer() : this(Enumerable.Empty()) - { - } - - public SymbolInformationOrDocumentSymbolContainer(IEnumerable items) : base(items) - { - } - - public SymbolInformationOrDocumentSymbolContainer(params SymbolInformationOrDocumentSymbol[] items) : base(items) - { - } - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(SymbolInformationOrDocumentSymbol[] items) => - new SymbolInformationOrDocumentSymbolContainer(items); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(Collection items) => - new SymbolInformationOrDocumentSymbolContainer(items); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(List items) => - new SymbolInformationOrDocumentSymbolContainer(items); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(SymbolInformation[] items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(Collection items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(List items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(DocumentSymbol[] items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(Collection items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - - public static implicit operator SymbolInformationOrDocumentSymbolContainer(List items) => - new SymbolInformationOrDocumentSymbolContainer(items.Select(SymbolInformationOrDocumentSymbol.Create)); - } -} diff --git a/src/Protocol/Models/TelemetryEventParams.cs b/src/Protocol/Models/TelemetryEventParams.cs deleted file mode 100644 index cee1c2c89..000000000 --- a/src/Protocol/Models/TelemetryEventParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using MediatR; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WindowNames.TelemetryEvent, Direction.ServerToClient)] - public class TelemetryEventParams : IRequest - { - [JsonExtensionData] public IDictionary Data { get; set; } = new Dictionary(); - } -} diff --git a/src/Protocol/Models/TextDocumentChangeRegistrationOptions.cs b/src/Protocol/Models/TextDocumentChangeRegistrationOptions.cs deleted file mode 100644 index 7409ffbf2..000000000 --- a/src/Protocol/Models/TextDocumentChangeRegistrationOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Descibe options to be used when registered for text document change events. - /// - public class TextDocumentChangeRegistrationOptions : TextDocumentRegistrationOptions - { - /// - /// How documents are synced to the server. See TextDocumentSyncKind.Full - /// and TextDocumentSyncKindIncremental. - /// - public TextDocumentSyncKind SyncKind { get; set; } - } -} diff --git a/src/Protocol/Models/TextDocumentContentChangeEvent.cs b/src/Protocol/Models/TextDocumentContentChangeEvent.cs deleted file mode 100644 index 46a4532b6..000000000 --- a/src/Protocol/Models/TextDocumentContentChangeEvent.cs +++ /dev/null @@ -1,31 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// An event describing a change to a text document. If range and rangeLength are omitted - /// the new text is considered to be the full content of the document. - /// - public class TextDocumentContentChangeEvent - { - /// - /// The range of the document that changed. - /// - [Optional] - public Range? Range { get; set; } - - /// - /// The length of the range that got replaced. - /// - /// - /// in the LSP spec - /// - [Optional] - public int RangeLength { get; set; } - - /// - /// The new text of the document. - /// - public string Text { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/TextDocumentEdit.cs b/src/Protocol/Models/TextDocumentEdit.cs deleted file mode 100644 index fbd4c58a2..000000000 --- a/src/Protocol/Models/TextDocumentEdit.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class TextDocumentEdit - { - /// - /// The text document to change. - /// - public VersionedTextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The edits to be applied. - /// - public TextEditContainer Edits { get; set; } = null!; - } -} diff --git a/src/Protocol/Models/TextDocumentRegistrationOptions.cs b/src/Protocol/Models/TextDocumentRegistrationOptions.cs deleted file mode 100644 index 580a3f327..000000000 --- a/src/Protocol/Models/TextDocumentRegistrationOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class TextDocumentRegistrationOptions : ITextDocumentRegistrationOptions - { - /// - /// A document selector to identify the scope of the registration. If set to null - /// the document selector provided on the client side will be used. - /// - public DocumentSelector? DocumentSelector { get; set; } - } -} diff --git a/src/Protocol/Models/TextDocumentSaveRegistrationOptions.cs b/src/Protocol/Models/TextDocumentSaveRegistrationOptions.cs deleted file mode 100644 index 8b0739eb3..000000000 --- a/src/Protocol/Models/TextDocumentSaveRegistrationOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class TextDocumentSaveRegistrationOptions : TextDocumentRegistrationOptions - { - /// - /// The client is supposed to include the content on save. - /// - [Optional] - public bool IncludeText { get; set; } - } -} diff --git a/src/Protocol/Models/TypeDefinitionParams.cs b/src/Protocol/Models/TypeDefinitionParams.cs deleted file mode 100644 index c9a95ef66..000000000 --- a/src/Protocol/Models/TypeDefinitionParams.cs +++ /dev/null @@ -1,13 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(TextDocumentNames.TypeDefinition, Direction.ClientToServer)] - public class TypeDefinitionParams : WorkDoneTextDocumentPositionParams, IPartialItemsRequest - { - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - } -} diff --git a/src/Protocol/Models/TypeDefinitionRegistrationOptions.cs b/src/Protocol/Models/TypeDefinitionRegistrationOptions.cs deleted file mode 100644 index 2a45db129..000000000 --- a/src/Protocol/Models/TypeDefinitionRegistrationOptions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class TypeDefinitionRegistrationOptions : WorkDoneTextDocumentRegistrationOptions - { - public class StaticOptions : StaticWorkDoneTextDocumentRegistrationOptions { } - - class TypeDefinitionRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public TypeDefinitionRegistrationOptionsConverter() : base(nameof(ServerCapabilities.TypeDefinitionProvider)) - { - } - public override StaticOptions Convert(TypeDefinitionRegistrationOptions source) => new StaticOptions { - WorkDoneProgress = source.WorkDoneProgress, - DocumentSelector = source.DocumentSelector - }; - } - } -} diff --git a/src/Protocol/Models/Unregistration.cs b/src/Protocol/Models/Unregistration.cs deleted file mode 100644 index 9ddec9357..000000000 --- a/src/Protocol/Models/Unregistration.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Diagnostics; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// General parameters to unregister a request or notification. - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class Unregistration - { - /// - /// The id used to unregister the request or notification. Usually an id - /// provided during the register request. - /// - public string Id { get; set; } = null!; - - /// - /// The method to unregister for. - /// - public string Method { get; set; } = null!; - - public static implicit operator Unregistration(Registration registration) => - new Unregistration { - Id = registration.Id, - Method = registration.Method - }; - - private string DebuggerDisplay => $"[{Id}] {Method}"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/UnregistrationContainer.cs b/src/Protocol/Models/UnregistrationContainer.cs deleted file mode 100644 index b8cc120a4..000000000 --- a/src/Protocol/Models/UnregistrationContainer.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class UnregistrationContainer : Container - { - public UnregistrationContainer() : this(Enumerable.Empty()) - { - } - - public UnregistrationContainer(IEnumerable items) : base(items) - { - } - - public UnregistrationContainer(params Unregistration[] items) : base(items) - { - } - - - public static implicit operator UnregistrationContainer(Unregistration[] items) => new UnregistrationContainer(items); - - public static implicit operator UnregistrationContainer(Collection items) => new UnregistrationContainer(items); - - public static implicit operator UnregistrationContainer(List items) => new UnregistrationContainer(items); - - - public static implicit operator UnregistrationContainer(Registration[] items) => new UnregistrationContainer(items.Select(x => (Unregistration) x)); - - public static implicit operator UnregistrationContainer(Collection items) => new UnregistrationContainer(items.Select(x => (Unregistration) x)); - - public static implicit operator UnregistrationContainer(List items) => new UnregistrationContainer(items.Select(x => (Unregistration) x)); - } -} diff --git a/src/Protocol/Models/UnregistrationParams.cs b/src/Protocol/Models/UnregistrationParams.cs deleted file mode 100644 index efd11274e..000000000 --- a/src/Protocol/Models/UnregistrationParams.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediatR; -using Newtonsoft.Json; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(ClientNames.UnregisterCapability, Direction.ServerToClient)] - public class UnregistrationParams : IRequest - { - public UnregistrationContainer? Unregisterations { get; set; } - - // Placeholder for v4 support - [JsonIgnore] - public UnregistrationContainer? Unregistrations - { - get => Unregisterations; - set => Unregisterations = value; - } - } -} diff --git a/src/Protocol/Models/WillSaveTextDocumentParams.cs b/src/Protocol/Models/WillSaveTextDocumentParams.cs deleted file mode 100644 index 7591827bb..000000000 --- a/src/Protocol/Models/WillSaveTextDocumentParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The parameters send in a will save text document notification. - /// - [Method(TextDocumentNames.WillSave, Direction.ClientToServer)] - public class WillSaveTextDocumentParams : IRequest - { - /// - /// The document that will be saved. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The 'TextDocumentSaveReason'. - /// - public TextDocumentSaveReason Reason { get; set; } - } -} diff --git a/src/Protocol/Models/WillSaveWaitUntilTextDocumentParams.cs b/src/Protocol/Models/WillSaveWaitUntilTextDocumentParams.cs deleted file mode 100644 index c43894a07..000000000 --- a/src/Protocol/Models/WillSaveWaitUntilTextDocumentParams.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The parameters send in a will save text document notification. - /// - [Method(TextDocumentNames.WillSaveWaitUntil, Direction.ClientToServer)] - public class WillSaveWaitUntilTextDocumentParams : IRequest - { - /// - /// The document that will be saved. - /// - public TextDocumentIdentifier TextDocument { get; set; } = null!; - - /// - /// The 'TextDocumentSaveReason'. - /// - public TextDocumentSaveReason Reason { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneProgress.cs b/src/Protocol/Models/WorkDoneProgress.cs deleted file mode 100644 index e80ffe560..000000000 --- a/src/Protocol/Models/WorkDoneProgress.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public abstract class WorkDoneProgress - { - public WorkDoneProgress(WorkDoneProgressKind kind) => Kind = kind; - - public WorkDoneProgressKind Kind { get; } - - /// - /// Optional, a final message indicating to for example indicate the outcome - /// of the operation. - /// - [Optional] - public string? Message { get; set; } - } - - [JsonConverter(typeof(EnumLikeStringConverter))] - public readonly struct WorkDoneProgressKind : IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = - new Lazy>( - () => { - return typeof(WorkDoneProgressKind) - .GetFields(BindingFlags.Static | BindingFlags.Public) - .Select(z => z.GetValue(null)) - .Cast() - .ToArray(); - } - ); - - public static IEnumerable Defaults => _defaults.Value; - - public static WorkDoneProgressKind Begin = new WorkDoneProgressKind("begin"); - public static WorkDoneProgressKind End = new WorkDoneProgressKind("end"); - public static WorkDoneProgressKind Report = new WorkDoneProgressKind("report"); - - private readonly string _value; - - public WorkDoneProgressKind(string modifier) => _value = modifier; - - public static implicit operator WorkDoneProgressKind(string kind) => new WorkDoneProgressKind(kind); - - public static implicit operator string(WorkDoneProgressKind kind) => kind._value; - - public override string ToString() => _value; - public bool Equals(WorkDoneProgressKind other) => _value == other._value; - - public override bool Equals(object obj) => obj is WorkDoneProgressKind other && Equals(other); - - public override int GetHashCode() => _value.GetHashCode(); - - public static bool operator ==(WorkDoneProgressKind left, WorkDoneProgressKind right) => left.Equals(right); - - public static bool operator !=(WorkDoneProgressKind left, WorkDoneProgressKind right) => !left.Equals(right); - } -} diff --git a/src/Protocol/Models/WorkDoneProgressBegin.cs b/src/Protocol/Models/WorkDoneProgressBegin.cs deleted file mode 100644 index af4cce085..000000000 --- a/src/Protocol/Models/WorkDoneProgressBegin.cs +++ /dev/null @@ -1,45 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// To start progress reporting a `$/progress` notification with the following payload must be sent - /// - public class WorkDoneProgressBegin : WorkDoneProgress - { - public WorkDoneProgressBegin() : base(WorkDoneProgressKind.Begin) - { - } - - /// - /// Mandatory title of the progress operation. Used to briefly inform about - /// the kind of operation being performed. - /// - /// Examples: "Indexing" or "Linking dependencies". - /// - public string Title { get; set; } = null!; - - /// - /// Controls if a cancel button should show to allow the user to cancel the - /// long running operation. Clients that don't support cancellation are allowed - /// to ignore the setting. - /// - [Optional] - public bool Cancellable { get; set; } - - /// - /// Optional progress percentage to display (value 100 is considered 100%). - /// If not provided infinite progress is assumed and clients are allowed - /// to ignore the `percentage` value in subsequent in report notifications. - /// - /// The value should be steadily rising. Clients are free to ignore values - /// that are not following this rule. - /// - /// - /// TODO: Change this (breaking) - /// in the LSP spec - /// - [Optional] - public double? Percentage { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneProgressCancelParams.cs b/src/Protocol/Models/WorkDoneProgressCancelParams.cs deleted file mode 100644 index 82e6f81fb..000000000 --- a/src/Protocol/Models/WorkDoneProgressCancelParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WindowNames.WorkDoneProgressCancel, Direction.ClientToServer)] - public class WorkDoneProgressCancelParams : IRequest - { - /// - /// The token to be used to report progress. - /// - public ProgressToken? Token { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneProgressCreateParams.cs b/src/Protocol/Models/WorkDoneProgressCreateParams.cs deleted file mode 100644 index 8718e0fd1..000000000 --- a/src/Protocol/Models/WorkDoneProgressCreateParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WindowNames.WorkDoneProgressCreate, Direction.ServerToClient)] - public class WorkDoneProgressCreateParams : IRequest - { - /// - /// The token to be used to report progress. - /// - public ProgressToken? Token { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneProgressEnd.cs b/src/Protocol/Models/WorkDoneProgressEnd.cs deleted file mode 100644 index 287aae4c0..000000000 --- a/src/Protocol/Models/WorkDoneProgressEnd.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Signaling the end of a progress reporting is done using the following payload - /// - public class WorkDoneProgressEnd : WorkDoneProgress - { - public WorkDoneProgressEnd() : base(WorkDoneProgressKind.End) - { - } - } -} diff --git a/src/Protocol/Models/WorkDoneProgressOptions.cs b/src/Protocol/Models/WorkDoneProgressOptions.cs deleted file mode 100644 index 0e06320f7..000000000 --- a/src/Protocol/Models/WorkDoneProgressOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class WorkDoneProgressOptions : IWorkDoneProgressOptions - { - [Optional] public bool WorkDoneProgress { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneProgressReport.cs b/src/Protocol/Models/WorkDoneProgressReport.cs deleted file mode 100644 index c5d7149fd..000000000 --- a/src/Protocol/Models/WorkDoneProgressReport.cs +++ /dev/null @@ -1,39 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// Reporting progress is done using the following payload - /// - public class WorkDoneProgressReport : WorkDoneProgress - { - public WorkDoneProgressReport() : base(WorkDoneProgressKind.Report) - { - } - - /// - /// Controls enablement state of a cancel button. This property is only valid if a cancel - /// button got requested in the `WorkDoneProgressStart` payload. - /// - /// Clients that don't support cancellation or don't support control the button's - /// enablement state are allowed to ignore the setting. - /// - [Optional] - public bool Cancellable { get; set; } - - /// - /// Optional progress percentage to display (value 100 is considered 100%). - /// If not provided infinite progress is assumed and clients are allowed - /// to ignore the `percentage` value in subsequent in report notifications. - /// - /// The value should be steadily rising. Clients are free to ignore values - /// that are not following this rule. - /// - /// - /// TODO: Change this (breaking) - /// in the LSP spec - /// - [Optional] - public double? Percentage { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneTextDocumentPositionParams.cs b/src/Protocol/Models/WorkDoneTextDocumentPositionParams.cs deleted file mode 100644 index 7cdc016b5..000000000 --- a/src/Protocol/Models/WorkDoneTextDocumentPositionParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public abstract class WorkDoneTextDocumentPositionParams : TextDocumentPositionParams, IWorkDoneProgressParams - { - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/WorkDoneTextDocumentRegistrationOptions.cs b/src/Protocol/Models/WorkDoneTextDocumentRegistrationOptions.cs deleted file mode 100644 index 21048d42c..000000000 --- a/src/Protocol/Models/WorkDoneTextDocumentRegistrationOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class WorkDoneTextDocumentRegistrationOptions : TextDocumentRegistrationOptions, IWorkDoneProgressOptions - { - /// - [Optional] - public bool WorkDoneProgress { get; set; } - } -} diff --git a/src/Protocol/Models/WorkspaceFolder.cs b/src/Protocol/Models/WorkspaceFolder.cs deleted file mode 100644 index 2be48420c..000000000 --- a/src/Protocol/Models/WorkspaceFolder.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Diagnostics; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class WorkspaceFolder : IEquatable - { - /// - /// The associated URI for this workspace folder. - /// - public DocumentUri Uri { get; set; } = null!; - - /// - /// The name of the workspace folder. Defaults to the uri's basename. - /// - public string Name { get; set; } = null!; - - public bool Equals(WorkspaceFolder? other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return Equals(Uri, other.Uri) && Name == other.Name; - } - - public override bool Equals(object? obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((WorkspaceFolder) obj); - } - - public override int GetHashCode() - { - unchecked - { - return ( ( Uri is not null ? Uri.GetHashCode() : 0 ) * 397 ) ^ ( Name != null ? Name.GetHashCode() : 0 ); - } - } - - public static bool operator ==(WorkspaceFolder left, WorkspaceFolder right) => Equals(left, right); - - public static bool operator !=(WorkspaceFolder left, WorkspaceFolder right) => !Equals(left, right); - - private string DebuggerDisplay => $"{Name} ({Uri})"; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/WorkspaceFolderParams.cs b/src/Protocol/Models/WorkspaceFolderParams.cs deleted file mode 100644 index 7b9807cf2..000000000 --- a/src/Protocol/Models/WorkspaceFolderParams.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.JsonRpc; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [Method(WorkspaceNames.WorkspaceFolders, Direction.ServerToClient)] - public class WorkspaceFolderParams : IRequest?> - { - public static WorkspaceFolderParams Instance = new WorkspaceFolderParams(); - } -} diff --git a/src/Protocol/Models/WorkspaceFolderRegistrationOptions.cs b/src/Protocol/Models/WorkspaceFolderRegistrationOptions.cs deleted file mode 100644 index a576e12da..000000000 --- a/src/Protocol/Models/WorkspaceFolderRegistrationOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class WorkspaceFolderRegistrationOptions : IWorkspaceFolderOptions - { - public bool Supported { get; set; } - public BooleanString ChangeNotifications { get; set; } - } -} diff --git a/src/Protocol/Models/WorkspaceFoldersChangeEvent.cs b/src/Protocol/Models/WorkspaceFoldersChangeEvent.cs deleted file mode 100644 index f67c5144d..000000000 --- a/src/Protocol/Models/WorkspaceFoldersChangeEvent.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The workspace folder change event. - /// - public class WorkspaceFoldersChangeEvent - { - /// - /// The array of added workspace folders - /// - public Container Added { get; set; } = new Container(); - - /// - /// The array of the removed workspace folders - /// - public Container Removed { get; set; } = new Container(); - } -} diff --git a/src/Protocol/Models/WorkspaceSymbolParams.cs b/src/Protocol/Models/WorkspaceSymbolParams.cs deleted file mode 100644 index 6c1369be2..000000000 --- a/src/Protocol/Models/WorkspaceSymbolParams.cs +++ /dev/null @@ -1,25 +0,0 @@ -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// The parameters of a Workspace Symbol Request. - /// - [Method(WorkspaceNames.WorkspaceSymbol, Direction.ClientToServer)] - public class WorkspaceSymbolParams : IPartialItemsRequest?, SymbolInformation>, IWorkDoneProgressParams - { - /// - /// A non-empty query string - /// - public string Query { get; set; } = null!; - - /// - [Optional] - public ProgressToken? PartialResultToken { get; set; } - - /// - [Optional] - public ProgressToken? WorkDoneToken { get; set; } - } -} diff --git a/src/Protocol/Models/WorkspaceSymbolRegistrationOptions.cs b/src/Protocol/Models/WorkspaceSymbolRegistrationOptions.cs deleted file mode 100644 index 2f11af574..000000000 --- a/src/Protocol/Models/WorkspaceSymbolRegistrationOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public class WorkspaceSymbolRegistrationOptions : WorkDoneProgressOptions, IRegistrationOptions - { - public class StaticOptions : WorkDoneProgressOptions { } - - class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public WorkspaceSymbolRegistrationOptionsConverter() : base(nameof(ServerCapabilities.WorkspaceSymbolProvider)) - { - } - public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) => new StaticOptions { WorkDoneProgress = source.WorkDoneProgress }; - } - } -} diff --git a/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs b/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs index 0a8ea56c9..ae154c936 100644 --- a/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs +++ b/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs @@ -8,8 +8,8 @@ using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { diff --git a/src/Protocol/Progress/ProgressManager.cs b/src/Protocol/Progress/ProgressManager.cs index 3377e19a8..16b7c5edd 100644 --- a/src/Protocol/Progress/ProgressManager.cs +++ b/src/Protocol/Progress/ProgressManager.cs @@ -8,10 +8,10 @@ using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using ISerializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.ISerializer; namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { + [BuiltIn] internal class ProgressManager : IProgressManager { private readonly IResponseRouter _router; diff --git a/src/Protocol/Progress/ProgressObserver.cs b/src/Protocol/Progress/ProgressObserver.cs index 2299e08ca..95d6e069e 100644 --- a/src/Protocol/Progress/ProgressObserver.cs +++ b/src/Protocol/Progress/ProgressObserver.cs @@ -6,7 +6,6 @@ using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using ISerializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.ISerializer; namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { diff --git a/src/Protocol/Progress/RequestProgressObservable.cs b/src/Protocol/Progress/RequestProgressObservable.cs index 3b7df4e10..8ba1ef002 100644 --- a/src/Protocol/Progress/RequestProgressObservable.cs +++ b/src/Protocol/Progress/RequestProgressObservable.cs @@ -7,8 +7,8 @@ using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { diff --git a/src/Protocol/Protocol.csproj b/src/Protocol/Protocol.csproj index e9734fe2f..6a21a818a 100644 --- a/src/Protocol/Protocol.csproj +++ b/src/Protocol/Protocol.csproj @@ -15,13 +15,6 @@ --> - - true - $(BaseIntermediateOutputPath)\GeneratedFiles - - - - @@ -58,7 +51,6 @@ - diff --git a/src/JsonRpc/RegistrationNameAttribute.cs b/src/Protocol/RegistrationNameAttribute.cs similarity index 96% rename from src/JsonRpc/RegistrationNameAttribute.cs rename to src/Protocol/RegistrationNameAttribute.cs index 81addadb3..078afbcb7 100644 --- a/src/JsonRpc/RegistrationNameAttribute.cs +++ b/src/Protocol/RegistrationNameAttribute.cs @@ -4,7 +4,7 @@ using System.Reflection; using MediatR; -namespace OmniSharp.Extensions.JsonRpc +namespace OmniSharp.Extensions.LanguageServer.Protocol { public class RegistrationNameAttribute : Attribute { diff --git a/src/Protocol/RegistrationOptionsConverterAttribute.cs b/src/Protocol/RegistrationOptionsConverterAttribute.cs new file mode 100644 index 000000000..3197cfa5a --- /dev/null +++ b/src/Protocol/RegistrationOptionsConverterAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + /// + /// Defines a converter that is used for converting from dynamic to static + /// + [AttributeUsage(AttributeTargets.Class)] + public class RegistrationOptionsConverterAttribute : Attribute + { + public Type ConverterType { get; } + + public RegistrationOptionsConverterAttribute(Type converterType) + { + ConverterType = converterType; + } + } +} diff --git a/src/Protocol/RegistrationOptionsFactoryAdapter.cs b/src/Protocol/RegistrationOptionsFactoryAdapter.cs new file mode 100644 index 000000000..e864f7733 --- /dev/null +++ b/src/Protocol/RegistrationOptionsFactoryAdapter.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static class RegistrationAdapter + where TCapability : ICapability + { + public static RegistrationOptionsDelegate Adapt(RegistrationOptionsDelegate? registrationOptionsFactory) + where TRegistrationOptions : class, new() => registrationOptionsFactory ?? ( (_, _) => new TRegistrationOptions() ); + + public static RegistrationOptionsDelegate Adapt(RegistrationOptionsDelegate? registrationOptionsFactory) + where TRegistrationOptions : class, new() => (_, cc) => registrationOptionsFactory?.Invoke(cc) ?? new TRegistrationOptions(); + + public static RegistrationOptionsDelegate Adapt(TRegistrationOptions? registrationOptions) + where TRegistrationOptions : class, new() => (_, _) => registrationOptions ?? new TRegistrationOptions(); + } + + public static class RegistrationAdapter + { + public static RegistrationOptionsDelegate Adapt(RegistrationOptionsDelegate? registrationOptionsFactory) + where TRegistrationOptions : class, new() => registrationOptionsFactory ?? ( _ => new TRegistrationOptions() ); + + public static RegistrationOptionsDelegate Adapt(TRegistrationOptions? registrationOptions) + where TRegistrationOptions : class, new() => _ => registrationOptions ?? new TRegistrationOptions(); + } + + public static class PartialAdapter + { + public static Action, CancellationToken> Adapt(Action, CancellationToken> handler) + => handler; + + public static Action, CancellationToken> Adapt(Action> handler) + => (a, o, _) => handler(a, o); + + public static Action>, CancellationToken> Adapt( + Action>, CancellationToken> handler + ) + => handler; + + public static Action>, CancellationToken> Adapt(Action>> handler) + => (a, o, _) => handler(a, o); + } + + + public static class PartialAdapter + where TCapability : ICapability + { + public static Action>, TCapability, CancellationToken> Adapt( + Action>, TCapability, CancellationToken> handler + ) + => handler; + + public static Action>, TCapability, CancellationToken> Adapt( + Action>, TCapability> handler + ) + => (a, o, c, _) => handler(a, o, c); + + public static Action>, TCapability, CancellationToken> Adapt( + Action>, CancellationToken> handler + ) + => (a, o, _, t) => handler(a, o, t); + + public static Action>, TCapability, CancellationToken> Adapt(Action>> handler) + => (a, o, _, _) => handler(a, o); + + public static Action, TCapability, CancellationToken> Adapt( + Action, TCapability, CancellationToken> handler + ) + => handler; + + public static Action, TCapability, CancellationToken> Adapt(Action, TCapability> handler) + => (a, o, c, _) => handler(a, o, c); + + public static Action, TCapability, CancellationToken> Adapt(Action> handler) + => (a, o, _, _) => handler(a, o); + + public static Action, TCapability, CancellationToken> Adapt(Action, CancellationToken> handler) + => (a, o, _, t) => handler(a, o, t); + } + + public static class HandlerAdapter + { + public static Func> Adapt(Func> handler) => (a, _) => handler(a); + public static Func> Adapt(Func> handler) => handler; + + public static Func Adapt(Func handler) => (a, _) => handler(a); + public static Func Adapt(Func handler) => handler; + + public static Func Adapt(Action handler) => (a, _) => { + handler(a); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => (a, t) => { + handler(a, t); + return Task.CompletedTask; + }; + } + + public static class HandlerAdapter + where TCapability : ICapability + { + public static Func> Adapt( + Func> handler + ) => + handler; + + public static Func> Adapt(Func> handler) => + (a, e, c, _) => handler(a, e, c); + + public static Func> Adapt( + Func> handler + ) => + (a, e, _, t) => handler(a, e, t); + + public static Func> Adapt(Func> handler) => + (a, e, _, _) => handler(a, e); + + public static Func Adapt(Func handler) => + handler; + + public static Func Adapt(Func handler) + => (a, e, c, _) => handler(a, e, c); + + public static Func Adapt(Func handler) => + (a, e, _, _) => handler(a, e); + + public static Func Adapt(Func handler) => + (a, e, _, t) => handler(a, e, t); + + public static Func Adapt(Action handler) => + (a, e, c, t) => { + handler(a, e, c, t); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, e, c, _) => { + handler(a, e, c); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, e, _, _) => { + handler(a, e); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, e, _, t) => { + handler(a, e, t); + return Task.CompletedTask; + }; + } + + public static class HandlerAdapter + where TCapability : ICapability + { + public static Func> Adapt(Func> handler) => + handler; + + public static Func> Adapt(Func> handler) => + (a, c, _) => handler(a, c); + + public static Func> Adapt(Func> handler) => + (a, _, t) => handler(a, t); + + public static Func> Adapt(Func> handler) => + (a, _, _) => handler(a); + + public static Func Adapt(Func handler) => + handler; + + public static Func Adapt(Func handler) => + (a, c, _) => handler(a, c); + + public static Func Adapt(Func handler) => + (a, _, _) => handler(a); + + public static Func Adapt(Func handler) => + (a, _, t) => handler(a, t); + + public static Func Adapt(Action handler) => + (a, c, t) => { + handler(a, c, t); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, c, _) => { + handler(a, c); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, _, _) => { + handler(a); + return Task.CompletedTask; + }; + + public static Func Adapt(Action handler) => + (a, _, t) => { + handler(a, t); + return Task.CompletedTask; + }; + } +} diff --git a/src/Protocol/RegistrationOptionsKeyAttribute.cs b/src/Protocol/RegistrationOptionsKeyAttribute.cs new file mode 100644 index 000000000..2b9d1172a --- /dev/null +++ b/src/Protocol/RegistrationOptionsKeyAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + /// + /// Defines a converter that is used for converting from dynamic to static + /// + [AttributeUsage(AttributeTargets.Class)] + public class RegistrationOptionsKeyAttribute : Attribute + { + public RegistrationOptionsKeyAttribute(string serverCapabilitiesKey) + { + ServerCapabilitiesKey = serverCapabilitiesKey; + } + + public string ServerCapabilitiesKey { get; } + } +} diff --git a/src/Protocol/Server/Capabilities/WorkspaceServerCapabilities.cs b/src/Protocol/Server/Capabilities/WorkspaceServerCapabilities.cs index a8daae3cb..6e64dde42 100644 --- a/src/Protocol/Server/Capabilities/WorkspaceServerCapabilities.cs +++ b/src/Protocol/Server/Capabilities/WorkspaceServerCapabilities.cs @@ -2,7 +2,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities { - public class WorkspaceServerCapabilities + public class WorkspaceServerCapabilities : CapabilitiesBase { /// /// The server supports workspace folder. diff --git a/src/Protocol/Server/ISetTraceHandler.cs b/src/Protocol/Server/ISetTraceHandler.cs deleted file mode 100644 index ea87b47ea..000000000 --- a/src/Protocol/Server/ISetTraceHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Server -{ - [Parallel] - [Method(GeneralNames.SetTrace, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IClientLanguageClient), typeof(ILanguageClient))] - public interface ISetTraceHandler : IJsonRpcNotificationHandler - { - } - - public abstract class SetTraceHandler : ISetTraceHandler - { - public abstract Task Handle(SetTraceParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Server/WorkDone/LanguageServerWorkDoneManager.cs b/src/Protocol/Server/WorkDone/LanguageServerWorkDoneManager.cs index 4c7b8619f..6475743e8 100644 --- a/src/Protocol/Server/WorkDone/LanguageServerWorkDoneManager.cs +++ b/src/Protocol/Server/WorkDone/LanguageServerWorkDoneManager.cs @@ -11,6 +11,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone { + [BuiltIn] internal class LanguageServerWorkDoneManager : IServerWorkDoneManager { private readonly IResponseRouter _router; diff --git a/src/Protocol/Shared/ILspHandlerDescriptor.cs b/src/Protocol/Shared/ILspHandlerDescriptor.cs index a302f142c..83fe71154 100644 --- a/src/Protocol/Shared/ILspHandlerDescriptor.cs +++ b/src/Protocol/Shared/ILspHandlerDescriptor.cs @@ -9,7 +9,6 @@ public interface ILspHandlerDescriptor : IHandlerDescriptor bool HasRegistration { get; } Type? RegistrationType { get; } object? RegistrationOptions { get; } - bool AllowsDynamicRegistration { get; } bool HasCapability { get; } Type? CapabilityType { get; } diff --git a/src/Protocol/Shared/ISupportedCapabilities.cs b/src/Protocol/Shared/ISupportedCapabilities.cs index 07de50653..11856cf12 100644 --- a/src/Protocol/Shared/ISupportedCapabilities.cs +++ b/src/Protocol/Shared/ISupportedCapabilities.cs @@ -8,8 +8,10 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Shared public interface ISupportedCapabilities { bool AllowsDynamicRegistration(Type capabilityType); - void SetCapability(ILspHandlerDescriptor descriptor, IJsonRpcHandler handler); + object? GetRegistrationOptions(ILspHandlerTypeDescriptor handlerTypeDescriptor, IJsonRpcHandler handler); + object? GetRegistrationOptions(ILspHandlerDescriptor handlerTypeDescriptor, IJsonRpcHandler handler); void Add(IEnumerable supports); void Add(ICapability capability); + void Initialize(ClientCapabilities clientCapabilities); } } diff --git a/src/Protocol/Shared/LspHandlerDescriptor.cs b/src/Protocol/Shared/LspHandlerDescriptor.cs index 56c9e6717..4df85ded6 100644 --- a/src/Protocol/Shared/LspHandlerDescriptor.cs +++ b/src/Protocol/Shared/LspHandlerDescriptor.cs @@ -13,10 +13,11 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Shared [DebuggerDisplay("{Key}:{Method}")] internal class LspHandlerDescriptor : ILspHandlerDescriptor, IDisposable, IEquatable { + public int Index { get; } private readonly Action _disposeAction; - private readonly Func _allowsDynamicRegistration; public LspHandlerDescriptor( + int index, string method, string key, IJsonRpcHandler handler, @@ -24,19 +25,20 @@ public LspHandlerDescriptor( Type? @params, Type? registrationType, object? registrationOptions, - Func allowsDynamicRegistration, Type? capabilityType, RequestProcessType? requestProcessType, Action disposeAction, ILspHandlerTypeDescriptor? typeDescriptor ) : this( - method, key, handler, handlerType, @params, registrationType, registrationOptions, allowsDynamicRegistration, capabilityType, requestProcessType, disposeAction, + index, + method, key, handler, handlerType, @params, registrationType, registrationOptions, capabilityType, requestProcessType, disposeAction, typeDescriptor, null ) { } public LspHandlerDescriptor( + int index, string method, string key, IJsonRpcHandler handler, @@ -44,7 +46,6 @@ public LspHandlerDescriptor( Type? @params, Type? registrationType, object? registrationOptions, - Func allowsDynamicRegistration, Type? capabilityType, RequestProcessType? requestProcessType, Action disposeAction, @@ -62,7 +63,6 @@ public LspHandlerDescriptor( Params = @params; RegistrationType = registrationType; RegistrationOptions = registrationOptions; - _allowsDynamicRegistration = allowsDynamicRegistration; CapabilityType = capabilityType; Response = typeDescriptor?.ResponseType ?? @@ -87,16 +87,27 @@ public LspHandlerDescriptor( IsRequest = !IsNotification; RequestProcessType = requestProcessType; TypeDescriptor = typeDescriptor; + Index = index; + IsBuiltIn = handler.GetType().GetCustomAttributes().Any(); + } + + public LspHandlerDescriptor( + LspHandlerDescriptor descriptor, + string key, + object? registrationOptions + ) : this(descriptor.Index, descriptor.Method, key, descriptor.Handler, descriptor.HandlerType, descriptor.Params, descriptor.RegistrationType, registrationOptions, descriptor.CapabilityType, descriptor.RequestProcessType, descriptor._disposeAction, descriptor.TypeDescriptor, descriptor.Id) + { } public Type ImplementationType { get; } public Type HandlerType { get; } + public bool IsBuiltIn { get; set; } + public Guid Id { get; } public bool HasRegistration => RegistrationType != null; public Type? RegistrationType { get; } public object? RegistrationOptions { get; } - public bool AllowsDynamicRegistration => _allowsDynamicRegistration(); public bool HasCapability => CapabilityType != null; public Type? CapabilityType { get; } @@ -123,14 +134,14 @@ public LspHandlerDescriptor( public bool Equals(LspHandlerDescriptor? other) => other is not null && - EqualityComparer.Default.Equals(HandlerType, other.HandlerType) && +// EqualityComparer.Default.Equals(HandlerType, other.HandlerType) && Method == other.Method && Key == other.Key; public override int GetHashCode() { var hashCode = -45133801; - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(HandlerType); +// hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(HandlerType); hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Method); hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Key); return hashCode; @@ -140,5 +151,12 @@ public override int GetHashCode() EqualityComparer.Default.Equals(descriptor1, descriptor2); public static bool operator !=(LspHandlerDescriptor descriptor1, LspHandlerDescriptor descriptor2) => !( descriptor1 == descriptor2 ); + + internal class AllowAllEqualityComparer : IEqualityComparer + { + public bool Equals(LspHandlerDescriptor x, LspHandlerDescriptor y) => x.Id == y.Id; + + public int GetHashCode(LspHandlerDescriptor obj) => obj.Id.GetHashCode(); + } } } diff --git a/src/Protocol/Shared/LspHandlerTypeDescriptor.cs b/src/Protocol/Shared/LspHandlerTypeDescriptor.cs index c46721321..a3a2000d5 100644 --- a/src/Protocol/Shared/LspHandlerTypeDescriptor.cs +++ b/src/Protocol/Shared/LspHandlerTypeDescriptor.cs @@ -27,11 +27,13 @@ public LspHandlerTypeDescriptor(Type handlerType) : base(handlerType) HasPartialItems = PartialItemsType != null; HasPartialItem = PartialItemType != null; - RegistrationType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType); + RegistrationType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<>), handlerType) + ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<,>), handlerType, 0); HasRegistration = RegistrationType != null && RegistrationType != typeof(object); if (!HasRegistration) RegistrationType = null; - CapabilityType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType); + CapabilityType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability<>), handlerType) + ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration<,>), handlerType, 1); HasCapability = CapabilityType != null; if (!HasCapability) CapabilityType = null; diff --git a/src/Protocol/Window/ILogMessageHandler.cs b/src/Protocol/Window/ILogMessageHandler.cs deleted file mode 100644 index 71cc15f42..000000000 --- a/src/Protocol/Window/ILogMessageHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.LogMessage, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] - public interface ILogMessageHandler : IJsonRpcNotificationHandler - { - } - - public abstract class LogMessageHandler : ILogMessageHandler - { - public abstract Task Handle(LogMessageParams request, CancellationToken cancellationToken); - } - - public static partial class LogMessageExtensions - { - public static void Log(this ILanguageServer mediator, LogMessageParams @params) => mediator.LogMessage(@params); - - public static void LogError(this ILanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Error, Message = message }); - - public static void Log(this ILanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Log, Message = message }); - - public static void LogWarning(this ILanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Warning, Message = message }); - - public static void LogInfo(this ILanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Info, Message = message }); - - public static void Log(this IWindowLanguageServer mediator, LogMessageParams @params) => mediator.LogMessage(@params); - - public static void LogError(this IWindowLanguageServer mediator, string message) => - mediator.LogMessage(new LogMessageParams { Type = MessageType.Error, Message = message }); - - public static void Log(this IWindowLanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Log, Message = message }); - - public static void LogWarning(this IWindowLanguageServer mediator, string message) => - mediator.LogMessage(new LogMessageParams { Type = MessageType.Warning, Message = message }); - - public static void LogInfo(this IWindowLanguageServer mediator, string message) => mediator.LogMessage(new LogMessageParams { Type = MessageType.Info, Message = message }); - } -} diff --git a/src/Protocol/Window/IShowDocumentRequestHandler.cs b/src/Protocol/Window/IShowDocumentRequestHandler.cs deleted file mode 100644 index 2e955453f..000000000 --- a/src/Protocol/Window/IShowDocumentRequestHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.ShowDocument, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] - public interface IShowDocumentRequestHandler : IJsonRpcRequestHandler - { - } - - public abstract class ShowDocumentRequestHandler : IShowDocumentRequestHandler - { - public abstract Task Handle(ShowDocumentParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Window/IShowMessageHandler.cs b/src/Protocol/Window/IShowMessageHandler.cs deleted file mode 100644 index 9afe6de58..000000000 --- a/src/Protocol/Window/IShowMessageHandler.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.ShowMessage, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] - public interface IShowMessageHandler : IJsonRpcNotificationHandler - { - } - - public abstract class ShowMessageHandler : IShowMessageHandler - { - public abstract Task Handle(ShowMessageParams request, CancellationToken cancellationToken); - } - - public static partial class ShowMessageExtensions - { - public static void Show(this ILanguageServer mediator, ShowMessageParams @params) => mediator.ShowMessage(@params); - - public static void ShowError(this ILanguageServer mediator, string message) => mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Error, Message = message }); - - public static void Show(this ILanguageServer mediator, string message) => mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Log, Message = message }); - - public static void ShowWarning(this ILanguageServer mediator, string message) => - mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Warning, Message = message }); - - public static void ShowInfo(this ILanguageServer mediator, string message) => mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Info, Message = message }); - - public static void Show(this IWindowLanguageServer mediator, ShowMessageParams @params) => mediator.ShowMessage(@params); - - public static void ShowError(this IWindowLanguageServer mediator, string message) => - mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Error, Message = message }); - - public static void Show(this IWindowLanguageServer mediator, string message) => mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Log, Message = message }); - - public static void ShowWarning(this IWindowLanguageServer mediator, string message) => - mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Warning, Message = message }); - - public static void ShowInfo(this IWindowLanguageServer mediator, string message) => - mediator.ShowMessage(new ShowMessageParams { Type = MessageType.Info, Message = message }); - } -} diff --git a/src/Protocol/Window/IShowMessageRequestHandler.cs b/src/Protocol/Window/IShowMessageRequestHandler.cs deleted file mode 100644 index f001e38fa..000000000 --- a/src/Protocol/Window/IShowMessageRequestHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.ShowMessageRequest, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] - public interface IShowMessageRequestHandler : IJsonRpcRequestHandler - { - } - - public abstract class ShowMessageRequestHandler : IShowMessageRequestHandler - { - public abstract Task Handle(ShowMessageRequestParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Window/IWorkDoneProgressCancelHandler.cs b/src/Protocol/Window/IWorkDoneProgressCancelHandler.cs deleted file mode 100644 index c1ccb6893..000000000 --- a/src/Protocol/Window/IWorkDoneProgressCancelHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.WorkDoneProgressCancel, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageClient), typeof(ILanguageClient))] - public interface IWorkDoneProgressCancelHandler : IJsonRpcNotificationHandler - { - } - - public abstract class WorkDoneProgressCancelHandler : IWorkDoneProgressCancelHandler - { - public abstract Task Handle(WorkDoneProgressCancelParams request, CancellationToken cancellationToken); - } - - public static partial class WorkDoneProgressCancelExtensions - { - public static void SendWorkDoneProgressCancel(this IWindowLanguageClient mediator, IWorkDoneProgressParams @params) => - mediator.SendNotification( - WindowNames.WorkDoneProgressCancel, new WorkDoneProgressCancelParams { - Token = @params.WorkDoneToken - } - ); - - public static void SendWorkDoneProgressCancel(this IWindowLanguageClient mediator, ProgressToken token) => - mediator.SendNotification( - WindowNames.WorkDoneProgressCancel, new WorkDoneProgressCancelParams { - Token = token - } - ); - } -} diff --git a/src/Protocol/Window/IWorkDoneProgressCreateHandler.cs b/src/Protocol/Window/IWorkDoneProgressCreateHandler.cs deleted file mode 100644 index 72cd7b048..000000000 --- a/src/Protocol/Window/IWorkDoneProgressCreateHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Window -{ - [Parallel] - [Method(WindowNames.WorkDoneProgressCreate, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))] - public interface IWorkDoneProgressCreateHandler : IJsonRpcRequestHandler - { - } - - public abstract class WorkDoneProgressCreateHandler : IWorkDoneProgressCreateHandler - { - public abstract Task Handle(WorkDoneProgressCreateParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Workspace/IApplyEditHandler.cs b/src/Protocol/Workspace/IApplyEditHandler.cs deleted file mode 100644 index 969dd4922..000000000 --- a/src/Protocol/Workspace/IApplyEditHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.ApplyEdit, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] - public interface IApplyWorkspaceEditHandler : IJsonRpcRequestHandler - { - } - - public abstract class ApplyWorkspaceEditHandler : IApplyWorkspaceEditHandler - { - public abstract Task Handle(ApplyWorkspaceEditParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Workspace/IConfigurationHandler.cs b/src/Protocol/Workspace/IConfigurationHandler.cs deleted file mode 100644 index c7017f0eb..000000000 --- a/src/Protocol/Workspace/IConfigurationHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.Configuration, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] - public interface IConfigurationHandler : IJsonRpcRequestHandler> - { - } - - public abstract class ConfigurationHandler : IConfigurationHandler - { - public abstract Task> Handle(ConfigurationParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Workspace/IDidChangeConfigurationHandler.cs b/src/Protocol/Workspace/IDidChangeConfigurationHandler.cs deleted file mode 100644 index 789d699e8..000000000 --- a/src/Protocol/Workspace/IDidChangeConfigurationHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.DidChangeConfiguration, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] - public interface IDidChangeConfigurationHandler : IJsonRpcNotificationHandler, - IRegistration, // TODO: Remove this in the future - ICapability - { - } - - public abstract class DidChangeConfigurationHandler : IDidChangeConfigurationHandler - { - public abstract Task Handle(DidChangeConfigurationParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DidChangeConfigurationCapability capability) => Capability = capability; - protected DidChangeConfigurationCapability Capability { get; private set; } = null!; - public object GetRegistrationOptions() => new object(); - } -} diff --git a/src/Protocol/Workspace/IDidChangeWatchedFilesHandler.cs b/src/Protocol/Workspace/IDidChangeWatchedFilesHandler.cs deleted file mode 100644 index 189404061..000000000 --- a/src/Protocol/Workspace/IDidChangeWatchedFilesHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.DidChangeWatchedFiles, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] - public interface IDidChangeWatchedFilesHandler : IJsonRpcNotificationHandler, IRegistration, - ICapability - { - } - - public abstract class DidChangeWatchedFilesHandler : IDidChangeWatchedFilesHandler - { - private readonly DidChangeWatchedFilesRegistrationOptions _options; - public DidChangeWatchedFilesHandler(DidChangeWatchedFilesRegistrationOptions registrationOptions) => _options = registrationOptions; - - public DidChangeWatchedFilesRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(DidChangeWatchedFilesParams request, CancellationToken cancellationToken); - public virtual void SetCapability(DidChangeWatchedFilesCapability capability) => Capability = capability; - protected DidChangeWatchedFilesCapability Capability { get; private set; } = null!; - } -} diff --git a/src/Protocol/Workspace/IDidChangeWorkspaceFoldersHandler.cs b/src/Protocol/Workspace/IDidChangeWorkspaceFoldersHandler.cs deleted file mode 100644 index 60b2d7812..000000000 --- a/src/Protocol/Workspace/IDidChangeWorkspaceFoldersHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.DidChangeWorkspaceFolders, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] - public interface IDidChangeWorkspaceFoldersHandler : IJsonRpcNotificationHandler, - IRegistration // TODO: Remove this in the future - { - } - - public abstract class DidChangeWorkspaceFoldersHandler : IDidChangeWorkspaceFoldersHandler - { - private readonly object _registrationOptions; - public DidChangeWorkspaceFoldersHandler(object registrationOptions) => _registrationOptions = registrationOptions; - public object GetRegistrationOptions() => _registrationOptions; - - public abstract Task Handle(DidChangeWorkspaceFoldersParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Workspace/IExecuteCommandHandler.cs b/src/Protocol/Workspace/IExecuteCommandHandler.cs deleted file mode 100644 index eea5af81f..000000000 --- a/src/Protocol/Workspace/IExecuteCommandHandler.cs +++ /dev/null @@ -1,409 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json.Linq; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Serial] - [Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] - public interface IExecuteCommandHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { - } - - public abstract class ExecuteCommandHandler : IExecuteCommandHandler - { - private readonly ExecuteCommandRegistrationOptions _options; - - public ExecuteCommandHandler(ExecuteCommandRegistrationOptions registrationOptions) => _options = registrationOptions; - - public ExecuteCommandRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken); - public virtual void SetCapability(ExecuteCommandCapability capability) => Capability = capability; - protected ExecuteCommandCapability Capability { get; private set; } = null!; - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, cancellationToken); - } - - public abstract Task Handle(T arg1, CancellationToken cancellationToken); - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - T2 arg2 = default; - if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, arg2!, cancellationToken); - } - - public abstract Task Handle(T arg1, T2 arg2, CancellationToken cancellationToken); - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - T2 arg2 = default; - if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); - T3 arg3 = default; - if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, arg2!, arg3!, cancellationToken); - } - - public abstract Task Handle(T arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken); - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - T2 arg2 = default; - if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); - T3 arg3 = default; - if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); - T4 arg4 = default; - if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, arg2!, arg3!, arg4!, cancellationToken); - } - - public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cancellationToken); - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - T2 arg2 = default; - if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); - T3 arg3 = default; - if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); - T4 arg4 = default; - if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); - T5 arg5 = default; - if (args.Count > 4) arg5 = args[4].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, arg2!, arg3!, arg4!, arg5!, cancellationToken); - } - - public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cancellationToken); - } - - public abstract class ExecuteCommandHandlerBase : ExecuteCommandHandler - { - private readonly ISerializer _serializer; - - public ExecuteCommandHandlerBase(string command, ISerializer serializer) : base(new ExecuteCommandRegistrationOptions { Commands = new Container(command) }) => - _serializer = serializer; - - public sealed override Task Handle(ExecuteCommandParams request, CancellationToken cancellationToken) - { - var args = request.Arguments ?? new JArray(); - T arg1 = default; - if (args.Count > 0) arg1 = args[0].ToObject(_serializer.JsonSerializer); - T2 arg2 = default; - if (args.Count > 1) arg2 = args[1].ToObject(_serializer.JsonSerializer); - T3 arg3 = default; - if (args.Count > 2) arg3 = args[2].ToObject(_serializer.JsonSerializer); - T4 arg4 = default; - if (args.Count > 3) arg4 = args[3].ToObject(_serializer.JsonSerializer); - T5 arg5 = default; - if (args.Count > 4) arg5 = args[4].ToObject(_serializer.JsonSerializer); - T6 arg6 = default; - if (args.Count > 5) arg6 = args[5].ToObject(_serializer.JsonSerializer); - return Handle(arg1!, arg2!, arg3!, arg4!, arg5!, arg6!, cancellationToken); - } - - public abstract Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, CancellationToken cancellationToken); - } - - public static partial class ExecuteCommandExtensions - { - public static Task ExecuteCommand(this IWorkspaceLanguageClient mediator, Command @params, CancellationToken cancellationToken = default) - => mediator.ExecuteCommand(new ExecuteCommandParams { Arguments = @params.Arguments, Command = @params.Name }, cancellationToken); - - public static Task ExecuteCommand(this ILanguageClient mediator, Command @params, CancellationToken cancellationToken = default) - => mediator.ExecuteCommand(new ExecuteCommandParams { Arguments = @params.Arguments, Command = @params.Name }, cancellationToken); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, capability, token) => handler(arg1, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, capability, token) => handler(arg1), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => - _handler = handler; - - public override async Task Handle(T arg1, CancellationToken cancellationToken) - { - await _handler(arg1, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, capability, token) => handler(arg1, arg2, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, capability, token) => handler(arg1, arg2), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => - _handler = handler; - - public override async Task Handle(T arg1, T2 arg2, CancellationToken cancellationToken) - { - await _handler(arg1, arg2, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, capability, token) => handler(arg1, arg2, arg3, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, capability, token) => handler(arg1, arg2, arg3), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => - _handler = handler; - - public override async Task Handle(T arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) - { - await _handler(arg1, arg2, arg3, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, capability, token) => handler(arg1, arg2, arg3, arg4, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, capability, token) => handler(arg1, arg2, arg3, arg4), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : base(command, serializer) => - _handler = handler; - - public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cancellationToken) - { - await _handler(arg1, arg2, arg3, arg4, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, arg5, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, string command, Func handler) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, arg5, capability, token) => handler(arg1, arg2, arg3, arg4, arg5), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : - base(command, serializer) => _handler = handler; - - public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cancellationToken) - { - await _handler(arg1, arg2, arg3, arg4, arg5, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => registry.AddHandler(_ => new Handler(command, handler, _.GetRequiredService())); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, arg5, arg6, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, arg6, token), - _.GetRequiredService() - ) - ); - - public static ILanguageServerRegistry OnExecuteCommand( - this ILanguageServerRegistry registry, string command, Func handler - ) => - registry.AddHandler( - _ => new Handler( - command, - (arg1, arg2, arg3, arg4, arg5, arg6, capability, token) => handler(arg1, arg2, arg3, arg4, arg5, arg6), - _.GetRequiredService() - ) - ); - - private class Handler : ExecuteCommandHandlerBase - { - private readonly Func _handler; - - public Handler(string command, Func handler, ISerializer serializer) : base( - command, serializer - ) => _handler = handler; - - public override async Task Handle(T arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, CancellationToken cancellationToken) - { - await _handler(arg1, arg2, arg3, arg4, arg5, arg6, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - } -} diff --git a/src/Protocol/Workspace/IWorkspaceFoldersHandler.cs b/src/Protocol/Workspace/IWorkspaceFoldersHandler.cs deleted file mode 100644 index eaeb543d6..000000000 --- a/src/Protocol/Workspace/IWorkspaceFoldersHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.WorkspaceFolders, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] - public interface IWorkspaceFoldersHandler : IJsonRpcRequestHandler?> - { - } - - public abstract class WorkspaceFoldersHandler : IWorkspaceFoldersHandler - { - public abstract Task?> Handle(WorkspaceFolderParams request, CancellationToken cancellationToken); - } -} diff --git a/src/Protocol/Workspace/IWorkspaceSymbolsHandler.cs b/src/Protocol/Workspace/IWorkspaceSymbolsHandler.cs deleted file mode 100644 index a1f991e52..000000000 --- a/src/Protocol/Workspace/IWorkspaceSymbolsHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Parallel] - [Method(WorkspaceNames.WorkspaceSymbol, Direction.ClientToServer)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] - public interface IWorkspaceSymbolsHandler : IJsonRpcRequestHandler?>, ICapability, - IRegistration - { - } - - public abstract class WorkspaceSymbolsHandler : IWorkspaceSymbolsHandler - { - protected WorkspaceSymbolCapability Capability { get; private set; } = null!;private readonly WorkspaceSymbolRegistrationOptions _options; - - public WorkspaceSymbolsHandler(WorkspaceSymbolRegistrationOptions registrationOptions) => _options = registrationOptions; - - public WorkspaceSymbolRegistrationOptions GetRegistrationOptions() => _options; - public abstract Task?> Handle(WorkspaceSymbolParams request, CancellationToken cancellationToken); - public virtual void SetCapability(WorkspaceSymbolCapability capability) => Capability = capability; - } -} diff --git a/src/Protocol/Workspace/Proposals/ICodeLensRefreshHandler.cs b/src/Protocol/Workspace/Proposals/ICodeLensRefreshHandler.cs deleted file mode 100644 index f7199482a..000000000 --- a/src/Protocol/Workspace/Proposals/ICodeLensRefreshHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals -{ - - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] - public interface ICodeLensRefreshHandler : IJsonRpcRequestHandler, ICapability { } - - [Obsolete(Constants.Proposal)] - public abstract class CodeLensRefreshHandlerBase : ICodeLensRefreshHandler - { - protected CodeLensCapability? Capability { get; private set; } - - public abstract Task Handle(CodeLensRefreshParams request, CancellationToken cancellationToken); - public void SetCapability(CodeLensCapability capability) => Capability = capability; - } -} diff --git a/src/Protocol/Workspace/Proposals/ISemanticTokensRefreshHandler.cs b/src/Protocol/Workspace/Proposals/ISemanticTokensRefreshHandler.cs deleted file mode 100644 index e45700a23..000000000 --- a/src/Protocol/Workspace/Proposals/ISemanticTokensRefreshHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Proposals -{ - [Obsolete(Constants.Proposal)] - [Parallel] - [Method(WorkspaceNames.SemanticTokensRefresh, Direction.ServerToClient)] - [GenerateHandlerMethods] - [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] - public interface ISemanticTokensRefreshHandler : IJsonRpcRequestHandler, ICapability { } - - [Obsolete(Constants.Proposal)] - public abstract class SemanticTokensRefreshHandlerBase : ISemanticTokensRefreshHandler - { - protected SemanticTokensCapability? Capability { get; private set; } - - public abstract Task Handle(SemanticTokensRefreshParams request, CancellationToken cancellationToken); - public void SetCapability(SemanticTokensCapability capability) => Capability = capability; - } -} diff --git a/src/Server/ClientCapabilityProvider.cs b/src/Server/ClientCapabilityProvider.cs index 62b0bb772..6a0efd002 100644 --- a/src/Server/ClientCapabilityProvider.cs +++ b/src/Server/ClientCapabilityProvider.cs @@ -24,9 +24,9 @@ public ClientCapabilityProvider(IHandlerCollection collection, bool supportsProg public bool HasStaticHandler(Supports capability) where T : ConnectedCapability?, IDynamicCapability? { - // Dynamic registration will cause us to double register things if we report our capabilities staticly. + // Dynamic registration will cause us to double register things if we report our capabilities statically. // However if the client does not tell us it's capabilities we should just assume that they do not support - // dynamic registraiton but we should report any capabilities statically + // dynamic registrations but we should report any capabilities statically if (capability.IsSupported && capability.Value != null && capability.Value.DynamicRegistration) return false; var handlerTypes = typeof(T).GetTypeInfo().ImplementedInterfaces diff --git a/src/Server/Configuration/DidChangeConfigurationProvider.cs b/src/Server/Configuration/DidChangeConfigurationProvider.cs index f3343b44e..10f56afa6 100644 --- a/src/Server/Configuration/DidChangeConfigurationProvider.cs +++ b/src/Server/Configuration/DidChangeConfigurationProvider.cs @@ -21,6 +21,7 @@ namespace OmniSharp.Extensions.LanguageServer.Server.Configuration { + [BuiltIn] internal class DidChangeConfigurationProvider : ConfigurationProvider, IDidChangeConfigurationHandler, IOnLanguageServerStarted, ILanguageServerConfiguration, IDisposable { private readonly HashSet _configurationItems = new HashSet(); diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 01dc7ab91..7778ab557 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -35,6 +35,7 @@ namespace OmniSharp.Extensions.LanguageServer.Server { + [BuiltIn] public partial class LanguageServer : JsonRpcServerBase, ILanguageServer, ILanguageProtocolInitializeHandler, ILanguageProtocolInitializedHandler, IAwaitableTermination { private readonly Connection _connection; @@ -43,7 +44,7 @@ public partial class LanguageServer : JsonRpcServerBase, ILanguageServer, ILangu private readonly ILspServerReceiver _serverReceiver; private readonly LspSerializer _serializer; private readonly TextDocumentIdentifiers _textDocumentIdentifiers; - private readonly IHandlerCollection _collection; + private readonly SharedHandlerCollection _collection; private readonly IEnumerable _initializeDelegates; private readonly IEnumerable _initializeHandlers; private readonly IEnumerable _initializedDelegates; @@ -266,21 +267,67 @@ async Task IRequestHandler(_serializer.JsonSerializer); + ConfigureServerLogging(request); - foreach (var group in _capabilityTypes) + ReadClientCapabilities(request, out var clientCapabilities, out var textDocumentCapabilities, out _, out var windowCapabilities); + + await LanguageProtocolEventingHelper.Run( + _initializeDelegates, + (handler, ct) => handler(this, ClientSettings, ct), + _initializeHandlers.Union(_collection.Select(z => z.Handler).OfType()), + (handler, ct) => handler.OnInitialize(this, ClientSettings, ct), + _concurrency, + token + ).ConfigureAwait(false); + + _disposable.Add( + LanguageServerHelpers.RegisterHandlers( + _initializeComplete.Select(z => System.Reactive.Unit.Default), + Client, + WorkDoneManager, + _supportedCapabilities, + _collection + ) + ); + + var result = ReadServerCapabilities( clientCapabilities, windowCapabilities, textDocumentCapabilities); + + await LanguageProtocolEventingHelper.Run( + _initializedDelegates, + (handler, ct) => handler(this, ClientSettings, result, ct), + _initializedHandlers.Union(_collection.Select(z => z.Handler).OfType()), + (handler, ct) => handler.OnInitialized(this, ClientSettings, result, ct), + _concurrency, + token + ).ConfigureAwait(false); + + + // TODO: + if (_clientVersion == ClientVersion.Lsp2) { - foreach (var capabilityType in group) - { - if (request.Capabilities.SelectToken(group.Key) is JObject capabilityData) - { - var capability = capabilityData.ToObject(capabilityType) as ICapability; - _supportedCapabilities.Add(capability!); - } - } + _serverReceiver.Initialized(); + _initializeComplete.OnNext(result); + _initializeComplete.OnCompleted(); + } + + return result; + } + + public Task Handle(InitializedParams @params, CancellationToken token) + { + if (_clientVersion == ClientVersion.Lsp3) + { + _serverReceiver.Initialized(); + _initializeComplete.OnNext(ServerSettings); + _initializeComplete.OnCompleted(); } - if (request.Trace == InitializeTrace.Verbose) + return Unit.Task; + } + + private void ConfigureServerLogging(InternalInitializeParams internalInitializeParams) + { + if (internalInitializeParams.Trace == InitializeTrace.Verbose) { var loggerSettings = Services.GetService(); @@ -297,6 +344,29 @@ async Task IRequestHandler(_serializer.JsonSerializer); + _supportedCapabilities.Initialize(clientCapabilities); + foreach (var group in _capabilityTypes) + { + foreach (var capabilityType in @group) + { + if (request.Capabilities.SelectToken(@group.Key) is JObject capabilityData) + { + var capability = capabilityData.ToObject(capabilityType) as ICapability; + _supportedCapabilities.Add(capability!); + } + } + } _clientVersion = clientCapabilities.GetClientVersion(); _serializer.SetClientCapabilities(clientCapabilities); @@ -317,40 +387,29 @@ async Task IRequestHandler System.Reactive.Unit.Default), - Client, - WorkDoneManager, - _supportedCapabilities, - _collection - ) - ); - - await LanguageProtocolEventingHelper.Run( - _initializeDelegates, - (handler, ct) => handler(this, ClientSettings, ct), - _initializeHandlers.Union(_collection.Select(z => z.Handler).OfType()), - (handler, ct) => handler.OnInitialize(this, ClientSettings, ct), - _concurrency, - token - ).ConfigureAwait(false); - - var ccp = new ClientCapabilityProvider(_collection, windowCapabilities.WorkDoneProgress.IsSupported); + return clientCapabilities; + } + private InitializeResult ReadServerCapabilities(ClientCapabilities clientCapabilities, WindowClientCapabilities windowCapabilities, TextDocumentClientCapabilities textDocumentCapabilities) + { var serverCapabilities = new ServerCapabilities(); var serverCapabilitiesObject = new JObject(); @@ -389,6 +448,7 @@ await LanguageProtocolEventingHelper.Run( _serializer.JsonSerializer.Populate(reader, serverCapabilities); } + var ccp = new ClientCapabilityProvider(_collection, windowCapabilities.WorkDoneProgress.IsSupported); serverCapabilities.TextDocumentSync = ccp.GetStaticOptions(textDocumentCapabilities.Synchronization) .Reduce(TextDocumentSyncOptions.Of)!; @@ -410,7 +470,10 @@ await LanguageProtocolEventingHelper.Run( var kinds = _collection .Select(x => x.Handler) .OfType() - .Select(x => ( (TextDocumentChangeRegistrationOptions?)x.GetRegistrationOptions() )?.SyncKind ?? TextDocumentSyncKind.None) + .Select( + x => ( (TextDocumentChangeRegistrationOptions?)x.GetRegistrationOptions(textDocumentCapabilities.Synchronization, clientCapabilities) )?.SyncKind + ?? TextDocumentSyncKind.None + ) .Where(x => x != TextDocumentSyncKind.None) .ToArray(); if (kinds.Any()) @@ -445,45 +508,9 @@ await LanguageProtocolEventingHelper.Run( Capabilities = serverCapabilities, ServerInfo = _serverInfo }; - - foreach (var item in _collection) - { - LspHandlerDescriptorHelpers.InitializeHandler(item, _supportedCapabilities, item.Handler); - } - - await LanguageProtocolEventingHelper.Run( - _initializedDelegates, - (handler, ct) => handler(this, ClientSettings, result, ct), - _initializedHandlers.Union(_collection.Select(z => z.Handler).OfType()), - (handler, ct) => handler.OnInitialized(this, ClientSettings, result, ct), - _concurrency, - token - ).ConfigureAwait(false); - - - // TODO: - if (_clientVersion == ClientVersion.Lsp2) - { - _serverReceiver.Initialized(); - _initializeComplete.OnNext(result); - _initializeComplete.OnCompleted(); - } - return result; } - public Task Handle(InitializedParams @params, CancellationToken token) - { - if (_clientVersion == ClientVersion.Lsp3) - { - _serverReceiver.Initialized(); - _initializeComplete.OnNext(ServerSettings); - _initializeComplete.OnCompleted(); - } - - return Unit.Task; - } - public IObservable Start => _initializeComplete.AsObservable(); public Task WasStarted => _initializeComplete.ToTask(); diff --git a/src/Server/LanguageServerHelpers.cs b/src/Server/LanguageServerHelpers.cs index da2e3e1fd..1c1b8f17e 100644 --- a/src/Server/LanguageServerHelpers.cs +++ b/src/Server/LanguageServerHelpers.cs @@ -51,10 +51,6 @@ internal static void InitHandlers(ILanguageServer client, CompositeDisposable re GetUniqueHandlers(result) .Select(handler => Observable.FromAsync(ct => handler.OnInitialize(client, client.ClientSettings, ct))) .Merge(), - GetAllDescriptors(result) - .Select(item => LspHandlerDescriptorHelpers.InitializeHandler(item, supportedCapabilities, item.Handler)) - .ToObservable() - .Select(z => Unit.Default), GetUniqueHandlers(result) .Select(handler => Observable.FromAsync(ct => handler.OnInitialized(client, client.ClientSettings, client.ServerSettings, ct))) .Merge(), @@ -128,11 +124,12 @@ IReadOnlyList descriptors return registrations.Distinct(new Registration.TextDocumentComparer()).ToArray(); } ) + .Where(z => z.Any()) .SelectMany( registrations => Observable.FromAsync(ct => client.RegisterCapability(new RegistrationParams { Registrations = registrations.ToArray() }, ct)), (a, b) => a ) - .Aggregate((z, b) => z) + .Aggregate(Array.Empty(), (z, _) => z) .Subscribe( registrations => { disposable.Add( diff --git a/src/Server/LanguageServerWorkspaceFolderManager.cs b/src/Server/LanguageServerWorkspaceFolderManager.cs index 4ec207494..78f22e471 100644 --- a/src/Server/LanguageServerWorkspaceFolderManager.cs +++ b/src/Server/LanguageServerWorkspaceFolderManager.cs @@ -14,6 +14,7 @@ namespace OmniSharp.Extensions.LanguageServer.Server { + [BuiltIn] internal class LanguageServerWorkspaceFolderManager : ILanguageServerWorkspaceFolderManager, IDidChangeWorkspaceFoldersHandler, IOnLanguageServerStarted, IDisposable { private readonly IWorkspaceLanguageServer _server; diff --git a/src/Server/Pipelines/SemanticTokensDeltaPipeline.cs b/src/Server/Pipelines/SemanticTokensDeltaPipeline.cs index a096b89dd..a20278bb5 100644 --- a/src/Server/Pipelines/SemanticTokensDeltaPipeline.cs +++ b/src/Server/Pipelines/SemanticTokensDeltaPipeline.cs @@ -29,14 +29,14 @@ public async Task Handle(TRequest request, CancellationToken cancella var response = await next().ConfigureAwait(false); if (GetResponse(semanticTokensDeltaParams, response, out var result)) { - if (result.Value.IsFull && string.IsNullOrEmpty(result.Value.Full!.ResultId)) + if (result.IsFull && string.IsNullOrEmpty(result.Full!.ResultId)) { - result.Value.Full.ResultId = semanticTokensDeltaParams.PreviousResultId; + result.Full.ResultId = semanticTokensDeltaParams.PreviousResultId; } - if (result.Value.IsDelta && string.IsNullOrEmpty(result.Value.Delta!.ResultId)) + if (result.IsDelta && string.IsNullOrEmpty(result.Delta!.ResultId)) { - result.Value.Delta.ResultId = semanticTokensDeltaParams.PreviousResultId; + result.Delta.ResultId = semanticTokensDeltaParams.PreviousResultId; } } return response; diff --git a/src/Shared/LspHandlerDescriptorHelpers.cs b/src/Shared/LspHandlerDescriptorHelpers.cs index 201eaaa53..3dbd9f864 100644 --- a/src/Shared/LspHandlerDescriptorHelpers.cs +++ b/src/Shared/LspHandlerDescriptorHelpers.cs @@ -10,12 +10,6 @@ namespace OmniSharp.Extensions.LanguageServer.Shared { internal static class LspHandlerDescriptorHelpers { - public static IJsonRpcHandler InitializeHandler(ILspHandlerDescriptor descriptor, ISupportedCapabilities supportedCapabilities, IJsonRpcHandler handler) - { - supportedCapabilities.SetCapability(descriptor, handler); - return handler; - } - public static IEnumerable GetSupportedCapabilities(object capabilities) => capabilities .GetType() diff --git a/src/Shared/SharedHandlerCollection.cs b/src/Shared/SharedHandlerCollection.cs index 9974882eb..f76dfa73b 100644 --- a/src/Shared/SharedHandlerCollection.cs +++ b/src/Shared/SharedHandlerCollection.cs @@ -6,38 +6,44 @@ using System.Reactive.Disposables; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using DryIoc; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; namespace OmniSharp.Extensions.LanguageServer.Shared { internal class SharedHandlerCollection : IHandlerCollection { - private static readonly MethodInfo GetRegistrationMethod = typeof(SharedHandlerCollection) - .GetTypeInfo() - .GetMethod(nameof(GetRegistration), BindingFlags.NonPublic | BindingFlags.Static)!; - private readonly ISupportedCapabilities _supportedCapabilities; private readonly TextDocumentIdentifiers _textDocumentIdentifiers; - private ImmutableHashSet _descriptors = ImmutableHashSet.Empty; + + private ImmutableHashSet + _descriptors = ImmutableHashSet.Empty; + private readonly IResolverContext _resolverContext; private readonly ILspHandlerTypeDescriptorProvider _handlerTypeDescriptorProvider; + private bool _initialized; + private int _index; public SharedHandlerCollection( ISupportedCapabilities supportedCapabilities, TextDocumentIdentifiers textDocumentIdentifiers, IResolverContext resolverContext, - ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider) + ILspHandlerTypeDescriptorProvider handlerTypeDescriptorProvider + ) { _supportedCapabilities = supportedCapabilities; _textDocumentIdentifiers = textDocumentIdentifiers; _resolverContext = resolverContext; _handlerTypeDescriptorProvider = handlerTypeDescriptorProvider; + _index = 0; } public IEnumerator GetEnumerator() => _descriptors.GetEnumerator(); @@ -52,21 +58,23 @@ public SharedHandlerCollection( IDisposable IHandlersManager.Add(JsonRpcHandlerFactory handlerFactory, JsonRpcHandlerOptions? options) => Add(handlerFactory(_resolverContext), options); - IDisposable IHandlersManager.Add(string method, JsonRpcHandlerFactory handlerFactory, JsonRpcHandlerOptions? options) => Add(method, handlerFactory(_resolverContext), options); + IDisposable IHandlersManager.Add(string method, JsonRpcHandlerFactory handlerFactory, JsonRpcHandlerOptions? options) => + Add(method, handlerFactory(_resolverContext), options); - IDisposable IHandlersManager.Add(Type handlerType, JsonRpcHandlerOptions? options) => Add((_resolverContext.Resolve(handlerType) as IJsonRpcHandler)!, options); + IDisposable IHandlersManager.Add(Type handlerType, JsonRpcHandlerOptions? options) => Add(( _resolverContext.Resolve(handlerType) as IJsonRpcHandler )!, options); - IDisposable IHandlersManager.Add(string method, Type handlerType, JsonRpcHandlerOptions? options) => Add(method, (_resolverContext.Resolve(handlerType) as IJsonRpcHandler)!, options); + IDisposable IHandlersManager.Add(string method, Type handlerType, JsonRpcHandlerOptions? options) => + Add(method, ( _resolverContext.Resolve(handlerType) as IJsonRpcHandler )!, options); IDisposable IHandlersManager.AddLink(string fromMethod, string toMethod) { - var source = _descriptors.FirstOrDefault(z => z.Method == fromMethod); - if (source is null) + if (_descriptors.FirstOrDefault(z => z.Method == fromMethod) is not { } source) { if (_descriptors.Any(z => z.Method == toMethod)) { throw new ArgumentException( - $"Could not find descriptor for '{fromMethod}', but I did find one for '{toMethod}'. Did you mean to link '{toMethod}' to '{fromMethod}' instead?", fromMethod + $"Could not find descriptor for '{fromMethod}', but I did find one for '{toMethod}'. Did you mean to link '{toMethod}' to '{fromMethod}' instead?", + fromMethod ); } @@ -155,7 +163,7 @@ public LspHandlerDescriptorDisposable Add(params Type[] handlerTypes) var cd = new CompositeDisposable(); foreach (var handlerType in handlerTypes) { - var (innerDescriptors, innerCompositeDisposable) = AddHandler((ActivatorUtilities.CreateInstance(_resolverContext, handlerType) as IJsonRpcHandler)!, null); + var (innerDescriptors, innerCompositeDisposable) = AddHandler(( ActivatorUtilities.CreateInstance(_resolverContext, handlerType) as IJsonRpcHandler )!, null); descriptors.UnionWith(innerDescriptors); cd.Add(innerCompositeDisposable); } @@ -165,13 +173,13 @@ public LspHandlerDescriptorDisposable Add(params Type[] handlerTypes) public LspHandlerDescriptorDisposable Add(Type handlerType, JsonRpcHandlerOptions options) { - var (descriptors, cd) = AddHandler((_resolverContext.Resolve(handlerType) as IJsonRpcHandler)!, options); + var (descriptors, cd) = AddHandler(( _resolverContext.Resolve(handlerType) as IJsonRpcHandler )!, options); return new LspHandlerDescriptorDisposable(descriptors, cd); } public LspHandlerDescriptorDisposable Add(string method, Type handlerType, JsonRpcHandlerOptions options) { - var (descriptors, cd) = AddHandler(method, (_resolverContext.Resolve(handlerType) as IJsonRpcHandler)!, options); + var (descriptors, cd) = AddHandler(method, ( _resolverContext.Resolve(handlerType) as IJsonRpcHandler )!, options); return new LspHandlerDescriptorDisposable(descriptors, cd); } @@ -238,48 +246,11 @@ private LspHandlerDescriptor GetDescriptor( ) { Type? @params = null; - object? registrationOptions = null; if (@interface.GetTypeInfo().IsGenericType) { @params = @interface.GetTypeInfo().GetGenericArguments()[0]; } - if (registrationType != null) - { - registrationOptions = GetRegistrationMethod - .MakeGenericMethod(registrationType) - .Invoke(null, new object[] { handler }); - } - - var key = "default"; - if (handler is IRegistration handlerRegistration) - { - // Ensure we only do this check for the specific registartion type that was found - if (typeof(TextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(registrationType)) - { - key = handlerRegistration.GetRegistrationOptions()?.DocumentSelector ?? key; - } - - // In some scenarios, users will implement both the main handler and the resolve handler to the same class - // This allows us to get a key for those interfaces so we can register many resolve handlers - // and then route those resolve requests to the correct handler - if (handler.GetType().GetTypeInfo().ImplementedInterfaces.Any(x => typeof(ICanBeResolvedHandler).IsAssignableFrom(x))) - { - key = handlerRegistration.GetRegistrationOptions()?.DocumentSelector ?? key; - } - } - else if (handler is IRegistration commandRegistration) - { - key = string.Join("|", commandRegistration.GetRegistrationOptions()?.Commands ?? Array.Empty()); - } - - if (string.IsNullOrWhiteSpace(key)) key = "default"; - - if (handler is ICanBeIdentifiedHandler identifiedHandler && identifiedHandler.Id != Guid.Empty) - { - key += ":" + identifiedHandler.Id.ToString("N"); - } - var requestProcessType = options?.RequestProcessType ?? typeDescriptor?.RequestProcessType ?? @@ -288,15 +259,25 @@ private LspHandlerDescriptor GetDescriptor( .OfType() .FirstOrDefault()?.Type; + string key = "default"; + if (!_initialized && + ( typeDescriptor?.RegistrationType is not null + || typeDescriptor?.CapabilityType is not null + || registrationType is not null + || capabilityType is not null )) + { + key = Guid.NewGuid().ToString(); + } + var descriptor = new LspHandlerDescriptor( + Interlocked.Increment(ref _index), method, key, handler, @interface, @params, registrationType, - registrationOptions, - registrationType == null ? (Func) ( () => false ) : () => capabilityType != null && _supportedCapabilities.AllowsDynamicRegistration(capabilityType), + null, capabilityType, requestProcessType, () => { @@ -312,16 +293,75 @@ private LspHandlerDescriptor GetDescriptor( id ); + // TODO: Come back and fix this... + if (descriptor.RegistrationType is not null && _initialized) + { + var (key1, registrationOptions) = InferKey(descriptor, descriptor.Handler); + descriptor = new LspHandlerDescriptor(descriptor, key1, registrationOptions); + } + return descriptor; } + private (string key, object? registrationOptions) InferKey(ILspHandlerDescriptor typeDescriptor, IJsonRpcHandler handler) + { + var key = "default"; + var registrationOptions = _supportedCapabilities.GetRegistrationOptions(typeDescriptor, handler); + + if (registrationOptions is ITextDocumentRegistrationOptions textDocumentRegistrationOptions) + { + // Ensure we only do this check for the specific registration type that was found + if (typeof(ITextDocumentRegistrationOptions).GetTypeInfo().IsAssignableFrom(typeDescriptor.RegistrationType)) + { + key = textDocumentRegistrationOptions.DocumentSelector ?? key; + } + + // In some scenarios, users will implement both the main handler and the resolve handler to the same class + // This allows us to get a key for those interfaces so we can register many resolve handlers + // and then route those resolve requests to the correct handler + if (handler.GetType().GetTypeInfo().ImplementedInterfaces.Any(x => typeof(ICanBeResolvedHandler).IsAssignableFrom(x))) + { + key = textDocumentRegistrationOptions.DocumentSelector ?? key; + } + } + else if (registrationOptions is ExecuteCommandRegistrationOptions commandRegistrationOptions) + { + key = string.Join("|", commandRegistrationOptions.Commands); + } + + if (string.IsNullOrWhiteSpace(key)) key = "default"; + + if (handler is ICanBeIdentifiedHandler identifiedHandler && identifiedHandler.Id != Guid.Empty) + { + key += ":" + identifiedHandler.Id.ToString("N"); + } + + return ( key, registrationOptions ); + } + public bool ContainsHandler(Type type) => ContainsHandler(type.GetTypeInfo()); public bool ContainsHandler(TypeInfo typeInfo) => - _descriptors.Any(z => z.HandlerType.GetTypeInfo().IsAssignableFrom(typeInfo) || z.ImplementationType.GetTypeInfo().IsAssignableFrom(typeInfo)); + _descriptors.Any( + z => z.HandlerType.GetTypeInfo().IsAssignableFrom(typeInfo) + || z.ImplementationType.GetTypeInfo().IsAssignableFrom(typeInfo) + || MethodAttribute.AllFrom(typeInfo).Any(x => x.Method == z.Method) + ); + + internal void Initialize() + { + _initialized = true; + var descriptors = ImmutableHashSet.Empty.ToBuilder(); + var orderedList = _descriptors + .OrderBy(z => z.IsBuiltIn) + .ToArray(); + foreach (var descriptor in orderedList) + { + var (key, options) = InferKey(descriptor, descriptor.Handler); + descriptors.Add(new LspHandlerDescriptor(descriptor, key, options)); + } - private static object? GetRegistration(IRegistration registration) - where T : class?, new() => - registration.GetRegistrationOptions() ?? new T(); + Interlocked.Exchange(ref _descriptors, descriptors.ToImmutable().WithComparer(EqualityComparer.Default)); + } } } diff --git a/src/Shared/SupportedCapabilities.cs b/src/Shared/SupportedCapabilities.cs index adf287914..755947b12 100644 --- a/src/Shared/SupportedCapabilities.cs +++ b/src/Shared/SupportedCapabilities.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol; @@ -8,14 +9,41 @@ namespace OmniSharp.Extensions.LanguageServer.Shared { - internal class SupportedCapabilities : ISupportedCapabilities, ICapabilitiesProvider + internal class SupportedCapabilities : SupportedCapabilitiesBase, ISupportedCapabilities, ICapabilitiesProvider { - private static readonly MethodInfo SetCapabilityInnerMethod = typeof(SupportedCapabilities) - .GetTypeInfo() - .GetMethod(nameof(SetCapabilityInner), BindingFlags.NonPublic | BindingFlags.Static)!; + public T GetCapability() where T : ICapability? + { + if (TryGetCapability(typeof(T), out var value) && value is T c) return c; + return default!; + } + + public ICapability? GetCapability(Type type) + { + if (TryGetCapability(type, out var value) && value is ICapability c) return c; + return default; + } + + public bool AllowsDynamicRegistration(Type capabilityType) + { + if (capabilityType != null && TryGetCapability(capabilityType, out var capability)) + { + if (capability is IDynamicCapability dc) + return dc.DynamicRegistration; + } + + return false; + } + } + internal class SupportedCapabilitiesBase + { private readonly IDictionary _supports = new Dictionary(); + public void Initialize(ClientCapabilities clientCapabilities) + { + _clientCapabilities = clientCapabilities; + } + public void Add(IEnumerable supports) { foreach (var item in supports) @@ -29,47 +57,94 @@ public void Add(IEnumerable supports) public void Add(ICapability capability) { var valueType = capability.GetType(); - if (_supports.TryGetValue(valueType, out _)) + if (TryGetCapability(valueType, out _)) _supports.Remove(valueType); _supports.Add(valueType, capability); } - public T GetCapability() where T : ICapability? + protected virtual bool TryGetCapability(Type capabilityType, [NotNullWhen(true)] out object? capability) { - if (_supports.TryGetValue(typeof(T), out var value) && value is T c) return c; - return default!; + return _supports.TryGetValue(capabilityType, out capability); } - public ICapability? GetCapability(Type type) + public object? GetRegistrationOptions(ILspHandlerTypeDescriptor descriptor, IJsonRpcHandler handler) { - if (_supports.TryGetValue(type, out var value) && value is ICapability c) return c; - return default; + return GetRegistrationOptions(descriptor.RegistrationType, descriptor.CapabilityType, handler); } - public bool AllowsDynamicRegistration(Type capabilityType) + public object? GetRegistrationOptions(ILspHandlerDescriptor descriptor, IJsonRpcHandler handler) { - if (capabilityType != null && _supports.TryGetValue(capabilityType, out var capability)) - { - if (capability is IDynamicCapability dc) - return dc.DynamicRegistration; - } - - return false; + return GetRegistrationOptions(descriptor.RegistrationType, descriptor.CapabilityType, handler); } - public void SetCapability(ILspHandlerDescriptor descriptor, IJsonRpcHandler handler) + public object? GetRegistrationOptions(Type? registrationType, Type? capabilityType, IJsonRpcHandler handler) { - if (!descriptor.HasCapability) return; - if (descriptor.CapabilityType == null || !typeof(ICapability<>).MakeGenericType(descriptor.CapabilityType).IsInstanceOfType(handler)) return; + // this method will play dual purpose, it will ensure that set capability has been called + // even though that is not part of the method. + if (!( registrationType is not null)) + { + if (capabilityType is null || !TryGetCapability(capabilityType, out var capability)) return null; + + if (typeof(ICapability<>).MakeGenericType(capabilityType).IsInstanceOfType(handler)) + { + SetCapabilityInnerMethod + .MakeGenericMethod(capabilityType) + .Invoke(null, new[] { handler, capability }); + } + + return null; + } - if (_supports.TryGetValue(descriptor.CapabilityType, out var capability)) + if (capabilityType is {} + && typeof(IRegistration<,>).MakeGenericType(registrationType, capabilityType).IsInstanceOfType(handler)) { - SetCapabilityInnerMethod - .MakeGenericMethod(descriptor.CapabilityType) - .Invoke(null, new[] { handler, capability }); + if (TryGetCapability(capabilityType, out var capability)) + { + var result = SetRegistrationCapabilityInnerMethod + .MakeGenericMethod(registrationType, capabilityType) + .Invoke(null, new[] { handler, capability, _clientCapabilities }); + return result; + } } + else if (!typeof(IRegistration<>).MakeGenericType(registrationType).IsInstanceOfType(handler)) + { + var result = GetRegistrationOptionsInnerMethod + .MakeGenericMethod(registrationType) + .Invoke(null, new object[] { handler, _clientCapabilities }); + return result; + } + + return null; } + protected static readonly MethodInfo SetCapabilityInnerMethod = typeof(SupportedCapabilitiesBase) + .GetTypeInfo() + .GetMethod(nameof(SetCapabilityInner), BindingFlags.NonPublic | BindingFlags.Static)!; + private static void SetCapabilityInner(ICapability capability, T instance) => capability.SetCapability(instance); + + private static readonly MethodInfo SetRegistrationCapabilityInnerMethod = typeof(SupportedCapabilitiesBase) + .GetTypeInfo() + .GetMethod(nameof(SetRegistrationCapabilityInner), BindingFlags.NonPublic | BindingFlags.Static)!; + + private static object SetRegistrationCapabilityInner(IRegistration capability, TC instance, ClientCapabilities clientCapabilities) + where TR : class + where TC : ICapability + { + var registrationCapabilityInner = capability.GetRegistrationOptions(instance, clientCapabilities); + return registrationCapabilityInner; + } + + private static readonly MethodInfo GetRegistrationOptionsInnerMethod = typeof(SupportedCapabilitiesBase) + .GetTypeInfo() + .GetMethod(nameof(GetRegistrationOptionsInner), BindingFlags.NonPublic | BindingFlags.Static)!; + + private ClientCapabilities _clientCapabilities; + + private static object GetRegistrationOptionsInner(IRegistration capability, ClientCapabilities clientCapabilities) where TR : class + { + var registrationOptionsInner = capability.GetRegistrationOptions(clientCapabilities); + return registrationOptionsInner; + } } } diff --git a/test/Client.Tests/ClientTests.cs b/test/Client.Tests/ClientTests.cs index 0875ae437..6a4200975 100644 --- a/test/Client.Tests/ClientTests.cs +++ b/test/Client.Tests/ClientTests.cs @@ -75,7 +75,7 @@ public async Task Hover_Success() } } )!; - }, new HoverRegistrationOptions() + }, (_, _) => new HoverRegistrationOptions() ); } ); @@ -162,7 +162,7 @@ public async Task Completions_Success() true ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); } ); @@ -264,7 +264,7 @@ public async Task SignatureHelp_Success() Assert.Equal(column, request.Position.Character); return Task.FromResult(expectedSignatureHelp)!; - }, new SignatureHelpRegistrationOptions() + }, (_, _) => new SignatureHelpRegistrationOptions() ); } ); @@ -343,7 +343,7 @@ public async Task Definition_Success() Assert.Equal(column, request.Position.Character); return Task.FromResult(expectedDefinitions); - }, new DefinitionRegistrationOptions() + }, (_, _) => new DefinitionRegistrationOptions() ); } ); @@ -415,7 +415,7 @@ public async Task DocumentHighlights_Success() Assert.Equal(column, request.Position.Character); return Task.FromResult(expectedHighlights)!; - }, new DocumentHighlightRegistrationOptions() + }, (_, _) => new DocumentHighlightRegistrationOptions() ); } ); @@ -492,7 +492,7 @@ public async Task DocumentSymbols_DocumentSymbol_Success() Assert.Equal(expectedDocumentUri, request.TextDocument.Uri); return Task.FromResult(expectedSymbols); - }, new DocumentSymbolRegistrationOptions() + }, (_, _) => new DocumentSymbolRegistrationOptions() ); } ); @@ -564,7 +564,7 @@ public async Task FoldingRanges_Success() Assert.NotNull(request.TextDocument); Assert.Equal(expectedDocumentUri, request.TextDocument.Uri); return Task.FromResult(expectedFoldingRanges)!; - }, new FoldingRangeRegistrationOptions() + }, (_, _) => new FoldingRangeRegistrationOptions() ); } ); diff --git a/test/Dap.Tests/EventingTests.cs b/test/Dap.Tests/EventingTests.cs index 27a32e7c0..986e37497 100644 --- a/test/Dap.Tests/EventingTests.cs +++ b/test/Dap.Tests/EventingTests.cs @@ -55,9 +55,9 @@ public async Task Initialize_Delegate_Is_Supported() public async Task Initialize_Interface_Is_Supported_On_Handlers() { var onDebugAdapterClientInitialize = - Substitute.For(new[] { typeof(IOnDebugAdapterClientInitialize), typeof(RunInTerminalHandler) }, Array.Empty()) as IOnDebugAdapterClientInitialize; + Substitute.For(new[] { typeof(IOnDebugAdapterClientInitialize), typeof(RunInTerminalHandlerBase) }, Array.Empty()) as IOnDebugAdapterClientInitialize; var onDebugAdapterServerInitialize = - Substitute.For(new[] { typeof(IOnDebugAdapterServerInitialize), typeof(CompletionsHandler) }, Array.Empty()) as + Substitute.For(new[] { typeof(IOnDebugAdapterServerInitialize), typeof(CompletionsHandlerBase) }, Array.Empty()) as IOnDebugAdapterServerInitialize; var (client, server) = await Initialize( // ReSharper disable once SuspiciousTypeConversion.Global @@ -102,9 +102,9 @@ public async Task Initialized_Delegate_Is_Supported() public async Task Initialized_Interface_Is_Supported_On_Handlers() { var onDebugAdapterClientInitialized = - Substitute.For(new[] { typeof(IOnDebugAdapterClientInitialized), typeof(RunInTerminalHandler) }, Array.Empty()) as IOnDebugAdapterClientInitialized; + Substitute.For(new[] { typeof(IOnDebugAdapterClientInitialized), typeof(RunInTerminalHandlerBase) }, Array.Empty()) as IOnDebugAdapterClientInitialized; var onDebugAdapterServerInitialized = - Substitute.For(new[] { typeof(IOnDebugAdapterServerInitialized), typeof(CompletionsHandler) }, Array.Empty()) as + Substitute.For(new[] { typeof(IOnDebugAdapterServerInitialized), typeof(CompletionsHandlerBase) }, Array.Empty()) as IOnDebugAdapterServerInitialized; var (client, server) = await Initialize( // ReSharper disable once SuspiciousTypeConversion.Global @@ -149,9 +149,9 @@ public async Task Started_Delegate_Is_Supported() public async Task Started_Interface_Is_Supported_On_Handlers() { var onDebugAdapterClientStarted = - Substitute.For(new[] { typeof(IOnDebugAdapterClientStarted), typeof(RunInTerminalHandler) }, Array.Empty()) as IOnDebugAdapterClientStarted; + Substitute.For(new[] { typeof(IOnDebugAdapterClientStarted), typeof(RunInTerminalHandlerBase) }, Array.Empty()) as IOnDebugAdapterClientStarted; var onDebugAdapterServerStarted = - Substitute.For(new[] { typeof(IOnDebugAdapterServerStarted), typeof(CompletionsHandler) }, Array.Empty()) as + Substitute.For(new[] { typeof(IOnDebugAdapterServerStarted), typeof(CompletionsHandlerBase) }, Array.Empty()) as IOnDebugAdapterServerStarted; var (client, server) = await Initialize( // ReSharper disable once SuspiciousTypeConversion.Global diff --git a/test/Dap.Tests/Integration/CustomRequestsTests.cs b/test/Dap.Tests/Integration/CustomRequestsTests.cs index ad8770534..184f5d7c0 100644 --- a/test/Dap.Tests/Integration/CustomRequestsTests.cs +++ b/test/Dap.Tests/Integration/CustomRequestsTests.cs @@ -44,7 +44,7 @@ await client.RequestAttach( [Fact] public async Task Should_Support_Custom_Attach_Request_Receiving_Regular_Request_Using_Base_Class() { - var fake = Substitute.For(); + var fake = Substitute.For(); var (client, _) = await Initialize(options => { }, options => { options.AddHandler(fake); }); await client.RequestAttach( @@ -108,7 +108,7 @@ await client.RequestLaunch( [Fact] public async Task Should_Support_Custom_Launch_Request_Receiving_Regular_Request_Using_Base_Class() { - var fake = Substitute.For(); + var fake = Substitute.For(); var (client, _) = await Initialize(options => { }, options => { options.AddHandler(fake); }); await client.RequestLaunch( diff --git a/test/Dap.Tests/Integration/RecursiveResolutionTests.cs b/test/Dap.Tests/Integration/RecursiveResolutionTests.cs index 3972207d0..9449dad99 100644 --- a/test/Dap.Tests/Integration/RecursiveResolutionTests.cs +++ b/test/Dap.Tests/Integration/RecursiveResolutionTests.cs @@ -185,7 +185,7 @@ public enum Side } [Method(nameof(ClassRequest))] - public class ClassRequest : IRequest + public class ClassRequest : IRequest { } @@ -204,7 +204,7 @@ public ClassHandler(T jsonRpcServer) } [Method(nameof(InterfaceRequest))] - public class InterfaceRequest : IRequest + public class InterfaceRequest : IRequest { } diff --git a/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs b/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs new file mode 100644 index 000000000..15e9195ec --- /dev/null +++ b/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc.Generators; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; +using TestingUtils; + +namespace Generation.Tests +{ + public class AutoImplementParamsGeneratorTests + { + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Auto_Magically_Implements_Properties() + { + var source = @" +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +#nullable enable +namespace Test +{ + [Method(""abcd"")] + public partial class DeclarationParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest { } +} +"; + var expected = @" +#nullable enable +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace Test +{ + public partial class DeclarationParams + { + [Optional] + public ProgressToken? WorkDoneToken + { + get; + set; + } + + [Optional] + public ProgressToken? PartialResultToken + { + get; + set; + } + } +} +#nullable restore"; + CacheKeyHasher.Cache = true; + await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + } + } +} diff --git a/test/Generation.Tests/FeatureFixture.cs b/test/Generation.Tests/FeatureFixture.cs new file mode 100644 index 000000000..c3dec6300 --- /dev/null +++ b/test/Generation.Tests/FeatureFixture.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Xunit.Sdk; + +namespace Generation.Tests +{ + internal static class FeatureFixture + { + public static Assembly Resources = typeof(FeatureFixture).GetTypeInfo().Assembly; + + public static string ReadSource(string featurePath) + { + var fileName = $"{Resources.GetName().Name}.Features.{featurePath}"; + + if (!Resources.GetManifestResourceNames().Contains(fileName)) + { + throw new XunitException($"Could find fixture for {fileName}"); + } + + using var streamReader = new StreamReader(Resources.GetManifestResourceStream(fileName)!); + return streamReader.ReadToEnd().Replace("\r\n", "\n").Replace("namespace OmniSharp.Extensions.LanguageServer.Protocol.Bogus", "namespace Test").TrimEnd(); + } + } +} diff --git a/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs b/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs index 51dded73d..9b824a5c9 100644 --- a/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs +++ b/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs @@ -6,6 +6,128 @@ namespace Generation.Tests { public class GeneratedRegistrationOptionsTests { + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Supports_Generating_Strongly_Typed_WorkDone_Registration_Options() + { + var source = @" +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +namespace Test +{ + [GenerateRegistrationOptions(nameof(ServerCapabilities.WorkspaceSymbolProvider), SupportsWorkDoneProgress = true)] + public partial class WorkspaceSymbolRegistrationOptions { } +} +"; + var expected = @" +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +#nullable enable +namespace Test +{ + [RegistrationOptionsConverterAttribute(typeof(WorkspaceSymbolRegistrationOptionsConverter))] + public partial class WorkspaceSymbolRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + + class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public WorkspaceSymbolRegistrationOptionsConverter(): base(nameof(ServerCapabilities.WorkspaceSymbolProvider)) + { + } + + public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) + { + return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; + } + } + + public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + } + } +} +#nullable restore"; + await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + } + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface() + { + var source = @" +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +namespace Test +{ + [GenerateRegistrationOptions(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class WorkspaceSymbolRegistrationOptions : IWorkDoneProgressOptions { } +} +"; + + var expected = @" +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +#nullable enable +namespace Test +{ + [RegistrationOptionsConverterAttribute(typeof(WorkspaceSymbolRegistrationOptionsConverter))] + public partial class WorkspaceSymbolRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + + class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public WorkspaceSymbolRegistrationOptionsConverter(): base(nameof(ServerCapabilities.WorkspaceSymbolProvider)) + { + } + + public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) + { + return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; + } + } + + public partial class StaticOptions : IWorkDoneProgressOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + } + } +} +#nullable restore"; + await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + } + [FactWithSkipOn(SkipOnPlatform.Windows)] public async Task Supports_Generating_Strongly_Typed_Registration_Options() { @@ -21,15 +143,17 @@ public async Task Supports_Generating_Strongly_Typed_Registration_Options() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; #nullable enable namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - [RegistrationOptions(nameof(ServerCapabilities.CodeActionProvider)), TextDocument, WorkDoneProgress] + [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeActionProvider), SupportsDocumentSelector = true, SupportsWorkDoneProgress = true] public partial class CodeActionRegistrationOptions { /// @@ -64,17 +188,18 @@ public partial class CodeActionRegistrationOptions using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; -using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; #nullable enable namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { [RegistrationOptionsConverterAttribute(typeof(CodeActionRegistrationOptionsConverter))] - public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions { public DocumentSelector? DocumentSelector { @@ -89,58 +214,56 @@ public bool WorkDoneProgress set; } - class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase + class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase { - public Converter(): base(nameof(ServerCapabilities.CodeActionProvider)) + public CodeActionRegistrationOptionsConverter(): base(nameof(ServerCapabilities.CodeActionProvider)) { } - public override StaticCodeActionRegistrationOptions Convert(CodeActionRegistrationOptions source) + public override StaticOptions Convert(CodeActionRegistrationOptions source) { - return new StaticCodeActionRegistrationOptions{CodeActionKinds = source.CodeActionKinds, ResolveProvider = source.ResolveProvider}; + return new StaticOptions{CodeActionKinds = source.CodeActionKinds, ResolveProvider = source.ResolveProvider, WorkDoneProgress = source.WorkDoneProgress}; } } - } - public partial class StaticCodeActionRegistrationOptions : IWorkDoneProgressOptions - { - /// - /// CodeActionKinds that this server may return. - /// - /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server - /// may list out every specific kind they provide. - /// - [Optional] - public Container? CodeActionKinds + public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions { - get; - set; - } + /// + /// CodeActionKinds that this server may return. + /// + /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + /// may list out every specific kind they provide. + /// + [Optional] + public Container? CodeActionKinds + { + get; + set; + } - = new Container(); - /// - /// The server provides support to resolve additional - /// information for a code action. - /// - /// @since 3.16.0 - /// - public bool ResolveProvider - { - get; - set; - } + = new Container(); + /// + /// The server provides support to resolve additional + /// information for a code action. + /// + /// @since 3.16.0 + /// + public bool ResolveProvider + { + get; + set; + } - [Optional] - public bool WorkDoneProgress - { - get; - set; + [Optional] + public bool WorkDoneProgress + { + get; + set; + } } } } -#nullable restore - -"; +#nullable restore"; await GenerationHelpers.AssertGeneratedAsExpected(source, expected); } @@ -159,6 +282,7 @@ public async Task Supports_Generating_Strongly_Typed_Registration_Options_With_C using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -167,9 +291,9 @@ public async Task Supports_Generating_Strongly_Typed_Registration_Options_With_C #nullable enable namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - [RegistrationOptions(nameof(ServerCapabilities.CodeActionProvider)), TextDocument, WorkDoneProgress] + [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeActionProvider)] [RegistrationOptionsConverter(typeof(CodeActionRegistrationOptionsConverter))] - public partial class CodeActionRegistrationOptions + public partial class CodeActionRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { /// /// CodeActionKinds that this server may return. @@ -222,6 +346,7 @@ public override StaticCodeActionRegistrationOptions Convert(CodeActionRegistrati using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -231,7 +356,7 @@ public override StaticCodeActionRegistrationOptions Convert(CodeActionRegistrati #nullable enable namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions { public DocumentSelector? DocumentSelector { @@ -245,47 +370,45 @@ public bool WorkDoneProgress get; set; } - } - public partial class StaticCodeActionRegistrationOptions : IWorkDoneProgressOptions - { - /// - /// CodeActionKinds that this server may return. - /// - /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server - /// may list out every specific kind they provide. - /// - [Optional] - public Container? CodeActionKinds + public partial class StaticOptions : IWorkDoneProgressOptions { - get; - set; - } + /// + /// CodeActionKinds that this server may return. + /// + /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + /// may list out every specific kind they provide. + /// + [Optional] + public Container? CodeActionKinds + { + get; + set; + } - = new Container(); - /// - /// The server provides support to resolve additional - /// information for a code action. - /// - /// @since 3.16.0 - /// - public bool ResolveProvider - { - get; - set; - } + = new Container(); + /// + /// The server provides support to resolve additional + /// information for a code action. + /// + /// @since 3.16.0 + /// + public bool ResolveProvider + { + get; + set; + } - [Optional] - public bool WorkDoneProgress - { - get; - set; + [Optional] + public bool WorkDoneProgress + { + get; + set; + } } } } -#nullable restore - -"; +#nullable restore"; await GenerationHelpers.AssertGeneratedAsExpected(source, expected); } } diff --git a/test/Generation.Tests/Generation.Tests.csproj b/test/Generation.Tests/Generation.Tests.csproj index 1cd111176..9da152b04 100644 --- a/test/Generation.Tests/Generation.Tests.csproj +++ b/test/Generation.Tests/Generation.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/test/Generation.Tests/JsonRpcGenerationTests.cs b/test/Generation.Tests/JsonRpcGenerationTests.cs index 44d036d16..adfb9e89e 100644 --- a/test/Generation.Tests/JsonRpcGenerationTests.cs +++ b/test/Generation.Tests/JsonRpcGenerationTests.cs @@ -1,7 +1,11 @@ +using System; using System.Threading.Tasks; +using FluentAssertions; using OmniSharp.Extensions.JsonRpc.Generators; +using OmniSharp.Extensions.JsonRpc.Generators.Cache; using TestingUtils; using Xunit; +using Xunit.Sdk; using static Generation.Tests.GenerationHelpers; namespace Generation.Tests @@ -20,6 +24,7 @@ public async Task Supports_Generating_Notifications_And_Infers_Direction_ExitHan using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -38,8 +43,11 @@ public interface IExitHandler : IJsonRpcNotificationHandler using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; using System; using System.Collections.Generic; using System.Threading; @@ -55,13 +63,43 @@ public static partial class ExitExtensions public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Func handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Action handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Func handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); - public static void SendExit(this ILanguageClient mediator, ExitParams @params) => mediator.SendNotification(@params); + public static void SendExit(this ILanguageClient mediator, ExitParams request) => mediator.SendNotification(request); } #nullable restore }"; await AssertGeneratedAsExpected(source, expected); } + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Should_Report_Diagnostic_If_Missing_Information() + { + var source = @" +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +namespace Test +{ + [Serial, Method(GeneralNames.Exit, Direction.ClientToServer), GenerateHandlerMethods, GenerateRequestMethods] + public interface IExitHandler : IJsonRpcNotificationHandler + { + } +}"; + + CacheKeyHasher.Cache = true; + Func a = () => AssertGeneratedAsExpected(source, ""); + a.Should().Throw().WithMessage("*Could not infer the request router(s)*"); + a.Should().Throw("cache").WithMessage("*Could not infer the request router(s)*"); + } + [FactWithSkipOn(SkipOnPlatform.Windows)] public async Task Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler() { @@ -79,11 +117,11 @@ namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test public interface ICapabilitiesHandler : IJsonRpcNotificationHandler { } }"; - var expected = @" -using MediatR; + var expected = @"using MediatR; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.DebugAdapter.Protocol; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Generation; @@ -102,7 +140,7 @@ public static partial class CapabilitiesExtensions public static IDebugAdapterClientRegistry OnCapabilities(this IDebugAdapterClientRegistry registry, Func handler) => registry.AddHandler(EventNames.Capabilities, NotificationHandler.For(handler)); public static IDebugAdapterClientRegistry OnCapabilities(this IDebugAdapterClientRegistry registry, Action handler) => registry.AddHandler(EventNames.Capabilities, NotificationHandler.For(handler)); public static IDebugAdapterClientRegistry OnCapabilities(this IDebugAdapterClientRegistry registry, Func handler) => registry.AddHandler(EventNames.Capabilities, NotificationHandler.For(handler)); - public static void SendCapabilities(this IDebugAdapterServer mediator, CapabilitiesEvent @params) => mediator.SendNotification(@params); + public static void SendCapabilities(this IDebugAdapterServer mediator, CapabilitiesEvent request) => mediator.SendNotification(request); } #nullable restore }"; @@ -122,6 +160,7 @@ public async Task Supports_Generating_Notifications_ExitHandler() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -140,12 +179,14 @@ public interface IExitHandler : IJsonRpcNotificationHandler using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Test; namespace Test { @@ -157,7 +198,7 @@ public static partial class ExitExtensions public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Func handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Action handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); public static ILanguageServerRegistry OnExit(this ILanguageServerRegistry registry, Func handler) => registry.AddHandler(GeneralNames.Exit, NotificationHandler.For(handler)); - public static void SendExit(this ILanguageClient mediator, ExitParams @params) => mediator.SendNotification(@params); + public static void SendExit(this ILanguageClient mediator, ExitParams request) => mediator.SendNotification(request); } #nullable restore }"; @@ -177,6 +218,7 @@ public async Task Supports_Generating_Notifications_And_Infers_Direction_DidChan using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -184,7 +226,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { [Serial, Method(TextDocumentNames.DidChange, Direction.ClientToServer), GenerateHandlerMethods, GenerateRequestMethods] public interface IDidChangeTextDocumentHandler : IJsonRpcNotificationHandler, - IRegistration, ICapability + IRegistration { } }"; @@ -196,8 +238,10 @@ public interface IDidChangeTextDocumentHandler : IJsonRpcNotificationHandler handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, TextDocumentChangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new TextDocumentChangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static void DidChangeTextDocument(this ILanguageClient mediator, DidChangeTextDocumentParams @params) => mediator.SendNotification(@params); + public static void DidChangeTextDocument(this ILanguageClient mediator, DidChangeTextDocumentParams request) => mediator.SendNotification(request); } #nullable restore } @@ -266,6 +304,7 @@ public async Task Supports_Generating_Notifications_And_Infers_Direction_Folding using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -274,7 +313,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Test [Parallel, Method(TextDocumentNames.FoldingRange, Direction.ClientToServer)] [GenerateHandlerMethods, GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] public interface IFoldingRangeHandler : IJsonRpcRequestHandler>, - IRegistration, ICapability + IRegistration { } }"; @@ -287,9 +326,11 @@ public interface IFoldingRangeHandler : IJsonRpcRequestHandler>> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.RequestRegistration, FoldingRangeRegistrationOptions>(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeRegistrationOptions, FoldingRangeCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.RequestRegistration, FoldingRangeRegistrationOptions>(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeRegistrationOptions, FoldingRangeCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions>(handler, registrationOptions, _.GetService(), values => new Container(values))); + return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeRegistrationOptions, FoldingRangeCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Action>> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions>(handler, registrationOptions, _.GetService(), values => new Container(values))); + return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); } - public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Action>, FoldingRangeCapability, CancellationToken> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeCapability, FoldingRangeRegistrationOptions>(handler, registrationOptions, _.GetService(), values => new Container(values))); + return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); } - public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, FoldingRangeRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, FoldingRangeCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new FoldingRangeRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeCapability, FoldingRangeRegistrationOptions>(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); } - public static IRequestProgressObservable, Container> RequestFoldingRange(this ITextDocumentLanguageClient mediator, FoldingRangeRequestParam @params, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(@params, value => new Container(value), cancellationToken); - public static IRequestProgressObservable, Container> RequestFoldingRange(this ILanguageClient mediator, FoldingRangeRequestParam @params, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(@params, value => new Container(value), cancellationToken); + public static IRequestProgressObservable, Container> RequestFoldingRange(this ITextDocumentLanguageClient mediator, FoldingRangeRequestParam request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); + public static IRequestProgressObservable, Container> RequestFoldingRange(this ILanguageClient mediator, FoldingRangeRequestParam request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); } #nullable restore } @@ -358,6 +393,7 @@ public async Task Supports_Generating_Requests_And_Infers_Direction() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; @@ -365,7 +401,7 @@ public async Task Supports_Generating_Requests_And_Infers_Direction() namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { [Parallel, Method(TextDocumentNames.Definition, Direction.ClientToServer), GenerateHandlerMethods, GenerateRequestMethods, Obsolete(""This is obsolete"")] - public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration, ICapability { } + public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration { } }"; var expected = @" @@ -376,9 +412,11 @@ public interface IDefinitionHandler : IJsonRpcRequestHandler> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.RequestRegistration(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.RequestRegistration(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static IRequestProgressObservable, LocationOrLocationLinks> RequestDefinition(this ILanguageClient mediator, DefinitionParams @params, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(@params, value => new LocationOrLocationLinks(value), cancellationToken); + public static IRequestProgressObservable, LocationOrLocationLinks> RequestDefinition(this ILanguageClient mediator, DefinitionParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationOrLocationLinks(value), cancellationToken); } #nullable restore }"; @@ -446,6 +478,7 @@ public async Task Supports_Generating_Requests() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; @@ -453,7 +486,7 @@ public async Task Supports_Generating_Requests() namespace Test { [Parallel, Method(TextDocumentNames.Definition, Direction.ClientToServer), GenerateHandlerMethods(typeof(ILanguageServerRegistry)), GenerateRequestMethods(typeof(ITextDocumentLanguageClient))] - public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration, ICapability { } + public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration { } }"; var expected = @" @@ -464,6 +497,7 @@ public interface IDefinitionHandler : IJsonRpcRequestHandler> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.RequestRegistration(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.RequestRegistration(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(handler, registrationOptions, _.GetService(), values => new LocationOrLocationLinks(values))); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, DefinitionRegistrationOptions? registrationOptions) + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) { - registrationOptions ??= new DefinitionRegistrationOptions(); - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(handler, registrationOptions)); + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); } - public static IRequestProgressObservable, LocationOrLocationLinks> RequestDefinition(this ITextDocumentLanguageClient mediator, DefinitionParams @params, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(@params, value => new LocationOrLocationLinks(value), cancellationToken); + public static IRequestProgressObservable, LocationOrLocationLinks> RequestDefinition(this ITextDocumentLanguageClient mediator, DefinitionParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationOrLocationLinks(value), cancellationToken); } #nullable restore }"; @@ -525,15 +554,20 @@ public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry public async Task Supports_Custom_Method_Names() { var source = @" -using System; -using System.Threading; -using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Test; namespace Test { @@ -547,12 +581,14 @@ public interface ILanguageProtocolInitializeHandler : IJsonRpcRequestHandler> handler) => registry.AddHandler(GeneralNames.Initialize, RequestHandler.For(handler)); public static ILanguageServerRegistry OnLanguageProtocolInitialize(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(GeneralNames.Initialize, RequestHandler.For(handler)); - public static Task RequestLanguageProtocolInitialize(this ITextDocumentLanguageClient mediator, InitializeParams @params, CancellationToken cancellationToken = default) => mediator.SendRequest(@params, cancellationToken); + public static Task RequestLanguageProtocolInitialize(this ITextDocumentLanguageClient mediator, InitializeParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); } #nullable restore }"; @@ -581,16 +617,17 @@ public async Task Supports_Allow_Derived_Requests() using System.Collections.Generic; using MediatR; -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { - [Parallel, Method(RequestNames.Attach, Direction.ClientToServer)] - [GenerateHandlerMethods(AllowDerivedRequests = true), GenerateRequestMethods] - public interface IAttachHandler : IJsonRpcRequestHandler { } + public class AttachResponse { } + [Method(""attach"", Direction.ClientToServer)] + [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] + public class AttachRequestArguments: IRequest { } }"; - var expected = @" -using MediatR; + var expected = @"using MediatR; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Bogus; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; using OmniSharp.Extensions.JsonRpc; @@ -600,19 +637,44 @@ public interface IAttachHandler : IJsonRpcRequestHandler : IJsonRpcRequestHandler where T : AttachRequestArguments + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AbstractHandlers.Request, IAttachRequestHandler where T : AttachRequestArguments + { + } + + public partial interface IAttachRequestHandler : IAttachRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AttachRequestHandlerBase, IAttachRequestHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { #nullable enable [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class AttachExtensions + public static partial class AttachRequestExtensions { - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) - where T : AttachRequestArguments => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) - where T : AttachRequestArguments => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static Task RequestAttach(this IDebugAdapterClient mediator, AttachRequestArguments @params, CancellationToken cancellationToken = default) => mediator.SendRequest(@params, cancellationToken); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static Task RequestAttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); } #nullable restore }"; @@ -631,18 +693,17 @@ public async Task Supports_Allows_Nullable_Responses() using System.Collections.Generic; using MediatR; -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Requests +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { -#nullable enable - [Parallel, Method(RequestNames.Attach, Direction.ClientToServer)] - [GenerateHandlerMethods(AllowDerivedRequests = true), GenerateRequestMethods] - public interface IAttachHandler : IJsonRpcRequestHandler { } -#nullable restore + public class AttachResponse { } + [Method(""attach"", Direction.ClientToServer)] + [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] + public class AttachRequestArguments: IRequest { } }"; - var expected = @" -using MediatR; + var expected = @"using MediatR; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Bogus; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; using OmniSharp.Extensions.JsonRpc; @@ -652,19 +713,44 @@ public interface IAttachHandler : IJsonRpcRequestHandler : IJsonRpcRequestHandler where T : AttachRequestArguments + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AbstractHandlers.Request, IAttachRequestHandler where T : AttachRequestArguments + { + } + + public partial interface IAttachRequestHandler : IAttachRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AttachRequestHandlerBase, IAttachRequestHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { #nullable enable [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class AttachExtensions + public static partial class AttachRequestExtensions { - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) - where T : AttachRequestArguments => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) - where T : AttachRequestArguments => registry.AddHandler(RequestNames.Attach, RequestHandler.For(handler)); - public static Task RequestAttach(this IDebugAdapterClient mediator, AttachRequestArguments @params, CancellationToken cancellationToken = default) => mediator.SendRequest(@params, cancellationToken); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static Task RequestAttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); } #nullable restore }"; @@ -687,17 +773,13 @@ namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { public class AttachResponse { } [Method(""attach"", Direction.ClientToServer)] + [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] public class AttachRequestArguments: IRequest { } - - [Parallel, Method(""attach"", Direction.ClientToServer)] - [GenerateHandlerMethods(AllowDerivedRequests = true), GenerateRequestMethods] - public interface IAttachHandler : IJsonRpcRequestHandler where T : AttachRequestArguments { } - public interface IAttachHandler : IAttachHandler { } }"; - var expected = @" -using MediatR; + var expected = @"using MediatR; using Microsoft.Extensions.DependencyInjection; using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Bogus; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; using OmniSharp.Extensions.JsonRpc; @@ -707,19 +789,140 @@ public interface IAttachHandler : IAttachHandler { } using System.Threading; using System.Threading.Tasks; +#nullable enable +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus +{ + [Method(""attach"", Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IAttachRequestHandler : IJsonRpcRequestHandler where T : AttachRequestArguments + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AbstractHandlers.Request, IAttachRequestHandler where T : AttachRequestArguments + { + } + + public partial interface IAttachRequestHandler : IAttachRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class AttachRequestHandlerBase : AttachRequestHandlerBase, IAttachRequestHandler + { + } +} +#nullable restore + namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus { #nullable enable [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class AttachExtensions + public static partial class AttachRequestExtensions { - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""attach"", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnAttach(this IDebugAdapterServerRegistry registry, Func> handler) + public static IDebugAdapterServerRegistry OnAttachRequest(this IDebugAdapterServerRegistry registry, Func> handler) where T : AttachRequestArguments => registry.AddHandler(""attach"", RequestHandler.For(handler)); - public static Task RequestAttach(this IDebugAdapterClient mediator, AttachRequestArguments @params, CancellationToken cancellationToken = default) => mediator.SendRequest(@params, cancellationToken); + public static Task RequestAttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +}"; + await AssertGeneratedAsExpected(source, expected); + } + + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Supports_Params_Type_As_Source() + { + var source = @" +using System; +using System.Threading; +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using System.Collections.Generic; +using MediatR; +using RenameRegistrationOptions = OmniSharp.Extensions.LanguageServer.Protocol.Models.RenameRegistrationOptions; +using RenameCapability = OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities.RenameCapability; +using ITextDocumentIdentifierParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentIdentifierParams; +using WorkspaceEdit = OmniSharp.Extensions.LanguageServer.Protocol.Models.WorkspaceEdit; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Bogus +{ + [Parallel] + [Method(TextDocumentNames.Rename, Direction.ClientToServer)] + [GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Bogus.Handlers""), GenerateHandlerMethods, GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(RenameRegistrationOptions))] + [Capability(typeof(RenameCapability))] + public partial class RenameParams : ITextDocumentIdentifierParams, IRequest + { + } +}"; + var expected = @" +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Bogus; +using OmniSharp.Extensions.LanguageServer.Protocol.Bogus.Handlers; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using RenameCapability = OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities.RenameCapability; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using ITextDocumentIdentifierParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentIdentifierParams; +using RenameRegistrationOptions = OmniSharp.Extensions.LanguageServer.Protocol.Models.RenameRegistrationOptions; +using WorkspaceEdit = OmniSharp.Extensions.LanguageServer.Protocol.Models.WorkspaceEdit; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Bogus.Handlers +{ + [Parallel, Method(TextDocumentNames.Rename, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IRenameHandler : IJsonRpcRequestHandler, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class RenameHandlerBase : AbstractHandlers.Request, IRenameHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Bogus.Handlers +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class RenameExtensions + { + public static ILanguageServerRegistry OnRename(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Rename, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnRename(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Rename, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnRename(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Rename, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static Task RequestRename(this ITextDocumentLanguageClient mediator, RenameParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task RequestRename(this ILanguageClient mediator, RenameParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); } #nullable restore }"; diff --git a/test/Generation.Tests/LspFeatureTests.cs b/test/Generation.Tests/LspFeatureTests.cs new file mode 100644 index 000000000..30851fb8d --- /dev/null +++ b/test/Generation.Tests/LspFeatureTests.cs @@ -0,0 +1,459 @@ +using System.Threading.Tasks; +using OmniSharp.Extensions.JsonRpc.Generators; +using TestingUtils; +using Xunit; + +namespace Generation.Tests +{ + public class LspFeatureTests + { +// [FactWithSkipOn(SkipOnPlatform.Windows, Skip = "for testing")] + [Fact] + public async Task Supports_Params_Type_As_Source() + { + var source = FeatureFixture.ReadSource("Workspace.WorkspaceSymbolsFeature.cs"); + var expected = @" +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace +{ + [Parallel, Method(WorkspaceNames.WorkspaceSymbol, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IWorkspaceSymbolsHandler : IJsonRpcRequestHandler?>, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class WorkspaceSymbolsHandlerBase : AbstractHandlers.Request?, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>, IWorkspaceSymbolsHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class WorkspaceSymbolsPartialHandlerBase : AbstractHandlers.PartialResults?, SymbolInformation, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>, IWorkspaceSymbolsHandler + { + protected WorkspaceSymbolsPartialHandlerBase(System.Guid id, IProgressManager progressManager): base(progressManager, Container.From) + { + } + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class WorkspaceSymbolsExtensions + { + public static ILanguageServerRegistry OnWorkspaceSymbols(this ILanguageServerRegistry registry, Func?>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, new LanguageProtocolDelegatingHandlers.Request?, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(HandlerAdapter.Adapt?>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnWorkspaceSymbols(this ILanguageServerRegistry registry, Func?>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, new LanguageProtocolDelegatingHandlers.Request?, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(HandlerAdapter.Adapt?>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnWorkspaceSymbols(this ILanguageServerRegistry registry, Func?>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, new LanguageProtocolDelegatingHandlers.Request?, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(HandlerAdapter.Adapt?>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveWorkspaceSymbols(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, _ => new LanguageProtocolDelegatingHandlers.PartialResults?, SymbolInformation, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveWorkspaceSymbols(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, _ => new LanguageProtocolDelegatingHandlers.PartialResults?, SymbolInformation, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveWorkspaceSymbols(this ILanguageServerRegistry registry, Action>, WorkspaceSymbolCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.WorkspaceSymbol, _ => new LanguageProtocolDelegatingHandlers.PartialResults?, SymbolInformation, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static IRequestProgressObservable, Container?> RequestWorkspaceSymbols(this ITextDocumentLanguageClient mediator, WorkspaceSymbolParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); + public static IRequestProgressObservable, Container?> RequestWorkspaceSymbols(this ILanguageClient mediator, WorkspaceSymbolParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); + } +#nullable restore +}"; + await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + } + + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Supports_Generating_Custom_Language_Extensions() + { + var source = @" +// ------------------------------------------------------------------------------ +// +// This code was generated a code generator. +// +// ------------------------------------------------------------------------------ + +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [Parallel, Method(""tests/run"", Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class UnitTest : IRequest + { + public string Name { get; set; } = null!; + } + + [Parallel, Method(""tests/discover"", Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class DiscoverUnitTestsParams : IPartialItemsRequest, UnitTest>, IWorkDoneProgressParams + { + public ProgressToken? PartialResultToken { get; set; } = null!; + public ProgressToken? WorkDoneToken { get; set; } = null!; + } + + [CapabilityKey(""workspace"", ""unitTests"")] + public partial class UnitTestCapability : DynamicCapability + { + public string Property { get; set; } = null!; + } + + [GenerateRegistrationOptions(""unitTestDiscovery"")] + public partial class UnitTestRegistrationOptions : IWorkDoneProgressOptions + { + [Optional] public bool SupportsDebugging { get; set; } + } +} +#nullable restore"; + + var expectedOptions = @"using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [RegistrationOptionsConverterAttribute(typeof(UnitTestRegistrationOptionsConverter))] + public partial class UnitTestRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + + class UnitTestRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public UnitTestRegistrationOptionsConverter(): base(""unitTestDiscovery"") + { + } + + public override StaticOptions Convert(UnitTestRegistrationOptions source) + { + return new StaticOptions{SupportsDebugging = source.SupportsDebugging, WorkDoneProgress = source.WorkDoneProgress}; + } + } + + public partial class StaticOptions : IWorkDoneProgressOptions + { + [Optional] + public bool SupportsDebugging + { + get; + set; + } + + [Optional] + public bool WorkDoneProgress + { + get; + set; + } + } + } +} +#nullable restore"; + var expectedStrongTypes = @" +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [Parallel, Method(""tests/run"", Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class UnitTest : IRequest + { + public string Name { get; set; } = null!; + } + + [Parallel, Method(""tests/discover"", Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class DiscoverUnitTestsParams : IPartialItemsRequest, UnitTest>, IWorkDoneProgressParams + { + public ProgressToken? PartialResultToken { get; set; } = null!; + public ProgressToken? WorkDoneToken { get; set; } = null!; + } + + [CapabilityKey(""workspace"", ""unitTests"")] + public partial class UnitTestCapability : DynamicCapability + { + public string Property { get; set; } = null!; + } + + [GenerateRegistrationOptions(""unitTestDiscovery"")] + public partial class UnitTestRegistrationOptions : IWorkDoneProgressOptions + { + [Optional] public bool SupportsDebugging { get; set; } + } +} +#nullable restore +"; + var expectedHandlers = @" +using Lsp.Tests.Integration.Fixtures; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [Parallel, Method(""tests/discover"", Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IDiscoverUnitTestsHandler : IJsonRpcRequestHandler>, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class DiscoverUnitTestsHandlerBase : AbstractHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>, IDiscoverUnitTestsHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class DiscoverUnitTestsPartialHandlerBase : AbstractHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>, IDiscoverUnitTestsHandler + { + protected DiscoverUnitTestsPartialHandlerBase(System.Guid id, IProgressManager progressManager): base(progressManager, Container.From) + { + } + } +} +#nullable restore + +namespace Lsp.Tests.Integration.Fixtures +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class DiscoverUnitTestsExtensions + { + public static ILanguageServerRegistry OnDiscoverUnitTests(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDiscoverUnitTests(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDiscoverUnitTests(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>, UnitTestCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static IRequestProgressObservable, Container> RequestDiscoverUnitTests(this ILanguageClient mediator, DiscoverUnitTestsParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); + } +#nullable restore +}"; + await GenerationHelpers.AssertGeneratedAsExpected(source, expectedOptions); + await GenerationHelpers.AssertGeneratedAsExpected(source, expectedStrongTypes); + await GenerationHelpers.AssertGeneratedAsExpected(source, expectedHandlers); + } + + [FactWithSkipOn(SkipOnPlatform.Windows)] + public async Task Supports_Generating_Void_Task_Return() + { + var source = @" +// ------------------------------------------------------------------------------ +// +// This code was generated a code generator. +// +// ------------------------------------------------------------------------------ + +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [ + GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Client"", Name = ""RegisterCapability""), + GenerateHandlerMethods(typeof(ILanguageClientRegistry), + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) + ] + public class RegistrationParams : IJsonRpcRequest + { + public RegistrationContainer Registrations { get; set; } = null!; + } + + /// + /// General parameters to to regsiter for a capability. + /// + [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] + [GenerateContainer] + public partial class Registration + { + } +} +#nullable restore"; + + var expectedHandlers = @" +using Lsp.Tests.Integration.Fixtures; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ + [Parallel, Method(ClientNames.RegisterCapability, Direction.ServerToClient)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IRegisterCapabilityHandler : IJsonRpcRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class RegisterCapabilityHandlerBase : AbstractHandlers.Request, IRegisterCapabilityHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class RegisterCapabilityExtensions + { + public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(handler)); + public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(handler)); + } +#nullable restore +}"; + await GenerationHelpers.AssertGeneratedAsExpected(source, expectedHandlers); + } + } +} diff --git a/test/Generation.Tests/Records.cs b/test/Generation.Tests/Records.cs new file mode 100644 index 000000000..207d2246e --- /dev/null +++ b/test/Generation.Tests/Records.cs @@ -0,0 +1,23 @@ +#pragma warning disable MA0048 // File name must match type name +#define INTERNAL_RECORD_ATTRIBUTES +#if NETSTANDARD || NETCOREAPP +using System.ComponentModel; + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] +#if INTERNAL_RECORD_ATTRIBUTES + internal +#else + public +#endif + static class IsExternalInit + { + } +} +#endif diff --git a/test/Generation.Tests/TypedCanBeResolvedTests.cs b/test/Generation.Tests/TypedCanBeResolvedTests.cs index 603b4768b..6931b11b6 100644 --- a/test/Generation.Tests/TypedCanBeResolvedTests.cs +++ b/test/Generation.Tests/TypedCanBeResolvedTests.cs @@ -21,6 +21,7 @@ public async Task Supports_Generating_Strongly_Typed_ICanBeResolved_Data() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -59,8 +60,7 @@ public partial class CodeLens : IRequest, ICanBeResolved } #nullable restore"; - var expected = @" -using System; + var expected = @"using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -71,6 +71,7 @@ public partial class CodeLens : IRequest, ICanBeResolved using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -86,10 +87,19 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Test public partial class CodeLens { public CodeLens WithData(TData data) - where TData : HandlerIdentity? , new() + where TData : HandlerIdentity? { return new CodeLens{Range = Range, Command = Command, Data = data}; } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""item"")] + public static CodeLens? From(CodeLens? item) + where T : HandlerIdentity? => item switch + { + not null => item, _ => null + } + + ; } /// @@ -101,7 +111,7 @@ public CodeLens WithData(TData data) /// [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial class CodeLens : ICanBeResolved where T : HandlerIdentity? , new() + public partial class CodeLens : ICanBeResolved where T : HandlerIdentity? { /// /// The range in which this code lens is valid. Should only span a single line. @@ -134,7 +144,7 @@ public T Data private string DebuggerDisplay => $""{Range}{(Command != null ? $"" {Command}"" : """")}""; public override string ToString() => DebuggerDisplay; public CodeLens WithData(TData data) - where TData : HandlerIdentity? , new() + where TData : HandlerIdentity? { return new CodeLens{Range = Range, Command = Command, Data = data}; } @@ -152,10 +162,23 @@ private JToken? JData } public static implicit operator CodeLens(CodeLens value) => new CodeLens{Range = value.Range, Command = value.Command, JData = ((ICanBeResolved)value).Data}; - public static implicit operator CodeLens(CodeLens value) => new CodeLens{Range = value.Range, Command = value.Command, Data = ((ICanBeResolved)value).Data}; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""value"")] + public static implicit operator CodeLens? (CodeLens? value) => value switch + { + not null => new CodeLens{Range = value.Range, Command = value.Command, Data = ((ICanBeResolved)value).Data}, _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""item"")] + public static CodeLens? From(CodeLens? item) => item switch + { + not null => item, _ => null + } + + ; } - public partial class CodeLensContainer : ContainerBase> where T : HandlerIdentity? , new() + public partial class CodeLensContainer : ContainerBase> where T : HandlerIdentity? { public CodeLensContainer(): this(Enumerable.Empty>()) { @@ -169,22 +192,93 @@ public CodeLensContainer(params CodeLens[] items): base(items) { } - public static implicit operator CodeLensContainer(CodeLens[] items) => new CodeLensContainer(items); - public static CodeLensContainer Create(params CodeLens[] items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(Collection> items) => new CodeLensContainer(items); - public static CodeLensContainer Create(Collection> items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(List> items) => new CodeLensContainer(items); - public static CodeLensContainer Create(List> items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(in ImmutableArray> items) => new CodeLensContainer(items); - public static CodeLensContainer Create(in ImmutableArray> items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(ImmutableList> items) => new CodeLensContainer(items); - public static CodeLensContainer Create(ImmutableList> items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(CodeLensContainer container) => new CodeLensContainer(container.Select(z => (CodeLens)z)); + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(IEnumerable>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(params CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (Collection>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(Collection>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (List>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(List>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (in ImmutableArray>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(in ImmutableArray>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (ImmutableList>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(ImmutableList>? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""container"")] + public static implicit operator CodeLensContainer? (CodeLensContainer? container) => container switch + { + not null => new CodeLensContainer(container.Select(value => (CodeLens)value)), _ => null + } + + ; } } -#nullable restore - -"; +#nullable restore"; await GenerationHelpers.AssertGeneratedAsExpected(source, expected); } @@ -203,6 +297,7 @@ public async Task Supports_Generating_Strongly_Typed_Container() using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -241,8 +336,7 @@ public partial class CodeLens : IRequest, ICanBeResolved } #nullable restore"; - var expected = @" -using System; + var expected = @"using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -253,6 +347,7 @@ public partial class CodeLens : IRequest, ICanBeResolved using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -280,21 +375,86 @@ public CodeLensContainer(params CodeLens[] items): base(items) { } - public static implicit operator CodeLensContainer(CodeLens[] items) => new CodeLensContainer(items); - public static CodeLensContainer Create(params CodeLens[] items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(Collection items) => new CodeLensContainer(items); - public static CodeLensContainer Create(Collection items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(List items) => new CodeLensContainer(items); - public static CodeLensContainer Create(List items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(in ImmutableArray items) => new CodeLensContainer(items); - public static CodeLensContainer Create(in ImmutableArray items) => new CodeLensContainer(items); - public static implicit operator CodeLensContainer(ImmutableList items) => new CodeLensContainer(items); - public static CodeLensContainer Create(ImmutableList items) => new CodeLensContainer(items); + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(IEnumerable? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(params CodeLens[] items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (Collection? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(Collection? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (List? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(List? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (in ImmutableArray? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(in ImmutableArray? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static implicit operator CodeLensContainer? (ImmutableList? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""items"")] + public static CodeLensContainer? From(ImmutableList? items) => items switch + { + not null => new CodeLensContainer(items), _ => null + } + + ; } } -#nullable restore - -"; +#nullable restore"; await GenerationHelpers.AssertGeneratedAsExpected(source, expected); } } diff --git a/test/JsonRpc.Tests/RecursiveResolutionTests.cs b/test/JsonRpc.Tests/RecursiveResolutionTests.cs index 8e922f089..f925c0003 100644 --- a/test/JsonRpc.Tests/RecursiveResolutionTests.cs +++ b/test/JsonRpc.Tests/RecursiveResolutionTests.cs @@ -109,7 +109,7 @@ public async Task Server_Facade_Can_Injected_Into_Handler_During_Creation_Using_ } [Method(nameof(ClassRequest))] - public class ClassRequest : IRequest + public class ClassRequest : IRequest { } @@ -128,7 +128,7 @@ public ClassHandler(T jsonRpcServer) } [Method(nameof(InterfaceRequest))] - public class InterfaceRequest : IRequest + public class InterfaceRequest : IRequest { } diff --git a/test/Lsp.Tests/ClientCapabilityProviderFixture.cs b/test/Lsp.Tests/ClientCapabilityProviderFixture.cs index 10b6815d6..92ff18f7f 100644 --- a/test/Lsp.Tests/ClientCapabilityProviderFixture.cs +++ b/test/Lsp.Tests/ClientCapabilityProviderFixture.cs @@ -9,6 +9,7 @@ using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; +using Arg = NSubstitute.Arg; namespace Lsp.Tests { @@ -19,7 +20,7 @@ internal class ClientCapabilityProviderFixture public ClientCapabilityProviderFixture() { var handler = Substitute.For(); - handler.GetRegistrationOptions().Returns(new ExecuteCommandRegistrationOptions()); + handler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new ExecuteCommandRegistrationOptions()); var handlerCollection = new SharedHandlerCollection( SupportedCapabilitiesFixture.AlwaysTrue, diff --git a/test/Lsp.Tests/ExecuteCommandSyncHandlerExtensions.cs b/test/Lsp.Tests/ExecuteCommandSyncHandlerExtensions.cs index 34bc679a5..2a9e949b8 100644 --- a/test/Lsp.Tests/ExecuteCommandSyncHandlerExtensions.cs +++ b/test/Lsp.Tests/ExecuteCommandSyncHandlerExtensions.cs @@ -1,6 +1,7 @@ using System.Threading; using MediatR; using NSubstitute; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; @@ -12,7 +13,7 @@ internal static class ExecuteCommandSyncExtensions public static IExecuteCommandHandler With(this IExecuteCommandHandler handler, Container commands) { - handler.GetRegistrationOptions().Returns(new ExecuteCommandRegistrationOptions { Commands = commands }); + handler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new ExecuteCommandRegistrationOptions { Commands = commands }); handler.Handle(Arg.Any(), Arg.Any()).Returns(Unit.Value); diff --git a/test/Lsp.Tests/FoundationTests.cs b/test/Lsp.Tests/FoundationTests.cs index 059ef0cc4..724d67015 100644 --- a/test/Lsp.Tests/FoundationTests.cs +++ b/test/Lsp.Tests/FoundationTests.cs @@ -129,7 +129,7 @@ public void Debugger_Display_Should_Not_Throw(Type type) { var instance = Activator.CreateInstance(type); var property = type.GetProperty("DebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance)!; - Func a1 = () => (property.GetValue(instance) as string)!; + Func a1 = () => ( property.GetValue(instance) as string )!; Func a2 = () => instance!.ToString()!; a1.Should().NotThrow().And.NotBeNull(); @@ -181,7 +181,7 @@ public void Registration_Converters_Should_Have_THe_Same_Properties(Type type) { var types = type.BaseType?.GetGenericArguments() ?? Array.Empty(); var source = types[0].GetProperties().Select(z => z.Name); - var destination = types[1].GetProperties().Select(z => z.Name).Except(new [] { "Id" }); + var destination = types[1].GetProperties().Select(z => z.Name).Except(new[] { "Id" }); source.Should().Contain(destination); } @@ -212,7 +212,7 @@ public void HandlersShouldAbstractClass(ILspHandlerTypeDescriptor descriptor) _logger.LogInformation("Delegating Handler: {Type}", delegatingHandler); delegatingHandler.DeclaringType.Should().NotBeNull(); delegatingHandler.DeclaringType!.GetMethods(BindingFlags.Public | BindingFlags.Static).Any(z => z.Name.StartsWith("On")).Should() - .BeTrue($"{descriptor.HandlerType.FullName} is missing delegating extension method"); + .BeTrue($"{descriptor.HandlerType.FullName} is missing delegating extension method"); } } @@ -578,10 +578,25 @@ public void Match(string description, params Func[] matchers) ) .Should().BeTrue($"{_descriptor.HandlerType.Name} {description} should have the correct method."); - if (_descriptor.HasRegistration && method.GetParameters().Length == 3) + if ( + _descriptor.HasRegistration + && _descriptor.RegistrationType is { } + && _descriptor.HasCapability + && _descriptor.CapabilityType is { } + && method.GetParameters().Length == 3 + ) { method.GetParameters()[2].ParameterType.Should().Be( - _descriptor.RegistrationType, + typeof(RegistrationOptionsDelegate<,>).MakeGenericType(_descriptor.RegistrationType, _descriptor.CapabilityType), + $"{_descriptor.HandlerType.FullName} {description} is has incorrect registration type {method.GetParameters()[2].ParameterType.FullName}" + ); + method.GetParameters()[2].IsOptional.Should() + .BeFalse($"{_descriptor.HandlerType.FullName} {description} Registration types should not be optional"); + } + else if (_descriptor.HasRegistration && _descriptor.RegistrationType is { } && method.GetParameters().Length == 3) + { + method.GetParameters()[2].ParameterType.Should().Be( + typeof(RegistrationOptionsDelegate<>).MakeGenericType(_descriptor.RegistrationType), $"{_descriptor.HandlerType.FullName} {description} is has incorrect registration type {method.GetParameters()[2].ParameterType.FullName}" ); method.GetParameters()[2].IsOptional.Should() @@ -653,14 +668,16 @@ public class TypeHandlerData : TheoryData public TypeHandlerData() { var handlerTypeDescriptorProvider = - new LspHandlerTypeDescriptorProvider(new[] { - typeof(HandlerTypeDescriptorProvider).Assembly, - typeof(LspHandlerTypeDescriptorProvider).Assembly, - typeof(LanguageServer).Assembly, - typeof(LanguageClient).Assembly, - typeof(ISupports).Assembly, - typeof(HandlerResolverTests).Assembly - }); + new LspHandlerTypeDescriptorProvider( + new[] { + typeof(HandlerTypeDescriptorProvider).Assembly, + typeof(LspHandlerTypeDescriptorProvider).Assembly, + typeof(LanguageServer).Assembly, + typeof(LanguageClient).Assembly, + typeof(ISupports).Assembly, + typeof(HandlerResolverTests).Assembly + } + ); foreach (var type in typeof(CompletionParams).Assembly.ExportedTypes.Where(z => z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => !z.Name.EndsWith("Manager")) .Except(new[] { typeof(ITextDocumentSyncHandler) }) @@ -675,7 +692,7 @@ public TypeHandlerData() public class TypeHandlerExtensionData : TheoryData { public static Type[] HandlersToSkip = { - typeof(ISemanticTokensHandler), + typeof(ISemanticTokensFullHandler), typeof(ISemanticTokensDeltaHandler), typeof(ISemanticTokensRangeHandler), typeof(ICodeActionHandler), @@ -684,14 +701,16 @@ public class TypeHandlerExtensionData : TheoryData z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => !z.Name.EndsWith("Manager")) @@ -700,8 +719,9 @@ public TypeHandlerExtensionData() { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; if (type.Name.EndsWith("Manager")) continue; - if (type == typeof(ICompletionResolveHandler) || type == typeof(ICodeLensResolveHandler) || type == typeof(IDocumentLinkResolveHandler) || type == typeof(ICodeActionResolveHandler)) continue; - if (type == typeof(ISemanticTokensHandler) || type == typeof(ISemanticTokensDeltaHandler) || type == typeof(ISemanticTokensRangeHandler)) continue; + if (type == typeof(ICompletionResolveHandler) || type == typeof(ICodeLensResolveHandler) || type == typeof(IDocumentLinkResolveHandler) + || type == typeof(ICodeActionResolveHandler)) continue; + if (type == typeof(ISemanticTokensFullHandler) || type == typeof(ISemanticTokensDeltaHandler) || type == typeof(ISemanticTokensRangeHandler)) continue; var descriptor = handlerTypeDescriptorProvider.GetHandlerTypeDescriptor(type); if (descriptor == null) diff --git a/test/Lsp.Tests/HandlerResolverTests.cs b/test/Lsp.Tests/HandlerResolverTests.cs index a62ea0c59..864bd8577 100644 --- a/test/Lsp.Tests/HandlerResolverTests.cs +++ b/test/Lsp.Tests/HandlerResolverTests.cs @@ -8,6 +8,7 @@ using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.General; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -15,6 +16,7 @@ using OmniSharp.Extensions.LanguageServer.Server; using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; +using Arg = NSubstitute.Arg; namespace Lsp.Tests { @@ -29,6 +31,7 @@ public void Should_Contain_AllDefinedMethods(Type requestHandler, string key, in { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler }, new object[0]); handler.Add(sub); @@ -41,6 +44,7 @@ public void Should_Contain_AllConcreteDefinedMethods() { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); handler.Add( Substitute.For(), @@ -63,6 +67,7 @@ public void Should_Contain_AllDefinedTextDocumentSyncMethods(string key, int cou { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); var sub = (IJsonRpcHandler) TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.something"), "csharp"); handler.Add(sub); @@ -79,6 +84,7 @@ public void Should_Contain_AllDefinedLanguageServerMethods(string key, int count { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); handler.Add( Substitute.For(), Substitute.For(), @@ -98,6 +104,7 @@ public void Should_Contain_AllDefinedLanguageServerMethods_GivenDuplicates(strin { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); handler.Add( Substitute.For(), Substitute.For(), @@ -125,6 +132,7 @@ public void Should_Contain_AllDefinedMethods_ForDifferentKeys(string key, int co { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); var sub = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); var sub2 = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); @@ -141,11 +149,12 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandle { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); - if (sub is IRegistration reg) - reg.GetRegistrationOptions() + if (sub is IRegistration reg) + reg.GetRegistrationOptions(Arg.Any()) .Returns( - new TextDocumentRegistrationOptions { + new TextDocumentSyncRegistrationOptions() { DocumentSelector = new DocumentSelector() } ); @@ -160,20 +169,21 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandle public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys(Type requestHandler, Type type2, string key, string key2, int count) { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), - new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); handler.Initialize(); +handler.Initialize(); var sub = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); - if (sub is IRegistration reg) - reg.GetRegistrationOptions() + if (sub is IRegistration reg) + reg.GetRegistrationOptions(Arg.Any()) .Returns( - new TextDocumentRegistrationOptions { + new TextDocumentSyncRegistrationOptions { DocumentSelector = new DocumentSelector() } ); var sub2 = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); - if (sub2 is IRegistration reg2) - reg2.GetRegistrationOptions() + if (sub2 is IRegistration reg2) + reg2.GetRegistrationOptions(Arg.Any()) .Returns( - new TextDocumentRegistrationOptions { + new TextDocumentSyncRegistrationOptions { DocumentSelector = new DocumentSelector() } ); @@ -190,6 +200,8 @@ public void Should_AllowSpecificHandlers_ToBeAdded(string method, Type handlerTy { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); + var sub = (IJsonRpcHandler) Substitute.For(new[] { handlerType }, new object[0]); var sub2 = (IJsonRpcHandler) Substitute.For(new[] { handlerType }, new object[0]); handler.Add(method, sub, null); @@ -205,17 +217,19 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflicti { var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); handler.Add(sub); var descriptor = handler.OfType().First(x => x.Method == method); descriptor.Key.Should().Be("default"); + handler.Initialize(); } [Fact] public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAccordingly() { var codeLensHandler = Substitute.For(new[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]); - ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions() + ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { DocumentSelector = new DocumentSelector(DocumentFilter.ForLanguage("foo")) @@ -224,6 +238,7 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAcco var handler = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, new TextDocumentIdentifiers(), Substitute.For(), new LspHandlerTypeDescriptorProvider(new [] { typeof(FoundationTests).Assembly, typeof(LanguageServer).Assembly, typeof(LanguageClient).Assembly, typeof(IRegistrationManager).Assembly, typeof(LspRequestRouter).Assembly })); + handler.Initialize(); handler.Add((codeLensHandler as IJsonRpcHandler)!); var descriptor = handler.OfType().Select(x => x.Key); @@ -233,7 +248,7 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAcco public static IEnumerable Should_DealWithClassesThatImplementMultipleHandlers_WithoutConflictingRegistrations_Data() { var codeLensHandler = Substitute.For(new[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler), typeof(ICanBeIdentifiedHandler) }, new object[0]); - ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions() + ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { DocumentSelector = new DocumentSelector() @@ -243,7 +258,7 @@ public static IEnumerable Should_DealWithClassesThatImplementMultipleH yield return new[] { TextDocumentNames.CodeLensResolve, codeLensHandler }; var documentLinkHandler = Substitute.For(new[] { typeof(IDocumentLinkHandler), typeof(IDocumentLinkResolveHandler), typeof(ICanBeIdentifiedHandler) }, new object[0]); - ( (IDocumentLinkHandler) documentLinkHandler ).GetRegistrationOptions() + ( (IDocumentLinkHandler) documentLinkHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new DocumentLinkRegistrationOptions { DocumentSelector = new DocumentSelector() @@ -253,7 +268,7 @@ public static IEnumerable Should_DealWithClassesThatImplementMultipleH yield return new[] { TextDocumentNames.DocumentLinkResolve, documentLinkHandler }; var completionHandler = Substitute.For(new[] { typeof(ICompletionHandler), typeof(ICompletionResolveHandler), typeof(ICanBeIdentifiedHandler) }, new object[0]); - ( (ICompletionHandler) completionHandler ).GetRegistrationOptions() + ( (ICompletionHandler) completionHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CompletionRegistrationOptions { DocumentSelector = new DocumentSelector() diff --git a/test/Lsp.Tests/Integration/DisableDefaultsTests.cs b/test/Lsp.Tests/Integration/DisableDefaultsTests.cs index 4804420d7..42055de0c 100644 --- a/test/Lsp.Tests/Integration/DisableDefaultsTests.cs +++ b/test/Lsp.Tests/Integration/DisableDefaultsTests.cs @@ -55,7 +55,7 @@ public async Task Should_Disable_Workspace_Folder_Manager() var serverAction = Substitute.For>(); var (client, server) = await Initialize( options => options.OnWorkspaceFolders(clientAction), - options => options.OnDidChangeWorkspaceFolders(serverAction, new object()) + options => options.OnDidChangeWorkspaceFolders(serverAction) ); var clientManager = client.Services.GetRequiredService(); @@ -63,7 +63,7 @@ public async Task Should_Disable_Workspace_Folder_Manager() clientManager.Descriptors.Should().ContainSingle(f => f.Method == WorkspaceNames.WorkspaceFolders); var serverManager = server.Services.GetRequiredService(); - serverManager.Descriptors.Should().Contain(f => f.Handler is LanguageProtocolDelegatingHandlers.Notification); + serverManager.Descriptors.Should().Contain(f => f.Handler is DelegatingHandlers.Notification); serverManager.Descriptors.Should().ContainSingle(f => f.Method == WorkspaceNames.DidChangeWorkspaceFolders); } @@ -74,7 +74,7 @@ public async Task Should_Allow_Custom_Workspace_Folder_Manager_Delegate() var (client, server) = await Initialize( options => { }, options => options - .OnDidChangeWorkspaceFolders(action, new object()) + .OnDidChangeWorkspaceFolders(action) ); var config = client.Services.GetRequiredService(); @@ -103,11 +103,11 @@ public async Task Should_Disable_Configuration() var action = Substitute.For>(); var (_, server) = await Initialize( options => { }, - options => options.OnDidChangeConfiguration(action, new object()) + options => options.OnDidChangeConfiguration(action) ); var serverManager = server.Services.GetRequiredService(); - serverManager.Descriptors.Should().Contain(f => f.Handler is LanguageProtocolDelegatingHandlers.Notification); + serverManager.Descriptors.Should().Contain(f => f.Handler is DelegatingHandlers.Notification); serverManager.Descriptors.Should().ContainSingle(f => f.Method == WorkspaceNames.DidChangeConfiguration); } @@ -121,7 +121,7 @@ public async Task Should_Allow_Custom_Configuration_Delegate() .WithServices(z => z.AddSingleton()), options => options .WithConfigurationSection("mysection") - .OnDidChangeConfiguration(action, new object()) + .OnDidChangeConfiguration(action) ); var clientManager = client.Services.GetRequiredService(); diff --git a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs index 4e8fdb0fc..d2fc8135c 100644 --- a/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs +++ b/test/Lsp.Tests/Integration/DynamicRegistrationTests.cs @@ -3,6 +3,7 @@ using System.Reactive.Linq; using System.Threading.Tasks; using FluentAssertions; +using ImTools; using Lsp.Tests.Integration.Fixtures; using NSubstitute; using NSubstitute.ReceivedExtensions; @@ -59,7 +60,7 @@ public async Task Should_Register_Dynamically_While_Server_Is_Running() x => x .OnCompletion( (@params, token) => Task.FromResult(new CompletionList()), - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ) @@ -108,7 +109,7 @@ public async Task Should_Unregister_Dynamically_While_Server_Is_Running() var disposable = server.Register( x => x.OnCompletion( (@params, token) => Task.FromResult(new CompletionList()), - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ) @@ -136,7 +137,9 @@ await TestHelper.DelayUntil( [Fact] public async Task Should_Only_Register_Semantic_Tokens_Registration_Once() { - var tokens = Substitute.For(new SemanticTokensRegistrationOptions()); + var tokens = Substitute.For(); + tokens.CreateRegistrationOptions(Arg.Any(), Arg.Any()) + .Returns(new SemanticTokensRegistrationOptions()); var (client, server) = await Initialize(new ConfigureClient().Configure, options => { new ConfigureServer().Configure(options); options.AddHandler(tokens); @@ -148,7 +151,7 @@ await TestHelper.DelayUntil( CancellationToken ); - tokens.Received(Quantity.Exactly(1)).GetRegistrationOptions(); + tokens.Received(1).CreateRegistrationOptions(Arg.Any(), Arg.Any()); client.RegistrationManager.CurrentRegistrations.Should().ContainSingle(x => x.Method == TextDocumentNames.SemanticTokensRegistration); } @@ -327,18 +330,18 @@ public void Configure(LanguageServerOptions options) { options.OnCompletion( (@params, token) => Task.FromResult(new CompletionList()), - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("csharp"), - ResolveProvider = false, + ResolveProvider = true, TriggerCharacters = new Container("a", "b"), AllCommitCharacters = new Container("1", "2"), } ); options.OnSemanticTokens( - (builder, @params, ct) => { return Task.CompletedTask; }, - (@params, token) => { return Task.FromResult(new SemanticTokensDocument(new SemanticTokensLegend())); }, - new SemanticTokensRegistrationOptions() + (builder, @params, ct) => Task.CompletedTask, + (@params, token) => Task.FromResult(new SemanticTokensDocument(new SemanticTokensLegend())), + (_, _) => new SemanticTokensRegistrationOptions() ); } } diff --git a/test/Lsp.Tests/Integration/EventingTests.cs b/test/Lsp.Tests/Integration/EventingTests.cs index 6e6493779..4cebd6ddf 100644 --- a/test/Lsp.Tests/Integration/EventingTests.cs +++ b/test/Lsp.Tests/Integration/EventingTests.cs @@ -58,9 +58,9 @@ public async Task Initialize_Delegate_Is_Supported() public async Task Initialize_Interface_Is_Supported_On_Handlers() { var onLanguageClientInitialize = - (IOnLanguageClientInitialize) Substitute.For(new[] { typeof(IOnLanguageClientInitialize), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientInitialize) Substitute.For(new[] { typeof(IOnLanguageClientInitialize), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerInitialize = - (IOnLanguageServerInitialize) Substitute.For(new[] { typeof(IOnLanguageServerInitialize), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerInitialize) Substitute.For(new[] { typeof(IOnLanguageServerInitialize), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize( options => options.AddHandler((IJsonRpcHandler) onLanguageClientInitialize!), options => options.AddHandler((IJsonRpcHandler) onLanguageServerInitialize!) @@ -74,9 +74,9 @@ public async Task Initialize_Interface_Is_Supported_On_Handlers() public async Task Initialize_Interface_Is_Supported_On_Handlers_After_Startup() { var onLanguageClientInitialize = - (IOnLanguageClientInitialize) Substitute.For(new[] { typeof(IOnLanguageClientInitialize), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientInitialize) Substitute.For(new[] { typeof(IOnLanguageClientInitialize), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerInitialize = - (IOnLanguageServerInitialize) Substitute.For(new[] { typeof(IOnLanguageServerInitialize), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerInitialize) Substitute.For(new[] { typeof(IOnLanguageServerInitialize), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize(o => { }, o => { }); await onLanguageClientInitialize.Received(0).OnInitialize(client, client.ClientSettings, Arg.Any()); @@ -121,9 +121,9 @@ public async Task Initialized_Delegate_Is_Supported() public async Task Initialized_Interface_Is_Supported_On_Handlers() { var onLanguageClientInitialized = - (IOnLanguageClientInitialized) Substitute.For(new[] { typeof(IOnLanguageClientInitialized), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientInitialized) Substitute.For(new[] { typeof(IOnLanguageClientInitialized), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerInitialized = - (IOnLanguageServerInitialized) Substitute.For(new[] { typeof(IOnLanguageServerInitialized), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerInitialized) Substitute.For(new[] { typeof(IOnLanguageServerInitialized), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize( options => options.AddHandler((IJsonRpcHandler) onLanguageClientInitialized!), options => options.AddHandler((IJsonRpcHandler) onLanguageServerInitialized!) @@ -137,9 +137,9 @@ public async Task Initialized_Interface_Is_Supported_On_Handlers() public async Task Initialized_Interface_Is_Supported_On_Handlers_After_Startup() { var onLanguageClientInitialized = - (IOnLanguageClientInitialized) Substitute.For(new[] { typeof(IOnLanguageClientInitialized), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientInitialized) Substitute.For(new[] { typeof(IOnLanguageClientInitialized), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerInitialized = - (IOnLanguageServerInitialized) Substitute.For(new[] { typeof(IOnLanguageServerInitialized), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerInitialized) Substitute.For(new[] { typeof(IOnLanguageServerInitialized), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize(o => { }, o => { }); await onLanguageClientInitialized.Received(0).OnInitialized(client, client.ClientSettings, client.ServerSettings, Arg.Any()); @@ -184,9 +184,9 @@ public async Task Started_Delegate_Is_Supported() public async Task Started_Interface_Is_Supported_On_Handlers() { var onLanguageClientStarted = - (IOnLanguageClientStarted) Substitute.For(new[] { typeof(IOnLanguageClientStarted), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientStarted) Substitute.For(new[] { typeof(IOnLanguageClientStarted), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerStarted = - (IOnLanguageServerStarted) Substitute.For(new[] { typeof(IOnLanguageServerStarted), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerStarted) Substitute.For(new[] { typeof(IOnLanguageServerStarted), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize( options => options.AddHandler((IJsonRpcHandler) onLanguageClientStarted!), options => options.AddHandler((IJsonRpcHandler) onLanguageServerStarted!) @@ -200,9 +200,9 @@ public async Task Started_Interface_Is_Supported_On_Handlers() public async Task Started_Interface_Is_Supported_On_Handlers_After_Startup() { var onLanguageClientStarted = - (IOnLanguageClientStarted) Substitute.For(new[] { typeof(IOnLanguageClientStarted), typeof(PublishDiagnosticsHandler) }, Array.Empty()); + (IOnLanguageClientStarted) Substitute.For(new[] { typeof(IOnLanguageClientStarted), typeof(PublishDiagnosticsHandlerBase) }, Array.Empty()); var onLanguageServerStarted = - (IOnLanguageServerStarted) Substitute.For(new[] { typeof(IOnLanguageServerStarted), typeof(CompletionHandler) }, new object[] { new CompletionRegistrationOptions() }); + (IOnLanguageServerStarted) Substitute.For(new[] { typeof(IOnLanguageServerStarted), typeof(CompletionHandlerBase) }, new object[] { }); var (client, server) = await Initialize(o => { }, o => { }); await onLanguageClientStarted.Received(0).OnStarted(client, Arg.Any()); diff --git a/test/Lsp.Tests/Integration/ExecuteCommandTests.cs b/test/Lsp.Tests/Integration/ExecuteCommandTests.cs index 17599ca21..7e0899b80 100644 --- a/test/Lsp.Tests/Integration/ExecuteCommandTests.cs +++ b/test/Lsp.Tests/Integration/ExecuteCommandTests.cs @@ -42,11 +42,11 @@ public async Task Should_Execute_A_Command() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( - command, new ExecuteCommandRegistrationOptions { + command, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-a") } ); @@ -86,17 +86,17 @@ public async Task Should_Execute_The_Correct_Command() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( - commanda, new ExecuteCommandRegistrationOptions { + commanda, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-a") } ); options.OnExecuteCommand( - commandb, new ExecuteCommandRegistrationOptions { + commandb, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-b") } ); @@ -131,7 +131,7 @@ public async Task Should_Fail_To_Execute_A_Command_When_No_Command_Is_Defined() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); } ); @@ -163,11 +163,11 @@ public async Task Should_Fail_To_Execute_A_Command_When_No_Command_Name_Is_Given } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( - command, new ExecuteCommandRegistrationOptions { + command, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-a") } ); @@ -202,17 +202,17 @@ public async Task Should_Fail_To_Execute_A_Command() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( - commandb, new ExecuteCommandRegistrationOptions { + commandb, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-b") } ); options.OnExecuteCommand( - commandc, new ExecuteCommandRegistrationOptions { + commandc, (_, _) => new ExecuteCommandRegistrationOptions { Commands = new Container("execute-c") } ); @@ -246,7 +246,7 @@ public async Task Should_Execute_1_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -283,7 +283,7 @@ public async Task Should_Execute_2_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -321,7 +321,7 @@ public async Task Should_Execute_3_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -360,7 +360,7 @@ public async Task Should_Execute_4_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -402,7 +402,7 @@ public async Task Should_Execute_5_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand>( @@ -446,7 +446,7 @@ public async Task Should_Execute_6_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand, Guid>( @@ -488,7 +488,7 @@ public async Task Should_Execute_1_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -525,7 +525,7 @@ public async Task Should_Execute_2_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -563,7 +563,7 @@ public async Task Should_Execute_3_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -602,7 +602,7 @@ public async Task Should_Execute_4_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -642,7 +642,7 @@ public async Task Should_Execute_5_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand>( @@ -683,7 +683,7 @@ public async Task Should_Execute_6_With_Missing_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand, Guid>( @@ -725,7 +725,7 @@ public async Task Should_Execute_1_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -762,7 +762,7 @@ public async Task Should_Execute_2_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -800,7 +800,7 @@ public async Task Should_Execute_3_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -839,7 +839,7 @@ public async Task Should_Execute_4_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand( @@ -879,7 +879,7 @@ public async Task Should_Execute_5_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand>( @@ -920,7 +920,7 @@ public async Task Should_Execute_6_Null_Args() } ) ); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); options.OnExecuteCommand, Guid>( diff --git a/test/Lsp.Tests/Integration/ExtensionTests.cs b/test/Lsp.Tests/Integration/ExtensionTests.cs index b6eefc5b2..ce376e30d 100644 --- a/test/Lsp.Tests/Integration/ExtensionTests.cs +++ b/test/Lsp.Tests/Integration/ExtensionTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using System.Threading; @@ -47,8 +47,11 @@ public async Task Should_Support_Custom_Capabilities() Property = "Abcd" } ), options => { - options.OnDiscoverUnitTests(onDiscoverHandler, new UnitTestRegistrationOptions()); - options.OnRunUnitTest(onRunUnitHandler, new UnitTestRegistrationOptions()); + options.OnDiscoverUnitTests(onDiscoverHandler, (_, _) => new UnitTestRegistrationOptions()); + options.OnRunUnitTest(onRunUnitHandler, (_, _) => new UnitTestRegistrationOptions() { + SupportsDebugging = true, + WorkDoneProgress = true + }); } ); @@ -73,7 +76,10 @@ public async Task Should_Support_Custom_Capabilities() client.RegistrationManager.CurrentRegistrations.Should().Contain(z => z.Method == "tests/run"); } - await client.RequestDiscoverUnitTests(new DiscoverUnitTestsParams(), CancellationToken); + await client.RequestDiscoverUnitTests(new DiscoverUnitTestsParams() { + PartialResultToken = new ProgressToken(1), + WorkDoneToken = new ProgressToken(1), + }, CancellationToken); await client.RunUnitTest(new UnitTest(), CancellationToken); onDiscoverHandler.Received(1).Invoke(Arg.Any(), Arg.Is(x => x.Property == "Abcd"), Arg.Any()); @@ -94,8 +100,8 @@ public async Task Should_Support_Custom_Capabilities_Using_Json() var (client, server) = await Initialize( options => { options.ClientCapabilities.Workspace!.ExtensionData["unitTests"] = JToken.FromObject(new { property = "Abcd", dynamicRegistration = true }); }, options => { - options.OnDiscoverUnitTests(onDiscoverHandler, new UnitTestRegistrationOptions()); - options.OnRunUnitTest(onRunUnitHandler, new UnitTestRegistrationOptions()); + options.OnDiscoverUnitTests(onDiscoverHandler, (_, _) => new UnitTestRegistrationOptions()); + options.OnRunUnitTest(onRunUnitHandler, (_, _) => new UnitTestRegistrationOptions()); } ); @@ -135,8 +141,8 @@ public async Task Should_Support_Custom_Static_Options() Property = "Abcd" } ), options => { - options.OnDiscoverUnitTests(onDiscoverHandler, new UnitTestRegistrationOptions() { SupportsDebugging = true }); - options.OnRunUnitTest(onRunUnitHandler, new UnitTestRegistrationOptions() { SupportsDebugging = true }); + options.OnDiscoverUnitTests(onDiscoverHandler, (_, _) => new UnitTestRegistrationOptions() { SupportsDebugging = true }); + options.OnRunUnitTest(onRunUnitHandler, (_, _) => new UnitTestRegistrationOptions() { SupportsDebugging = true }); } ); @@ -146,8 +152,8 @@ public async Task Should_Support_Custom_Static_Options() } { - server.ServerSettings.Capabilities.ExtensionData["unitTests"].Should().NotBeNull(); - server.ServerSettings.Capabilities.ExtensionData["unitTests"] + server.ServerSettings.Capabilities.ExtensionData["unitTestDiscovery"].Should().NotBeNull(); + server.ServerSettings.Capabilities.ExtensionData["unitTestDiscovery"] .ToObject().SupportsDebugging.Should().BeTrue(); } @@ -186,7 +192,7 @@ public async Task Should_Convert_Registration_Options_Into_Static_Options_As_Req options => { options.OnCodeAction( (@params, capability, token) => Task.FromResult(new CommandOrCodeActionContainer()), - new CodeActionRegistrationOptions() { + (_, _) => new CodeActionRegistrationOptions() { CodeActionKinds = new Container( CodeActionKind.RefactorExtract, CodeActionKind.RefactorInline, diff --git a/test/Lsp.Tests/Integration/Fixtures/ExampleExtensions.cs b/test/Lsp.Tests/Integration/Fixtures/ExampleExtensions.cs index 2a4850c6b..e109240e5 100644 --- a/test/Lsp.Tests/Integration/Fixtures/ExampleExtensions.cs +++ b/test/Lsp.Tests/Integration/Fixtures/ExampleExtensions.cs @@ -4,69 +4,43 @@ using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; namespace Lsp.Tests.Integration.Fixtures { + [Parallel, Method("tests/discover", Direction.ClientToServer)] + [ + GenerateHandler, + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class DiscoverUnitTestsParams : IPartialItemsRequest, UnitTest>, IWorkDoneProgressParams { } + [Parallel, Method("tests/run", Direction.ClientToServer)] - public class UnitTest : IRequest + [ + GenerateHandler(Name = "RunUnitTest"), + GenerateHandlerMethods(typeof(ILanguageServerRegistry)), + GenerateRequestMethods(typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] + public partial class UnitTest : IJsonRpcRequest { public string Name { get; set; } = null!; } [CapabilityKey("workspace", "unitTests")] - public class UnitTestCapability : DynamicCapability + public partial class UnitTestCapability : DynamicCapability { public string Property { get; set; } = null!; } - public class UnitTestRegistrationOptions : IWorkDoneProgressOptions, IRegistrationOptions + [GenerateRegistrationOptions("unitTestDiscovery")] + public partial class UnitTestRegistrationOptions : IWorkDoneProgressOptions { [Optional] public bool SupportsDebugging { get; set; } - [Optional] public bool WorkDoneProgress { get; set; } - - public class StaticOptions : WorkDoneProgressOptions - { - [Optional] public bool SupportsDebugging { get; set; } - } - - private class Converter : RegistrationOptionsConverterBase - { - public Converter() : base("unitTests") - { - } - - public override StaticOptions Convert(UnitTestRegistrationOptions source) - { - return new StaticOptions { - SupportsDebugging = source.SupportsDebugging, - WorkDoneProgress = source.WorkDoneProgress, - }; - } - } - } - - [Parallel, Method("tests/discover", Direction.ClientToServer)] - public class DiscoverUnitTestsParams : IPartialItemsRequest, UnitTest>, IWorkDoneProgressParams - { - public ProgressToken? PartialResultToken { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } = null!; - } - - [Parallel, Method("tests/discover", Direction.ClientToServer)] - [GenerateHandlerMethods(typeof(ILanguageServerRegistry))] - [GenerateRequestMethods(typeof(ILanguageClient))] - public interface IDiscoverUnitTestsHandler : IJsonRpcRequestHandler>, IRegistration, - ICapability - { - } - - [Parallel, Method("tests/run", Direction.ClientToServer)] - [GenerateHandlerMethods(typeof(ILanguageServerRegistry))] - [GenerateRequestMethods(typeof(ILanguageClient))] - public interface IRunUnitTestHandler : IJsonRpcRequestHandler, IRegistration, ICapability - { } } diff --git a/test/Lsp.Tests/Integration/InitializationTests.cs b/test/Lsp.Tests/Integration/InitializationTests.cs index 45d39272a..383034eb9 100644 --- a/test/Lsp.Tests/Integration/InitializationTests.cs +++ b/test/Lsp.Tests/Integration/InitializationTests.cs @@ -14,6 +14,7 @@ using OmniSharp.Extensions.LanguageProtocol.Testing; using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -114,9 +115,9 @@ await Observable.FromAsync(client.Initialize) response.Should().NotBeNull(); } - class CodeLensHandlerA : CodeLensHandler + class CodeLensHandlerA : CodeLensHandlerBase { - public CodeLensHandlerA(ILanguageServerFacade languageServerFacade) : base(new CodeLensRegistrationOptions()) + public CodeLensHandlerA(ILanguageServerFacade languageServerFacade) { languageServerFacade.Should().NotBeNull(); } @@ -124,6 +125,7 @@ public CodeLensHandlerA(ILanguageServerFacade languageServerFacade) : base(new C public override Task Handle(CodeLensParams request, CancellationToken cancellationToken) => Task.FromResult(new CodeLensContainer()); public override Task Handle(CodeLens request, CancellationToken cancellationToken) => Task.FromResult(request); + protected internal override CodeLensRegistrationOptions CreateRegistrationOptions(CodeLensCapability capability, ClientCapabilities clientCapabilities) => new (); } private readonly List _logs = new List(); diff --git a/test/Lsp.Tests/Integration/MonikerTests.cs b/test/Lsp.Tests/Integration/MonikerTests.cs index 11a0a5212..fe00526fc 100644 --- a/test/Lsp.Tests/Integration/MonikerTests.cs +++ b/test/Lsp.Tests/Integration/MonikerTests.cs @@ -52,7 +52,7 @@ public async Task Should_Get_Monikers() private void ServerOptionsAction(LanguageServerOptions obj) { obj.OnMoniker( - _request, new MonikerRegistrationOptions() { + _request, (_, _) => new MonikerRegistrationOptions() { DocumentSelector = DocumentSelector.ForLanguage("csharp"), } ); diff --git a/test/Lsp.Tests/Integration/OverrideHandlerTests.cs b/test/Lsp.Tests/Integration/OverrideHandlerTests.cs index 79be3846c..7a89a6106 100644 --- a/test/Lsp.Tests/Integration/OverrideHandlerTests.cs +++ b/test/Lsp.Tests/Integration/OverrideHandlerTests.cs @@ -73,7 +73,7 @@ public async Task Should_Support_Mixed_Execute_Command_Handlers() } [Method(WorkspaceNames.ExecuteCommand)] - public class CustomExecuteCommandHandler : IJsonRpcRequestHandler, IRegistration, ICapability + public class CustomExecuteCommandHandler : IJsonRpcRequestHandler, IRegistration { // ReSharper disable once NotAccessedField.Local private ExecuteCommandCapability? _capability; @@ -87,8 +87,11 @@ public Task Handle(CustomExecuteCommandParams request, CancellationToken return Task.FromResult(JToken.FromObject(new { someValue = "custom" })); } - public ExecuteCommandRegistrationOptions GetRegistrationOptions() { return _executeCommandRegistrationOptions; } - public void SetCapability(ExecuteCommandCapability capability) => _capability = capability; + public ExecuteCommandRegistrationOptions GetRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities) + { + _capability = capability; + return _executeCommandRegistrationOptions; + } } [Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] diff --git a/test/Lsp.Tests/Integration/PartialItemTests.cs b/test/Lsp.Tests/Integration/PartialItemTests.cs index 9ad4b2c2c..6e6a21471 100644 --- a/test/Lsp.Tests/Integration/PartialItemTests.cs +++ b/test/Lsp.Tests/Integration/PartialItemTests.cs @@ -64,13 +64,13 @@ public async Task Should_Behave_Like_An_Observable_Without_Progress_Support() public class DelegateServer : IConfigureLanguageServerOptions { - public void Configure(LanguageServerOptions options) => options.OnSemanticTokens( + public void Configure(LanguageServerOptions options) => options.ObserveSemanticTokensFull( (@params, observer, arg3) => { observer.OnNext(new SemanticTokensPartialResult() { Data = new[] { 0 }.ToImmutableArray() }); observer.OnNext(new SemanticTokensPartialResult() { Data = new[] { 0, 1 }.ToImmutableArray() }); observer.OnNext(new SemanticTokensPartialResult() { Data = new[] { 0, 1, 2 }.ToImmutableArray() }); observer.OnCompleted(); - }, new SemanticTokensRegistrationOptions() + }, (_, _) => new SemanticTokensRegistrationOptions() ); } } diff --git a/test/Lsp.Tests/Integration/PartialItemsTests.cs b/test/Lsp.Tests/Integration/PartialItemsTests.cs index 575096b8c..d3740aa9f 100644 --- a/test/Lsp.Tests/Integration/PartialItemsTests.cs +++ b/test/Lsp.Tests/Integration/PartialItemsTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reactive; @@ -8,6 +8,7 @@ using System.Threading.Tasks; using FluentAssertions; using Lsp.Tests.Integration.Fixtures; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Client.WorkDone; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -78,7 +79,7 @@ public async Task Should_Behave_Like_An_Observable_Without_Progress_Support() public class DelegateServer : IConfigureLanguageServerOptions { public void Configure(LanguageServerOptions options) => - options.OnCodeLens( + options.ObserveCodeLens( (@params, observer, capability, cancellationToken) => { observer.OnNext( new[] { @@ -108,7 +109,7 @@ public void Configure(LanguageServerOptions options) => } ); observer.OnCompleted(); - }, new CodeLensRegistrationOptions() + }, (_, _) => new CodeLensRegistrationOptions() ); } } @@ -150,12 +151,12 @@ public class HandlersServer : IConfigureLanguageServerOptions } } - private class InnerCodeLensHandler : CodeLensHandler + private class InnerCodeLensHandler : CodeLensHandlerBase { private readonly IServerWorkDoneManager _workDoneManager; private readonly IProgressManager _progressManager; - public InnerCodeLensHandler(IServerWorkDoneManager workDoneManager, IProgressManager progressManager) : base(new CodeLensRegistrationOptions()) + public InnerCodeLensHandler(IServerWorkDoneManager workDoneManager, IProgressManager progressManager) { _workDoneManager = workDoneManager; _progressManager = progressManager; @@ -247,6 +248,7 @@ public override async Task Handle(CodeLensParams request, Can } public override Task Handle(CodeLens request, CancellationToken cancellationToken) => Task.FromResult(request); + protected internal override CodeLensRegistrationOptions CreateRegistrationOptions(CodeLensCapability capability, ClientCapabilities clientCapabilities) => new CodeLensRegistrationOptions(); } } } diff --git a/test/Lsp.Tests/Integration/RecursiveResolutionTests.cs b/test/Lsp.Tests/Integration/RecursiveResolutionTests.cs index 46b9072af..205cca543 100644 --- a/test/Lsp.Tests/Integration/RecursiveResolutionTests.cs +++ b/test/Lsp.Tests/Integration/RecursiveResolutionTests.cs @@ -329,7 +329,7 @@ public enum Side } [Method(nameof(ClassRequest))] - public class ClassRequest : IRequest + public class ClassRequest : IRequest { } @@ -348,7 +348,7 @@ public ClassHandler(T jsonRpcServer) } [Method(nameof(InterfaceRequest))] - public class InterfaceRequest : IRequest + public class InterfaceRequest : IRequest { } @@ -367,7 +367,7 @@ public InterfaceHandler(T jsonRpcServer) } [Method(nameof(NestedRequest))] - public class NestedRequest : IRequest + public class NestedRequest : IRequest { } diff --git a/test/Lsp.Tests/Integration/RenameTests.cs b/test/Lsp.Tests/Integration/RenameTests.cs index bab37f116..a8c609dc8 100644 --- a/test/Lsp.Tests/Integration/RenameTests.cs +++ b/test/Lsp.Tests/Integration/RenameTests.cs @@ -210,12 +210,12 @@ await client.DelayUntil( private void ServerOptionsAction(LanguageServerOptions obj) { obj.OnPrepareRename( - _prepareRename, new TextDocumentRegistrationOptions() { + _prepareRename, (_, _) => new RenameRegistrationOptions() { DocumentSelector = DocumentSelector.ForLanguage("csharp") } ); obj.OnRename( - _rename, new RenameRegistrationOptions() { + _rename, (_, _) =>new RenameRegistrationOptions() { DocumentSelector = DocumentSelector.ForLanguage("csharp"), PrepareProvider = true, } diff --git a/test/Lsp.Tests/Integration/RequestCancellationTests.cs b/test/Lsp.Tests/Integration/RequestCancellationTests.cs index 1a071d9c8..f7631f1d6 100644 --- a/test/Lsp.Tests/Integration/RequestCancellationTests.cs +++ b/test/Lsp.Tests/Integration/RequestCancellationTests.cs @@ -162,9 +162,9 @@ private void ConfigureServer(LanguageServerOptions options) async (x, ct) => { await Task.Delay(50000, ct); return new CompletionList(); - }, new CompletionRegistrationOptions() + }, (_, _) => new CompletionRegistrationOptions() ); - options.OnDidChangeTextDocument(async x => { await Task.Delay(20); }, new TextDocumentChangeRegistrationOptions()); + options.OnDidChangeTextDocument(async x => { await Task.Delay(20); }, (_, _) =>new TextDocumentChangeRegistrationOptions()); } } } diff --git a/test/Lsp.Tests/Integration/TypedCallHierarchyTests.cs b/test/Lsp.Tests/Integration/TypedCallHierarchyTests.cs index 96df3836a..0dcbc084b 100644 --- a/test/Lsp.Tests/Integration/TypedCallHierarchyTests.cs +++ b/test/Lsp.Tests/Integration/TypedCallHierarchyTests.cs @@ -35,7 +35,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() var outgoingHandlerA = Substitute.For, Task?>>>(); var outgoingHandlerB = Substitute.For, Task?>>>(); var (client, _) = await Initialize( - options => { }, options => { + options => { options.EnableAllCapabilities(); }, options => { var identifier = Substitute.For(); identifier.GetTextDocumentAttributes(Arg.Any()).Returns( call => new TextDocumentAttributes(call.ArgAt(0), "file", "csharp") @@ -60,7 +60,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() )!, incomingHandlerA, outgoingHandlerA, - new CallHierarchyRegistrationOptions() { + (_, _) => new() { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -79,7 +79,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() )!, incomingHandlerB, outgoingHandlerB, - new CallHierarchyRegistrationOptions() { + (_, _) => new() { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -109,7 +109,7 @@ public async Task Should_Resolve_With_Data_Capability() var incomingHandler = Substitute.For, Task?>>>(); var outgoingHandler = Substitute.For, Task?>>>(); var (client, _) = await Initialize( - options => { }, options => { + options => { options.EnableAllCapabilities(); }, options => { options.OnCallHierarchy( @params => Task.FromResult( new Container?>( @@ -128,7 +128,7 @@ public async Task Should_Resolve_With_Data_Capability() )!, incomingHandler, outgoingHandler, - new CallHierarchyRegistrationOptions() { + (_, _) => new() { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -187,7 +187,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() b.OnNext(Enumerable.Empty()); b.OnCompleted(); }, - new CallHierarchyRegistrationOptions() + (_, _) => new() ); } ); diff --git a/test/Lsp.Tests/Integration/TypedCodeActionTests.cs b/test/Lsp.Tests/Integration/TypedCodeActionTests.cs index 3d334a943..6df7dd1ce 100644 --- a/test/Lsp.Tests/Integration/TypedCodeActionTests.cs +++ b/test/Lsp.Tests/Integration/TypedCodeActionTests.cs @@ -61,7 +61,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action.Command!.Name = "resolved-a"; return Task.FromResult(action); }, - new CodeActionRegistrationOptions { + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -88,7 +88,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action.Command!.Name = "resolved-b"; return Task.FromResult(action); }, - new CodeActionRegistrationOptions { + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -112,7 +112,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action.Command!.Name = "resolved-c"; return Task.FromResult(action); }, - new CodeActionRegistrationOptions { + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -136,7 +136,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action.Command!.Name = "resolved-d"; return Task.FromResult(action); }, - new CodeActionRegistrationOptions { + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ); @@ -191,7 +191,7 @@ public async Task Should_Resolve_With_Data_Capability() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -209,7 +209,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer, capability, token) => { var a = new CodeActionContainer( new CodeAction { @@ -239,7 +239,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -284,7 +284,7 @@ public async Task Should_Resolve_With_Data_CancellationToken() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -302,7 +302,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer, token) => { var a = new CodeActionContainer( new CodeAction { @@ -332,7 +332,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -377,7 +377,7 @@ public async Task Should_Resolve_With_Data() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -395,7 +395,7 @@ public async Task Should_Resolve_With_Partial_Data() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer) => { var a = new CodeActionContainer( new CodeAction { @@ -425,7 +425,7 @@ public async Task Should_Resolve_With_Partial_Data() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -461,7 +461,7 @@ public async Task Should_Resolve_Capability() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -479,7 +479,7 @@ public async Task Should_Resolve_Partial_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer, capability, token) => { var a = new CommandOrCodeActionContainer( new CodeAction { @@ -492,14 +492,14 @@ public async Task Should_Resolve_Partial_Capability() } ); - observer.OnNext(a.GetCodeActions()); + observer.OnNext(a); observer.OnCompleted(); }, (codeAction, capability, token) => { codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -534,7 +534,7 @@ public async Task Should_Resolve_CancellationToken() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -552,7 +552,7 @@ public async Task Should_Resolve_Partial_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer, token) => { var a = new CommandOrCodeActionContainer( new CodeAction { @@ -565,14 +565,14 @@ public async Task Should_Resolve_Partial_CancellationToken() } ); - observer.OnNext(a.GetCodeActions()); + observer.OnNext(a); observer.OnCompleted(); }, (codeAction, token) => { codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -607,7 +607,7 @@ public async Task Should_Resolve() codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); @@ -625,7 +625,7 @@ public async Task Should_Resolve_Partial() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeAction( + options.ObserveCodeAction( (codeActionParams, observer) => { var a = new CommandOrCodeActionContainer( new CodeAction { @@ -638,14 +638,14 @@ public async Task Should_Resolve_Partial() } ); - observer.OnNext(a.GetCodeActions()); + observer.OnNext(a); observer.OnCompleted(); }, codeAction => { codeAction.Command!.Name = "resolved"; return Task.FromResult(codeAction); }, - new CodeActionRegistrationOptions() + (_, _) => new CodeActionRegistrationOptions() ); } ); diff --git a/test/Lsp.Tests/Integration/TypedCodeLensTests.cs b/test/Lsp.Tests/Integration/TypedCodeLensTests.cs index c30650cf9..8ac6cdcf3 100644 --- a/test/Lsp.Tests/Integration/TypedCodeLensTests.cs +++ b/test/Lsp.Tests/Integration/TypedCodeLensTests.cs @@ -60,7 +60,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l.Command!.Name = "resolved-a"; return Task.FromResult(l); }, - new CodeLensRegistrationOptions { + (_, _) => new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -85,7 +85,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l.Command!.Name = "resolved-b"; return Task.FromResult(l); }, - new CodeLensRegistrationOptions { + (_, _) => new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -107,7 +107,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l.Command!.Name = "resolved-c"; return Task.FromResult(l); }, - new CodeLensRegistrationOptions { + (_, _) => new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -129,7 +129,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l.Command!.Name = "resolved-d"; return Task.FromResult(l); }, - new CodeLensRegistrationOptions { + (_, _) => new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ); @@ -182,7 +182,7 @@ public async Task Should_Resolve_With_Data_Capability() lens.Command!.Name = "resolved"; return Task.FromResult(lens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -200,7 +200,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer, capability, token) => { var a = new CodeLensContainer( new CodeLens { @@ -228,7 +228,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -271,7 +271,7 @@ public async Task Should_Resolve_With_Data_CancellationToken() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -289,7 +289,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer, token) => { var a = new CodeLensContainer( new CodeLens { @@ -317,7 +317,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -360,7 +360,7 @@ public async Task Should_Resolve_With_Data() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -378,7 +378,7 @@ public async Task Should_Resolve_With_Partial_Data() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer) => { var a = new CodeLensContainer( new CodeLens { @@ -406,7 +406,7 @@ public async Task Should_Resolve_With_Partial_Data() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -440,7 +440,7 @@ public async Task Should_Resolve_Capability() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -458,7 +458,7 @@ public async Task Should_Resolve_Partial_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer, capability, token) => { var a = new CodeLensContainer( new CodeLens { @@ -476,7 +476,7 @@ public async Task Should_Resolve_Partial_Capability() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -509,7 +509,7 @@ public async Task Should_Resolve_CancellationToken() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -527,7 +527,7 @@ public async Task Should_Resolve_Partial_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer, token) => { var a = new CodeLensContainer( new CodeLens { @@ -545,7 +545,7 @@ public async Task Should_Resolve_Partial_CancellationToken() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -578,7 +578,7 @@ public async Task Should_Resolve() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); @@ -596,7 +596,7 @@ public async Task Should_Resolve_Partial() { var (client, _) = await Initialize( options => { }, options => { - options.OnCodeLens( + options.ObserveCodeLens( (codeLensParams, observer) => { var a = new CodeLensContainer( new CodeLens { @@ -614,7 +614,7 @@ public async Task Should_Resolve_Partial() codeLens.Command!.Name = "resolved"; return Task.FromResult(codeLens); }, - new CodeLensRegistrationOptions() + (_, _) => new CodeLensRegistrationOptions() ); } ); diff --git a/test/Lsp.Tests/Integration/TypedCompletionTests.cs b/test/Lsp.Tests/Integration/TypedCompletionTests.cs index 706a7ad68..523c0164c 100644 --- a/test/Lsp.Tests/Integration/TypedCompletionTests.cs +++ b/test/Lsp.Tests/Integration/TypedCompletionTests.cs @@ -60,7 +60,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem.Command!.Name = "resolved-a"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -85,7 +85,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem.Command!.Name = "resolved-b"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -107,7 +107,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem.Command!.Name = "resolved-c"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -129,7 +129,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem.Command!.Name = "resolved-d"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions { + (_, _) => new CompletionRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ); @@ -182,7 +182,7 @@ public async Task Should_Resolve_With_Data_Capability() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -200,7 +200,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer, capability, token) => { var a = new CompletionList( new CompletionItem { @@ -228,7 +228,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -271,7 +271,7 @@ public async Task Should_Resolve_With_Data_CancellationToken() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -289,7 +289,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer, token) => { var a = new CompletionList( new CompletionItem { @@ -317,7 +317,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -360,7 +360,7 @@ public async Task Should_Resolve_With_Data() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -378,7 +378,7 @@ public async Task Should_Resolve_With_Partial_Data() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer) => { var a = new CompletionList( new CompletionItem { @@ -406,7 +406,7 @@ public async Task Should_Resolve_With_Partial_Data() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -440,7 +440,7 @@ public async Task Should_Resolve_Capability() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -458,7 +458,7 @@ public async Task Should_Resolve_Partial_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer, capability, token) => { var a = new CompletionList( new CompletionItem { @@ -476,7 +476,7 @@ public async Task Should_Resolve_Partial_Capability() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -509,7 +509,7 @@ public async Task Should_Resolve_CancellationToken() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -527,7 +527,7 @@ public async Task Should_Resolve_Partial_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer, token) => { var a = new CompletionList( new CompletionItem { @@ -545,7 +545,7 @@ public async Task Should_Resolve_Partial_CancellationToken() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -578,7 +578,7 @@ public async Task Should_Resolve() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); @@ -596,7 +596,7 @@ public async Task Should_Resolve_Partial() { var (client, _) = await Initialize( options => { }, options => { - options.OnCompletion( + options.ObserveCompletion( (completionParams, observer) => { var a = new CompletionList( new CompletionItem { @@ -614,7 +614,7 @@ public async Task Should_Resolve_Partial() completionItem.Detail = "resolved"; return Task.FromResult(completionItem); }, - new CompletionRegistrationOptions() + (_, _) => new CompletionRegistrationOptions() ); } ); diff --git a/test/Lsp.Tests/Integration/TypedDocumentLinkTests.cs b/test/Lsp.Tests/Integration/TypedDocumentLinkTests.cs index 3fe3300b8..05c13c9c1 100644 --- a/test/Lsp.Tests/Integration/TypedDocumentLinkTests.cs +++ b/test/Lsp.Tests/Integration/TypedDocumentLinkTests.cs @@ -55,7 +55,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink.Tooltip = "resolved-a"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions { + (_, _) => new DocumentLinkRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -77,7 +77,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink.Tooltip = "resolved-b"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions { + (_, _) => new DocumentLinkRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -96,7 +96,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink.Tooltip = "resolved-c"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions { + (_, _) => new DocumentLinkRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") } ); @@ -115,7 +115,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink.Tooltip = "resolved-d"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions { + (_, _) => new DocumentLinkRegistrationOptions { DocumentSelector = DocumentSelector.ForLanguage("vb") } ); @@ -165,7 +165,7 @@ public async Task Should_Resolve_With_Data_Capability() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -183,7 +183,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer, capability, token) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -208,7 +208,7 @@ public async Task Should_Resolve_With_Partial_Data_Capability() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -248,7 +248,7 @@ public async Task Should_Resolve_With_Data_CancellationToken() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -266,7 +266,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer, token) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -291,7 +291,7 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -331,7 +331,7 @@ public async Task Should_Resolve_With_Data() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -349,7 +349,7 @@ public async Task Should_Resolve_With_Partial_Data() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -374,7 +374,7 @@ public async Task Should_Resolve_With_Partial_Data() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -405,7 +405,7 @@ public async Task Should_Resolve_Capability() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -423,7 +423,7 @@ public async Task Should_Resolve_Partial_Capability() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer, capability, token) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -438,7 +438,7 @@ public async Task Should_Resolve_Partial_Capability() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -468,7 +468,7 @@ public async Task Should_Resolve_CancellationToken() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -486,7 +486,7 @@ public async Task Should_Resolve_Partial_CancellationToken() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer, token) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -501,7 +501,7 @@ public async Task Should_Resolve_Partial_CancellationToken() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -531,7 +531,7 @@ public async Task Should_Resolve() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); @@ -549,7 +549,7 @@ public async Task Should_Resolve_Partial() { var (client, _) = await Initialize( options => { }, options => { - options.OnDocumentLink( + options.ObserveDocumentLink( (documentLinkParams, observer) => { var a = new DocumentLinkContainer( new DocumentLink { @@ -564,7 +564,7 @@ public async Task Should_Resolve_Partial() documentLink.Tooltip = "resolved"; return Task.FromResult(documentLink); }, - new DocumentLinkRegistrationOptions() + (_, _) => new DocumentLinkRegistrationOptions() ); } ); diff --git a/test/Lsp.Tests/Lsp.Tests.csproj b/test/Lsp.Tests/Lsp.Tests.csproj index 07539c929..0d749a9cf 100644 --- a/test/Lsp.Tests/Lsp.Tests.csproj +++ b/test/Lsp.Tests/Lsp.Tests.csproj @@ -4,13 +4,6 @@ true AnyCPU - - true - $(BaseIntermediateOutputPath)\GeneratedFiles - - - - diff --git a/test/Lsp.Tests/LspRequestRouterTests.cs b/test/Lsp.Tests/LspRequestRouterTests.cs index 62b36493d..1774e5f28 100644 --- a/test/Lsp.Tests/LspRequestRouterTests.cs +++ b/test/Lsp.Tests/LspRequestRouterTests.cs @@ -104,6 +104,7 @@ public async Task ShouldRouteToCorrect_Notification_WithManyHandlers() ) ) { textDocumentSyncHandler, textDocumentSyncHandler2 }; + collection.Initialize(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); AutoSubstitute.Provide(new TextDocumentMatcher(LoggerFactory.CreateLogger(), textDocumentIdentifiers)); @@ -135,7 +136,7 @@ public async Task ShouldRouteToCorrect_Request() .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions().Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CommandOrCodeActionContainer()); @@ -183,7 +184,7 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers() .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions().Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CommandOrCodeActionContainer()); @@ -195,7 +196,7 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers() .Returns(new CommandOrCodeActionContainer()); registry.OnCodeAction( codeActionDelegate, - new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") } + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") } ); var textDocumentIdentifiers = new TextDocumentIdentifiers(); @@ -245,13 +246,13 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers_CodeLensHandler( .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions().Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CodeLensContainer()); var codeActionHandler2 = Substitute.For(); - codeActionHandler2.GetRegistrationOptions().Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") }); + codeActionHandler2.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") }); codeActionHandler2 .Handle(Arg.Any(), Arg.Any()) .Returns(new CodeLensContainer()); @@ -268,6 +269,7 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers_CodeLensHandler( ) ) { textDocumentSyncHandler, textDocumentSyncHandler2, codeActionHandler, codeActionHandler2 }; + collection.Initialize(); AutoSubstitute.Provide(collection); AutoSubstitute.Provide>(collection); AutoSubstitute.Provide(new TextDocumentMatcher(LoggerFactory.CreateLogger(), tdi)); diff --git a/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs b/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs index 65ce6f8b3..c438d8b8a 100644 --- a/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/ExecuteCommandHandlerMatcherTests.cs @@ -61,6 +61,7 @@ public void Should_Return_Handler_Descriptor() new ExecuteCommandParams { Command = "Command" }, new List { new LspHandlerDescriptor( + 0, "workspace/executeCommand", "Key", executeCommandHandler, @@ -68,7 +69,6 @@ public void Should_Return_Handler_Descriptor() typeof(ExecuteCommandParams), typeof(ExecuteCommandRegistrationOptions), registrationsOptions, - () => true, typeof(ExecuteCommandCapability), null, () => { }, diff --git a/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs b/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs index add3fd3ef..d708e4115 100644 --- a/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/ResolveCommandMatcherTests.cs @@ -62,6 +62,7 @@ public void Should_Not_Throw_Given_Another_Descriptor() // Given var resolveHandler = Substitute.For(); var handlerDescriptor = new LspHandlerDescriptor( + 0, TextDocumentNames.CodeLens, "Key", resolveHandler, @@ -69,7 +70,6 @@ public void Should_Not_Throw_Given_Another_Descriptor() typeof(CodeLensParams), null, null, - () => false, null, null, () => { }, @@ -102,6 +102,7 @@ public void Should_Return_CodeLensResolve_Descriptor() }, new List { new LspHandlerDescriptor( + 0, TextDocumentNames.CodeLensResolve, "Key", resolveHandler!, @@ -109,13 +110,13 @@ public void Should_Return_CodeLensResolve_Descriptor() typeof(CodeLens), null, null, - () => false, null, null, () => { }, Substitute.For() ), new LspHandlerDescriptor( + 0, TextDocumentNames.CodeLensResolve, "Key2", resolveHandler2, @@ -123,7 +124,6 @@ public void Should_Return_CodeLensResolve_Descriptor() typeof(CodeLens), null, null, - () => false, null, null, () => { }, @@ -150,6 +150,7 @@ public void Should_Handle_Null_Data() new CompletionItem(), new List { new LspHandlerDescriptor( + 0, TextDocumentNames.CompletionResolve, "Key", resolveHandler, @@ -157,7 +158,6 @@ public void Should_Handle_Null_Data() typeof(CompletionItem), null, null, - () => false, null, null, () => { }, @@ -188,6 +188,7 @@ public void Should_Return_CompletionResolve_Descriptor() }, new List { new LspHandlerDescriptor( + 0, TextDocumentNames.CompletionResolve, "Key", resolveHandler!, @@ -195,13 +196,13 @@ public void Should_Return_CompletionResolve_Descriptor() typeof(CompletionItem), null, null, - () => false, null, null, () => { }, Substitute.For() ), new LspHandlerDescriptor( + 0, TextDocumentNames.CompletionResolve, "Key2", resolveHandler2!, @@ -209,7 +210,6 @@ public void Should_Return_CompletionResolve_Descriptor() typeof(CompletionItem), null, null, - () => false, null, null, () => { }, @@ -237,6 +237,7 @@ public async Task Should_Update_CompletionItems_With_HandlerType() ); ( resolveHandler as ICanBeIdentifiedHandler )?.Id.Returns(_trueId); var descriptor = new LspHandlerDescriptor( + 0, TextDocumentNames.Completion, "Key", (resolveHandler as IJsonRpcHandler)!, @@ -244,7 +245,6 @@ public async Task Should_Update_CompletionItems_With_HandlerType() typeof(CompletionParams), null, null, - () => false, null, null, () => { }, @@ -287,6 +287,7 @@ public async Task Should_Update_CodeLensContainer_With_HandlerType() ); ( resolveHandler as ICanBeIdentifiedHandler )?.Id.Returns(_trueId); var descriptor = new LspHandlerDescriptor( + 0, TextDocumentNames.CodeLens, "Key", (resolveHandler as IJsonRpcHandler)!, @@ -294,7 +295,6 @@ public async Task Should_Update_CodeLensContainer_With_HandlerType() typeof(CodeLensParams), null, null, - () => false, null, null, () => { }, @@ -337,6 +337,7 @@ public async Task Should_Update_CodeLens_Removing_HandlerType() ); ( resolveHandler as ICanBeIdentifiedHandler )?.Id.Returns(_trueId); var descriptor = new LspHandlerDescriptor( + 0, TextDocumentNames.CodeLensResolve, "Key", (resolveHandler as IJsonRpcHandler)!, @@ -344,7 +345,6 @@ public async Task Should_Update_CodeLens_Removing_HandlerType() typeof(CodeLens), null, null, - () => false, null, null, () => { }, diff --git a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs index d9f72ab0a..ee8554c42 100644 --- a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs @@ -6,6 +6,7 @@ using NSubstitute; using OmniSharp.Extensions.LanguageServer.Client; using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; @@ -14,6 +15,7 @@ using OmniSharp.Extensions.LanguageServer.Shared; using Xunit; using Xunit.Abstractions; +using Arg = NSubstitute.Arg; namespace Lsp.Tests.Matchers { @@ -217,7 +219,7 @@ public void Should_Return_Code_Lens_Descriptor() var handlerMatcher = AutoSubstitute.Resolve(); var codeLensHandler = (ICodeLensHandler) Substitute.For(new[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]); - codeLensHandler.GetRegistrationOptions() + codeLensHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.cs" }) @@ -225,13 +227,14 @@ public void Should_Return_Code_Lens_Descriptor() ); var codeLensHandler2 = (ICodeLensHandler) Substitute.For(new[] { typeof(ICodeLensHandler), typeof(ICodeLensResolveHandler) }, new object[0]); - codeLensHandler2.GetRegistrationOptions() + codeLensHandler2.GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.cake" }) } ); collection.Add(codeLensHandler, codeLensHandler2); + collection.Initialize(); // When var result = handlerMatcher.FindHandler( @@ -262,7 +265,7 @@ public void Should_Return_Did_Folding_Range_handler() var textDocumentSyncHandler = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.ps*1"), "powershell"); var handler = Substitute.For(); - handler.GetRegistrationOptions().Returns( + handler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns( new FoldingRangeRegistrationOptions { DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.ps*1" }) } diff --git a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs index 15c3df0ed..0b4e8c6a2 100644 --- a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs +++ b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs @@ -39,7 +39,7 @@ public async Task RequestsCancellation() textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()).Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions().Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns( diff --git a/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests_$SimpleTest.json index 332e1a12c..410ad3f2c 100644 --- a/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests_$SimpleTest.json @@ -9,7 +9,6 @@ "source.organizeImports" ], "resolveProvider": false, - "workDoneProgress": false, "documentSelector": [ { "language": "csharp", @@ -21,5 +20,6 @@ "scheme": "scheme", "pattern": "pattern" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests_$SimpleTest.json index 15e81928a..783fcf765 100644 --- a/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests_$SimpleTest.json @@ -1,6 +1,5 @@ { "resolveProvider": true, - "workDoneProgress": false, "documentSelector": [ { "language": "csharp", @@ -12,5 +11,6 @@ "scheme": "scheme", "pattern": "pattern" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests_$SimpleTest.json index 00cc34774..d7c3fde10 100644 --- a/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests_$SimpleTest.json @@ -3,10 +3,10 @@ "triggerCharacters": [ "." ], - "workDoneProgress": false, "documentSelector": [ { "language": "csharp" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests_$SimpleTest.json index 975ed30ea..0a1f03e65 100644 --- a/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests_$SimpleTest.json @@ -1,9 +1,9 @@ { "resolveProvider": true, - "workDoneProgress": false, "documentSelector": [ { "language": "csharp" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests_$SimpleTest.json index c496034fb..65761c1db 100644 --- a/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests_$SimpleTest.json @@ -4,10 +4,10 @@ "1", "2" ], - "workDoneProgress": false, "documentSelector": [ { "language": "csharp" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/InitializeResultTests.cs b/test/Lsp.Tests/Models/InitializeResultTests.cs index a195a91e3..174d75043 100644 --- a/test/Lsp.Tests/Models/InitializeResultTests.cs +++ b/test/Lsp.Tests/Models/InitializeResultTests.cs @@ -83,26 +83,21 @@ public void BooleanOrTest(string expected) } }, ColorProvider = new DocumentColorRegistrationOptions.StaticOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.foo"), Id = "foo" }, DeclarationProvider = new DeclarationRegistrationOptions.StaticOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.foo"), Id = "foo" }, FoldingRangeProvider = new FoldingRangeRegistrationOptions.StaticOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.foo"), Id = "foo" }, ImplementationProvider = new ImplementationRegistrationOptions.StaticOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.foo"), Id = "foo" }, RenameProvider = new RenameRegistrationOptions.StaticOptions { PrepareProvider = true }, TypeDefinitionProvider = new TypeDefinitionRegistrationOptions.StaticOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.foo"), Id = "foo" } } diff --git a/test/Lsp.Tests/Models/InitializeResultTests_$BooleanOrTest.json b/test/Lsp.Tests/Models/InitializeResultTests_$BooleanOrTest.json index 0a93cb342..abf2085a4 100644 --- a/test/Lsp.Tests/Models/InitializeResultTests_$BooleanOrTest.json +++ b/test/Lsp.Tests/Models/InitializeResultTests_$BooleanOrTest.json @@ -14,48 +14,23 @@ "experimental": {}, "typeDefinitionProvider": { "workDoneProgress": false, - "id": "foo", - "documentSelector": [ - { - "pattern": "**/*.foo" - } - ] + "id": "foo" }, "implementationProvider": { "workDoneProgress": false, - "id": "foo", - "documentSelector": [ - { - "pattern": "**/*.foo" - } - ] + "id": "foo" }, "colorProvider": { "workDoneProgress": false, - "id": "foo", - "documentSelector": [ - { - "pattern": "**/*.foo" - } - ] + "id": "foo" }, "foldingRangeProvider": { "workDoneProgress": false, - "id": "foo", - "documentSelector": [ - { - "pattern": "**/*.foo" - } - ] + "id": "foo" }, "declarationProvider": { "workDoneProgress": false, - "id": "foo", - "documentSelector": [ - { - "pattern": "**/*.foo" - } - ] + "id": "foo" } } } diff --git a/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests_$SimpleTest.json index 69c513f5a..d8000d59e 100644 --- a/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests_$SimpleTest.json +++ b/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests_$SimpleTest.json @@ -3,10 +3,10 @@ "a", "b" ], - "workDoneProgress": false, "documentSelector": [ { "language": "csharp" } - ] + ], + "workDoneProgress": false } diff --git a/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests.cs deleted file mode 100644 index 0b8c1ae51..000000000 --- a/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using FluentAssertions; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using Xunit; - -namespace Lsp.Tests.Models -{ - public class TextDocumentRegistrationOptionsTests - { - [Theory] - [JsonFixture] - public void SimpleTest(string expected) - { - var model = new TextDocumentRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { - Language = "csharp" - } - ) - }; - var result = Fixture.SerializeObject(model); - - result.Should().Be(expected); - - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); - deresult.Should().BeEquivalentTo(model); - } - } -} diff --git a/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests_$SimpleTest.json b/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests_$SimpleTest.json deleted file mode 100644 index abb741073..000000000 --- a/test/Lsp.Tests/Models/TextDocumentRegistrationOptionsTests_$SimpleTest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "documentSelector": [ - { - "language": "csharp" - } - ] -} \ No newline at end of file diff --git a/test/Lsp.Tests/SupportedCapabilitiesFixture.cs b/test/Lsp.Tests/SupportedCapabilitiesFixture.cs index 4b075296d..030681472 100644 --- a/test/Lsp.Tests/SupportedCapabilitiesFixture.cs +++ b/test/Lsp.Tests/SupportedCapabilitiesFixture.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Shared; namespace Lsp.Tests { @@ -12,7 +14,7 @@ public class SupportedCapabilitiesFixture public static readonly ISupportedCapabilities AlwaysTrue = new AlwaysTrueSupportedCapabilities(); public static readonly ISupportedCapabilities AlwaysFalse = new AlwaysFalseSupportedCapabilities(); - private class AlwaysTrueSupportedCapabilities : ISupportedCapabilities + private class AlwaysTrueSupportedCapabilities : SupportedCapabilitiesBase, ISupportedCapabilities { // ReSharper disable once UnusedParameter.Local // ReSharper disable once UnusedMember.Local @@ -20,18 +22,14 @@ private class AlwaysTrueSupportedCapabilities : ISupportedCapabilities public bool AllowsDynamicRegistration(Type capabilityType) => true; - public void SetCapability(ILspHandlerDescriptor descriptor, IJsonRpcHandler handler) + protected override bool TryGetCapability(Type capabilityType, [NotNullWhen(true)] out object? capability) { + capability = Activator.CreateInstance(capabilityType); + return true; } - - public void Add(IEnumerable supports) - { - } - - public void Add(ICapability capability) {} } - private class AlwaysFalseSupportedCapabilities : ISupportedCapabilities + private class AlwaysFalseSupportedCapabilities : SupportedCapabilitiesBase, ISupportedCapabilities { // ReSharper disable once UnusedParameter.Local // ReSharper disable once UnusedMember.Local @@ -39,15 +37,11 @@ private class AlwaysFalseSupportedCapabilities : ISupportedCapabilities public bool AllowsDynamicRegistration(Type capabilityType) => false; - public void SetCapability(ILspHandlerDescriptor descriptor, IJsonRpcHandler handler) + protected override bool TryGetCapability(Type capabilityType, [NotNullWhen(true)] out object? capability) { + capability = null; + return false; } - - public void Add(IEnumerable supports) - { - } - - public void Add(ICapability capability) {} } } } diff --git a/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs b/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs index 4fe2e3658..b4b3aa289 100644 --- a/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs +++ b/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs @@ -1,5 +1,6 @@ using NSubstitute; using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -12,10 +13,10 @@ public static ITextDocumentSyncHandler With(DocumentSelector documentSelector, s public static ITextDocumentSyncHandler With(this ITextDocumentSyncHandler handler, DocumentSelector documentSelector, string language) { - ( (IDidChangeTextDocumentHandler) handler ).GetRegistrationOptions().Returns(new TextDocumentChangeRegistrationOptions { DocumentSelector = documentSelector }); - ( (IDidOpenTextDocumentHandler) handler ).GetRegistrationOptions().Returns(new TextDocumentRegistrationOptions { DocumentSelector = documentSelector }); - ( (IDidCloseTextDocumentHandler) handler ).GetRegistrationOptions().Returns(new TextDocumentRegistrationOptions { DocumentSelector = documentSelector }); - ( (IDidSaveTextDocumentHandler) handler ).GetRegistrationOptions().Returns(new TextDocumentSaveRegistrationOptions { DocumentSelector = documentSelector }); + ( (IDidChangeTextDocumentHandler) handler ).GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new TextDocumentChangeRegistrationOptions() { DocumentSelector = documentSelector }); + ( (IDidOpenTextDocumentHandler) handler ).GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new TextDocumentOpenRegistrationOptions() { DocumentSelector = documentSelector }); + ( (IDidCloseTextDocumentHandler) handler ).GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new TextDocumentCloseRegistrationOptions() { DocumentSelector = documentSelector }); + ( (IDidSaveTextDocumentHandler) handler ).GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new TextDocumentSaveRegistrationOptions() { DocumentSelector = documentSelector }); handler.GetTextDocumentAttributes(Arg.Any()) .Returns(c => new TextDocumentAttributes(c.Arg(), language)); diff --git a/test/TestingUtils/RetryTheoryAttribute.cs b/test/TestingUtils/RetryTheoryAttribute.cs index 93ec88d75..7c5c214c5 100644 --- a/test/TestingUtils/RetryTheoryAttribute.cs +++ b/test/TestingUtils/RetryTheoryAttribute.cs @@ -1,6 +1,8 @@ // See https://github.com/JoshKeegan/xRetry using System; +using System.Linq; +using System.Reflection; using Xunit.Sdk; namespace TestingUtils @@ -17,4 +19,15 @@ public class RetryTheoryAttribute : RetryFactAttribute public RetryTheoryAttribute(int maxRetries = 3, int delayBetweenRetriesMs = 0) : base(maxRetries, delayBetweenRetriesMs) { } } + + public static class NSubstituteExtensions + { + public static object Protected(this object target, string name, params object[] args) + { + var type = target.GetType(); + var method = type + .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Single(x => x.Name == name && x.IsVirtual); + return method.Invoke(target, args); + } + } } diff --git a/test/coverlet.runsettings b/test/coverlet.runsettings new file mode 100644 index 000000000..b13b639e4 --- /dev/null +++ b/test/coverlet.runsettings @@ -0,0 +1,14 @@ + + + + + + json,lcov,cobertura,opencover + [Bogus*]*,[Autofac*]*,[FakeItEasy*]*,[Moq*]*,[xunit*]*,[Microsoft.*]*,[XunitXml*]*,[coverlet.*]*,[System.*]*,[*]JetBrains.Annotations* + [Omnisharp.*]* + Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute + + + + +