diff --git a/.build/.build.csproj b/.build/.build.csproj index 509faac59..b158ccf34 100644 --- a/.build/.build.csproj +++ b/.build/.build.csproj @@ -11,7 +11,6 @@ - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c9be2115..ec11fff2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@v4.0.0 with: clean: 'false' fetch-depth: '0' @@ -117,7 +117,7 @@ jobs: run: | dotnet nuke Pack --skip - name: 🐿 Publish Coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v4.0.0-beta.2 with: name: 'actions-${{ matrix.os }}' - name: 🏺 Publish logs diff --git a/.github/workflows/close-milestone.yml b/.github/workflows/close-milestone.yml index 48c4ed612..5bdb84908 100644 --- a/.github/workflows/close-milestone.yml +++ b/.github/workflows/close-milestone.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@v4.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index da4198773..279a744f2 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@v4.0.0 with: fetch-depth: 0 diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index dd03f5704..6b8e1de71 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@v4.0.0 - name: Run Labeler if: success() diff --git a/.github/workflows/update-milestone.yml b/.github/workflows/update-milestone.yml index ebdb54332..f881a2ada 100644 --- a/.github/workflows/update-milestone.yml +++ b/.github/workflows/update-milestone.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@v4.0.0 with: ref: ${{ github.sha }} fetch-depth: 0 diff --git a/.gitignore b/.gitignore index f2f6f24b6..99a0f4a92 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ coverage.info /codealike.json .tmp/ .nuke/temp/ +**/*.received.cs diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index f99d257e6..470cfeef1 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -37,6 +37,7 @@ "AppVeyor", "AzurePipelines", "Bamboo", + "Bitbucket", "Bitrise", "GitHubActions", "GitLab", diff --git a/Directory.Packages.props b/Directory.Packages.props index d3ac5d926..201d01aac 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -35,11 +35,13 @@ - + + + diff --git a/LSP.sln b/LSP.sln index 68d6c34bf..82baf3397 100644 --- a/LSP.sln +++ b/LSP.sln @@ -6,6 +6,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D764E024-3D3 ProjectSection(SolutionItems) = preProject src\Directory.Build.props = src\Directory.Build.props src\Directory.Build.targets = src\Directory.Build.targets + src\.editorconfig = src\.editorconfig EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2F323ED5-EBF8-45E1-B9D3-C014561B3DDA}" @@ -38,6 +39,8 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleServer", "sample\SampleServer\SampleServer.csproj", "{F2067F5F-FA4E-4990-B301-E7898FC4C45F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{A316FCEC-81AD-45FB-93EE-C62CA09300DC}" + ProjectSection(SolutionItems) = preProject + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "src\Client\Client.csproj", "{417E95B2-5AB9-49D5-B7CD-12255472E2E7}" EndProject @@ -53,8 +56,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dap.Server", "src\Dap.Serve EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = ".build", ".build\.build.csproj", "{28B13787-A442-4D28-BF9A-3D65BF13AAEC}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{26522B49-0743-4CBE-BA67-6D17FF65CAB9}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "src\Shared\Shared.csproj", "{18FB2302-023B-4F6F-9F6D-099B47B69D9F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dap.Tests", "test\Dap.Tests\Dap.Tests.csproj", "{6D9E5BF4-4666-476B-AC88-D108A80567F6}" @@ -81,6 +82,67 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Protocol.Proposals", "src\P EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lsp.Integration.Tests", "test\Lsp.Integration.Tests\Lsp.Integration.Tests.csproj", "{72A74595-A278-46F0-9C8B-3151C9681B91}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{93A0F406-2CEB-491E-9F40-6DA1BA67DD7C}" + ProjectSection(SolutionItems) = preProject + .config\dotnet-tools.json = .config\dotnet-tools.json + Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props + Directory.Packages.supports.props = Directory.Packages.supports.props + Directory.Build.targets = Directory.Build.targets + .editorconfig = .editorconfig + build.cmd = build.cmd + build.sh = build.sh + build.ps1 = build.ps1 + GitReleaseManager.yaml = GitReleaseManager.yaml + .codecov.yml = .codecov.yml + .azure-pipelines.yml = .azure-pipelines.yml + .appveyor.yml = .appveyor.yml + azure-pipelines.nuke.yml = azure-pipelines.nuke.yml + GitVersion.yml = GitVersion.yml + .travis.yml = .travis.yml + LICENSE = LICENSE + README.md = README.md + .gitignore = .gitignore + .gitattributes = .gitattributes + .prettierignore = .prettierignore + .prettierrc = .prettierrc + .lintstagedrc.js = .lintstagedrc.js + NuGet.config = NuGet.config + package.json = package.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{19909559-F753-4337-952B-A8B5B5889959}" + ProjectSection(SolutionItems) = preProject + .github\labels.yml = .github\labels.yml + .github\renovate.json = .github\renovate.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{97924298-E17E-46E6-83CC-D9CD3B9F5E6F}" + ProjectSection(SolutionItems) = preProject + .github\workflows\ci-ignore.yml = .github\workflows\ci-ignore.yml + .github\workflows\draft-release.yml = .github\workflows\draft-release.yml + .github\workflows\publish-nuget.yml = .github\workflows\publish-nuget.yml + .github\workflows\dependabot-merge.yml = .github\workflows\dependabot-merge.yml + .github\workflows\sync-labels.yml = .github\workflows\sync-labels.yml + .github\workflows\close-milestone.yml = .github\workflows\close-milestone.yml + .github\workflows\update-milestone.yml = .github\workflows\update-milestone.yml + .github\workflows\ci.yml = .github\workflows\ci.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".husky", ".husky", "{BED6765C-97D8-406D-B782-3307132D16F0}" + ProjectSection(SolutionItems) = preProject + .husky\pre-commit = .husky\pre-commit + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vscode", ".vscode", "{09BE8ED9-1986-40F3-A9A6-D826A7413581}" + ProjectSection(SolutionItems) = preProject + .vscode\settings.json = .vscode\settings.json + .vscode\csharp.code-snippets = .vscode\csharp.code-snippets + .vscode\launch.json = .vscode\launch.json + .vscode\tasks.json.old = .vscode\tasks.json.old + .vscode\tasks.json = .vscode\tasks.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -388,7 +450,7 @@ Global {E540868F-438E-4F7F-BBB7-010D6CB18A57} = {D764E024-3D3F-4112-B932-2DB722A1BACC} {F2C9D555-118E-442B-A953-9A7B58A53F33} = {D764E024-3D3F-4112-B932-2DB722A1BACC} {E1A9123B-A236-4240-8C82-A61BD85C3BF4} = {D764E024-3D3F-4112-B932-2DB722A1BACC} - {28B13787-A442-4D28-BF9A-3D65BF13AAEC} = {26522B49-0743-4CBE-BA67-6D17FF65CAB9} + {28B13787-A442-4D28-BF9A-3D65BF13AAEC} = {93A0F406-2CEB-491E-9F40-6DA1BA67DD7C} {18FB2302-023B-4F6F-9F6D-099B47B69D9F} = {D764E024-3D3F-4112-B932-2DB722A1BACC} {6D9E5BF4-4666-476B-AC88-D108A80567F6} = {2F323ED5-EBF8-45E1-B9D3-C014561B3DDA} {678A4DD2-A656-4DCC-AE78-F9940C82A6E6} = {D764E024-3D3F-4112-B932-2DB722A1BACC} @@ -402,6 +464,10 @@ Global {D43637CC-94E6-4ED4-BAA3-E5D1AD3285F5} = {D764E024-3D3F-4112-B932-2DB722A1BACC} {201B1CA7-AB12-41AD-9246-BC30F2EBE2DF} = {D764E024-3D3F-4112-B932-2DB722A1BACC} {72A74595-A278-46F0-9C8B-3151C9681B91} = {2F323ED5-EBF8-45E1-B9D3-C014561B3DDA} + {19909559-F753-4337-952B-A8B5B5889959} = {93A0F406-2CEB-491E-9F40-6DA1BA67DD7C} + {97924298-E17E-46E6-83CC-D9CD3B9F5E6F} = {19909559-F753-4337-952B-A8B5B5889959} + {BED6765C-97D8-406D-B782-3307132D16F0} = {93A0F406-2CEB-491E-9F40-6DA1BA67DD7C} + {09BE8ED9-1986-40F3-A9A6-D826A7413581} = {93A0F406-2CEB-491E-9F40-6DA1BA67DD7C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D38DD0EC-D095-4BCD-B8AF-2D788AF3B9AE} diff --git a/global.json b/global.json index 8c21be6de..e46b1d265 100644 --- a/global.json +++ b/global.json @@ -3,4 +3,4 @@ "version": "6.0.414", "rollForward": "latestMinor" } -} +} \ No newline at end of file diff --git a/language-server-protocol.sha.txt b/language-server-protocol.sha.txt index 98fc9b305..f1d289146 100644 --- a/language-server-protocol.sha.txt +++ b/language-server-protocol.sha.txt @@ -1,4 +1,5 @@ -- This is the last commit we caught up with https://github.com/Microsoft/language-server-protocol/commits/gh-pages -lastSha: bdcc0f2 +lastSha: 5fc92456c046ed980646bb95c1d2e390d5b3ef9d + +https://github.com/Microsoft/language-server-protocol/compare/5fc92456c046ed980646bb95c1d2e390d5b3ef9d..gh-pages -https://github.com/Microsoft/language-server-protocol/compare/bdcc0f2..gh-pages diff --git a/sample/SampleServer/FoldingRangeHandler.cs b/sample/SampleServer/FoldingRangeHandler.cs index f885fe33f..54214784d 100644 --- a/sample/SampleServer/FoldingRangeHandler.cs +++ b/sample/SampleServer/FoldingRangeHandler.cs @@ -10,7 +10,7 @@ internal class FoldingRangeHandler : IFoldingRangeHandler { public FoldingRangeRegistrationOptions GetRegistrationOptions() => new FoldingRangeRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp") + DocumentSelector = TextDocumentSelector.ForLanguage("csharp") }; public Task?> Handle( @@ -30,7 +30,7 @@ CancellationToken cancellationToken ); public FoldingRangeRegistrationOptions GetRegistrationOptions(FoldingRangeCapability capability, ClientCapabilities clientCapabilities) => new FoldingRangeRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp") + DocumentSelector = TextDocumentSelector.ForLanguage("csharp") }; } } diff --git a/sample/SampleServer/SampleServer.csproj b/sample/SampleServer/SampleServer.csproj index c7a131ab7..0300dcca5 100644 --- a/sample/SampleServer/SampleServer.csproj +++ b/sample/SampleServer/SampleServer.csproj @@ -10,16 +10,10 @@ - - - - - - - - - - + + + + diff --git a/sample/SampleServer/SemanticTokensHandler.cs b/sample/SampleServer/SemanticTokensHandler.cs index a95635c3d..0f8c3d517 100644 --- a/sample/SampleServer/SemanticTokensHandler.cs +++ b/sample/SampleServer/SemanticTokensHandler.cs @@ -95,7 +95,7 @@ protected override SemanticTokensRegistrationOptions CreateRegistrationOptions( { return new SemanticTokensRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp"), + DocumentSelector = TextDocumentSelector.ForLanguage("csharp"), Legend = new SemanticTokensLegend { TokenModifiers = capability.TokenModifiers, diff --git a/sample/SampleServer/TextDocumentHandler.cs b/sample/SampleServer/TextDocumentHandler.cs index f3b6f9c2f..e9a06b74a 100644 --- a/sample/SampleServer/TextDocumentHandler.cs +++ b/sample/SampleServer/TextDocumentHandler.cs @@ -25,8 +25,8 @@ internal class TextDocumentHandler : TextDocumentSyncHandlerBase private readonly ILogger _logger; private readonly ILanguageServerConfiguration _configuration; - private readonly DocumentSelector _documentSelector = new DocumentSelector( - new DocumentFilter { + private readonly TextDocumentSelector _textDocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Pattern = "**/*.cs" } ); @@ -69,8 +69,8 @@ public override Task Handle(DidCloseTextDocumentParams notification, Cance public override Task Handle(DidSaveTextDocumentParams notification, CancellationToken token) => Unit.Task; - protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) => new TextDocumentSyncRegistrationOptions() { - DocumentSelector = _documentSelector, + protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions(TextSynchronizationCapability capability, ClientCapabilities clientCapabilities) => new TextDocumentSyncRegistrationOptions() { + DocumentSelector = _textDocumentSelector, Change = Change, Save = new SaveOptions() { IncludeText = true } }; @@ -129,7 +129,7 @@ CancellationToken cancellationToken } public DocumentSymbolRegistrationOptions GetRegistrationOptions(DocumentSymbolCapability capability, ClientCapabilities clientCapabilities) => new DocumentSymbolRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp") + DocumentSelector = TextDocumentSelector.ForLanguage("csharp") }; } @@ -146,7 +146,7 @@ public MyWorkspaceSymbolsHandler(IServerWorkDoneManager serverWorkDoneManager, I _logger = logger; } - public async Task> Handle( + public async Task> Handle( WorkspaceSymbolParams request, CancellationToken cancellationToken ) @@ -190,9 +190,8 @@ CancellationToken cancellationToken partialResults.OnNext( new[] { - new SymbolInformation { + new WorkspaceSymbol { ContainerName = "Partial Container", - Deprecated = true, Kind = SymbolKind.Constant, Location = new Location { Range = new Range( @@ -221,15 +220,14 @@ CancellationToken cancellationToken ); partialResults.OnCompleted(); - return new SymbolInformation[] { }; + return new WorkspaceSymbol[] { }; } try { return new[] { - new SymbolInformation { + new WorkspaceSymbol { ContainerName = "Container", - Deprecated = true, Kind = SymbolKind.Constant, Location = new Location { Range = new Range( diff --git a/src/Client/DefaultLanguageClientFacade.cs b/src/Client/DefaultLanguageClientFacade.cs index d5ae45489..cab0129d2 100644 --- a/src/Client/DefaultLanguageClientFacade.cs +++ b/src/Client/DefaultLanguageClientFacade.cs @@ -13,6 +13,7 @@ namespace OmniSharp.Extensions.LanguageServer.Client internal class DefaultLanguageClientFacade : LanguageProtocolProxy, ILanguageClientFacade, IOnLanguageClientStarted { private readonly Lazy _textDocument; + private readonly Lazy _notebookDocument; private readonly Lazy _client; private readonly Lazy _general; private readonly Lazy _window; @@ -28,6 +29,7 @@ public DefaultLanguageClientFacade( IProgressManager progressManager, ILanguageProtocolSettings languageProtocolSettings, Lazy textDocument, + Lazy notebookDocument, Lazy client, Lazy general, Lazy window, @@ -38,6 +40,7 @@ IInsanceHasStarted instanceHasStarted ) : base(requestRouter, resolverContext, progressManager, languageProtocolSettings) { _textDocument = textDocument; + _notebookDocument = notebookDocument; _client = client; _general = general; _window = window; @@ -48,6 +51,7 @@ IInsanceHasStarted instanceHasStarted } public ITextDocumentLanguageClient TextDocument => _textDocument.Value; + public INotebookDocumentLanguageClient NotebookDocument => _notebookDocument.Value; public IClientLanguageClient Client => _client.Value; public IGeneralLanguageClient General => _general.Value; public IWindowLanguageClient Window => _window.Value; diff --git a/src/Client/LanguageClient.cs b/src/Client/LanguageClient.cs index 633634784..22c7004df 100644 --- a/src/Client/LanguageClient.cs +++ b/src/Client/LanguageClient.cs @@ -177,6 +177,7 @@ internal LanguageClient( IEnumerable startedDelegates, IEnumerable startedHandlers, ITextDocumentLanguageClient textDocumentLanguageClient, + INotebookDocumentLanguageClient notebookDocumentLanguageClient, IClientLanguageClient clientLanguageClient, IGeneralLanguageClient generalLanguageClient, IWindowLanguageClient windowLanguageClient, @@ -228,6 +229,7 @@ IScheduler scheduler // We need to at least create Window here in case any handler does loggin in their constructor TextDocument = textDocumentLanguageClient; + NotebookDocument = notebookDocumentLanguageClient; Client = clientLanguageClient; General = generalLanguageClient; Window = windowLanguageClient; @@ -235,6 +237,7 @@ IScheduler scheduler } public ITextDocumentLanguageClient TextDocument { get; } + public INotebookDocumentLanguageClient NotebookDocument { get; } public IClientLanguageClient Client { get; } public IGeneralLanguageClient General { get; } public IWindowLanguageClient Window { get; } diff --git a/src/Client/LanguageClientRegistrationManager.cs b/src/Client/LanguageClientRegistrationManager.cs index b6703e4c3..19bcfc48e 100644 --- a/src/Client/LanguageClientRegistrationManager.cs +++ b/src/Client/LanguageClientRegistrationManager.cs @@ -180,14 +180,14 @@ public IObservable> Registrations public IEnumerable GetRegistrationsForMethod(string method) => _registrations.Select(z => z.Value).Where(x => x.Method == method); - public IEnumerable GetRegistrationsMatchingSelector(DocumentSelector documentSelector) => + public IEnumerable GetRegistrationsMatchingSelector(TextDocumentSelector textDocumentSelector) => _registrations .Select(z => z.Value) .Where( x => x.RegisterOptions is ITextDocumentRegistrationOptions { DocumentSelector: { } } ro && ro.DocumentSelector .Join( - documentSelector, + textDocumentSelector, z => z.HasLanguage ? z.Language : z.HasScheme ? z.Scheme : z.HasPattern ? z.Pattern : string.Empty, diff --git a/src/Client/LanguageClientServiceCollectionExtensions.cs b/src/Client/LanguageClientServiceCollectionExtensions.cs index a0e3c8b3c..cb0433cbf 100644 --- a/src/Client/LanguageClientServiceCollectionExtensions.cs +++ b/src/Client/LanguageClientServiceCollectionExtensions.cs @@ -44,6 +44,9 @@ internal static IContainer AddLanguageClientInternals(this IContainer container, container.RegisterMany( serviceTypeCondition: type => type.Name.Contains(nameof(TextDocumentLanguageClient)), reuse: Reuse.Singleton ); + container.RegisterMany( + serviceTypeCondition: type => type.Name.Contains(nameof(NotebookDocumentLanguageClient)), reuse: Reuse.Singleton + ); container.RegisterMany( serviceTypeCondition: type => type.Name.Contains(nameof(ClientLanguageClient)), reuse: Reuse.Singleton ); diff --git a/src/Dap.Protocol/Dap.Protocol.csproj b/src/Dap.Protocol/Dap.Protocol.csproj index 4622960c4..52c4b5467 100644 --- a/src/Dap.Protocol/Dap.Protocol.csproj +++ b/src/Dap.Protocol/Dap.Protocol.csproj @@ -14,35 +14,24 @@ - + - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Server, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Server, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f diff --git a/src/JsonRpc.Generators/ActionContextExtensions.cs b/src/JsonRpc.Generators/ActionContextExtensions.cs index f555d9dc4..1c6df349f 100644 --- a/src/JsonRpc.Generators/ActionContextExtensions.cs +++ b/src/JsonRpc.Generators/ActionContextExtensions.cs @@ -1,6 +1,7 @@ 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 { @@ -8,12 +9,12 @@ static class ActionContextExtensions { public static ParameterListSyntax GetRegistryParameterList(this ExtensionMethodContext extensionMethodContext) { - return SyntaxFactory.ParameterList( - SyntaxFactory.SeparatedList( + return ParameterList( + SeparatedList( new[] { - SyntaxFactory.Parameter(SyntaxFactory.Identifier("registry")) + Parameter(Identifier("registry")) .WithType(extensionMethodContext.Item) - .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ThisKeyword))) + .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))) } ) ); diff --git a/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs b/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs index c9eac05da..45b3f9f94 100644 --- a/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs +++ b/src/JsonRpc.Generators/AutoImplementParamsGenerator.cs @@ -16,7 +16,7 @@ public class AutoImplementParamsGenerator : IIncrementalGenerator public void Initialize(IncrementalGeneratorInitializationContext context) { var _attributes = "Method,RegistrationOptions"; - var _interfaces = "IPartialItemsRequest,IPartialItemRequest,IWorkDoneProgressParams,IHandlerIdentity"; + var _interfaces = "IPartialItemsRequest,IPartialItemsWithInitialValueRequest,IPartialItemRequest,IPartialItemWithInitialValueRequest,IWorkDoneProgressParams,IHandlerIdentity"; var syntaxProvider = context.SyntaxProvider.CreateSyntaxProvider( (syntaxNode, _) => @@ -102,7 +102,7 @@ private static IEnumerable AutoImplementInterfaces(Base .WithAccessorList(GetInitAccessor); } - if (syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName() is "IPartialItemsRequest" or "IPartialItemRequest") == true + if (syntax.BaseList?.Types.Any(z => z.Type.GetSyntaxName() is "IPartialItemsRequest" or "IPartialItemRequest" or "IPartialItemsWithInitialValueRequest" or "IPartialItemWithInitialValueRequest") == true && symbol.GetMembers("PartialResultToken").IsEmpty) { yield return PropertyDeclaration(NullableType(IdentifierName("ProgressToken")), Identifier("PartialResultToken")) diff --git a/src/JsonRpc.Generators/Contexts/GeneratorData.cs b/src/JsonRpc.Generators/Contexts/GeneratorData.cs index 33cffce86..f83292bda 100644 --- a/src/JsonRpc.Generators/Contexts/GeneratorData.cs +++ b/src/JsonRpc.Generators/Contexts/GeneratorData.cs @@ -43,6 +43,7 @@ HashSet additionalUsings if (IsRequest(candidateClass)) { var responseType = GetResponseType(candidateClass, symbol); + var (partialItem, inheritsFromSelf) = GetPartialItem(candidateClass, symbol, requestType, compilation); return new RequestItem( candidateClass, symbol, @@ -54,8 +55,10 @@ HashSet additionalUsings responseType.Syntax.GetSyntaxName() == "Unit", GetCapability(candidateClass, symbol, lspAttributes), GetRegistrationOptions(candidateClass, symbol, lspAttributes), - GetPartialItem(candidateClass, symbol, requestType), + partialItem, GetPartialItems(candidateClass, symbol, requestType), + symbol.AllInterfaces.Concat(requestType.Symbol.AllInterfaces).Any(z => z.Name.EndsWith("WithInitialValue", StringComparison.Ordinal)), + inheritsFromSelf, additionalUsings, new List(), model, compilation diff --git a/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs b/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs index 28b59670c..226500e35 100644 --- a/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs +++ b/src/JsonRpc.Generators/Contexts/RegistrationOptionAttributes.cs @@ -11,11 +11,13 @@ internal record RegistrationOptionAttributes( string? Key, ExpressionSyntax[]? KeyExpression, bool SupportsWorkDoneProgress, - bool SupportsDocumentSelector, + bool SupportsTextDocumentSelector, + bool SupportsNotebookDocumentSelector, bool SupportsStaticRegistrationOptions, SyntaxSymbol? RegistrationOptionsConverter, bool ImplementsWorkDoneProgress, - bool ImplementsDocumentSelector, + bool ImplementsTextDocumentSelector, + bool ImplementsNotebookDocumentSelector, bool ImplementsStaticRegistrationOptions ) { @@ -28,24 +30,33 @@ bool ImplementsStaticRegistrationOptions // var registrationOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions"); var textDocumentRegistrationOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions"); + var notebookDocumentRegistrationOptionsInterfaceSymbol = + compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.INotebookDocumentRegistrationOptions"); var workDoneProgressOptionsInterfaceSymbol = compilation.GetTypeByMetadataName("OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions"); var staticRegistrationOptionsInterfaceSymbol = 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; + if (data.ApplicationSyntaxReference?.GetSyntax() is not AttributeSyntax attributeSyntax) return null; TypeSyntax? converterSyntax = null; ITypeSymbol? converter = null; - var supportsDocumentSelector = data.NamedArguments.Any(z => z is { Key: nameof(SupportsDocumentSelector), Value: { Value: true } }) + var supportsTextDocumentSelector = data.NamedArguments.Any(z => z is { Key: nameof(SupportsTextDocumentSelector), 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 supportsNotebookDocumentSelector = data.NamedArguments.Any(z => z is { Key: nameof(SupportsNotebookDocumentSelector), Value: { Value: true } }) + || ( symbol.AllInterfaces.Length > 0 && symbol.AllInterfaces.Any( + z => SymbolEqualityComparer.Default.Equals(z, notebookDocumentRegistrationOptionsInterfaceSymbol) + ) ) + || ( notebookDocumentRegistrationOptionsInterfaceSymbol is { } && syntax.BaseList?.Types.Any( + type => type.Type.GetSyntaxName()?.Contains(notebookDocumentRegistrationOptionsInterfaceSymbol.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) @@ -135,7 +146,8 @@ static IEnumerable getStringExpressionSyntaxes(AttributeArgume value, valueExpressionSyntaxes, supportsWorkDoneProgress, - supportsDocumentSelector, + supportsTextDocumentSelector, + supportsNotebookDocumentSelector, supportsStaticRegistrationOptions, converterSyntax is null ? null : new SyntaxSymbol(converterSyntax, (INamedTypeSymbol)converter!), symbol @@ -156,6 +168,15 @@ static IEnumerable getStringExpressionSyntaxes(AttributeArgume .AsEnumerable() .Any(x => SymbolEqualityComparer.Default.Equals(z, x)) == true ), + symbol + .GetMembers() + .AsEnumerable() + .All( + z => notebookDocumentRegistrationOptionsInterfaceSymbol? + .GetMembers() + .AsEnumerable() + .Any(x => SymbolEqualityComparer.Default.Equals(z, x)) == true + ), symbol .GetMembers() .AsEnumerable() diff --git a/src/JsonRpc.Generators/Contexts/RequestItem.cs b/src/JsonRpc.Generators/Contexts/RequestItem.cs index 3b5103243..5d3af252e 100644 --- a/src/JsonRpc.Generators/Contexts/RequestItem.cs +++ b/src/JsonRpc.Generators/Contexts/RequestItem.cs @@ -17,6 +17,8 @@ record RequestItem( SyntaxSymbol? RegistrationOptions, SyntaxSymbol? PartialItem, SyntaxSymbol? PartialItems, + bool PartialHasInitialValue, + bool PartialItemInheritsFromSelf, HashSet AdditionalUsings, List AssemblyJsonRpcHandlersAttributeArguments, SemanticModel Model, diff --git a/src/JsonRpc.Generators/DelegateHelpers.cs b/src/JsonRpc.Generators/DelegateHelpers.cs index 677afcaab..cd82c89ff 100644 --- a/src/JsonRpc.Generators/DelegateHelpers.cs +++ b/src/JsonRpc.Generators/DelegateHelpers.cs @@ -29,25 +29,25 @@ public static Func MakeGenericFactory(Func< ); } - public static Func MakeGenericFactory( - Func factory, TypeSyntax 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))) - ) - ); + return (syntax, resolveSyntax, initialValueHandler) => factory(syntax, resolveSyntax, initialValueHandler) + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) + .WithConstraintClauses( + SingletonList( + TypeParameterConstraintClause(IdentifierName("T")) + .WithConstraints(SingletonSeparatedList(TypeConstraint(constraint))) + ) + ); } - public static Func> MakeGenericFactory( - Func> factory, TypeSyntax constraint + public static Func> MakeGenericFactory( + Func> factory, TypeSyntax constraint ) { - return (syntax, resolveSyntax) => factory(syntax, resolveSyntax) + return (syntax, resolveSyntax, initialValueHandler) => factory(syntax, resolveSyntax, initialValueHandler) .Select( method => method .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter(Identifier("T"))))) diff --git a/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs b/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs index 51e875466..24cfc1473 100644 --- a/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs +++ b/src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs @@ -48,12 +48,19 @@ syntaxNode is TypeDeclarationSyntax tds actionItem = GeneratorData.Create( compilaiton, (TypeDeclarationSyntax)syntaxContext.Node, syntaxContext.SemanticModel, additionalUsings ); + if (actionItem is null) + { + diagnostic = Diagnostic.Create( + GeneratorDiagnostics.MustBeARequestOrNotification, syntaxContext.Node.GetLocation(), + ( (TypeDeclarationSyntax)syntaxContext.Node ).Identifier.Text + ); + } } catch (Exception e) { diagnostic = Diagnostic.Create( GeneratorDiagnostics.Exception, syntaxContext.Node.GetLocation(), e.Message, - e.StackTrace ?? string.Empty + e.StackTrace?.Replace("\n", " ") ?? string.Empty, e.ToString() ); Debug.WriteLine(e); Debug.WriteLine(e.StackTrace); @@ -81,7 +88,7 @@ private void GenerateHandlerMethods( if (actionItem is null) { - context.ReportDiagnostic(diagnostic!); + if (diagnostic is { }) context.ReportDiagnostic(diagnostic); return; } @@ -99,7 +106,7 @@ private void GenerateHandlerMethods( context.ReportDiagnostic( Diagnostic.Create( GeneratorDiagnostics.Exception, candidateClass.GetLocation(), - $"Strategy {strategy.GetType().FullName} failed!" + " - " + e.Message, e.StackTrace ?? string.Empty + $"Strategy {strategy.GetType().FullName} failed!" + " - " + e.Message, e.StackTrace?.Replace("\n", " ") ?? string.Empty ) ); Debug.WriteLine($"Strategy {strategy.GetType().FullName} failed!"); @@ -194,11 +201,14 @@ private static ImmutableArray GetCompilationU new OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy(false), new OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy(true), new OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy(), +// new OnRequestTypedMethodGeneratorWithoutRegistrationOptionsStrategy(), new OnRequestMethodGeneratorWithRegistrationOptionsStrategy(false), new OnRequestMethodGeneratorWithRegistrationOptionsStrategy(true), new OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy(), +// new OnRequestTypedMethodGeneratorWithRegistrationOptionsStrategy(), new SendMethodNotificationStrategy(), - new SendMethodRequestStrategy() + new SendMethodRequestStrategy()/*, + new SendMethodTypedResolveRequestStrategy()*/ ); var actionStrategies = ImmutableArray.Create( new EnsureNamespaceStrategy(), diff --git a/src/JsonRpc.Generators/GeneratorDiagnostics.cs b/src/JsonRpc.Generators/GeneratorDiagnostics.cs index b93e808c5..42ae8b41a 100644 --- a/src/JsonRpc.Generators/GeneratorDiagnostics.cs +++ b/src/JsonRpc.Generators/GeneratorDiagnostics.cs @@ -8,7 +8,11 @@ internal static class GeneratorDiagnostics { public static DiagnosticDescriptor Exception { get; } = new DiagnosticDescriptor( "JRPC0001", "Exception", - "{0} - {1}", "JRPC", DiagnosticSeverity.Error, true + "{0} - {1} {2}", "JRPC", DiagnosticSeverity.Error, true + ); + public static DiagnosticDescriptor ExceptionWarning { get; } = new DiagnosticDescriptor( + "JRPC0002", "Exception", + "{0} - {1} {2}", "JRPC", DiagnosticSeverity.Warning, true ); public static DiagnosticDescriptor NoHandlerRegistryProvided { get; } = new DiagnosticDescriptor( @@ -41,6 +45,11 @@ internal static class GeneratorDiagnostics "Type {0} must be made readonly.", "JsonRPC", DiagnosticSeverity.Error, true ); + public static DiagnosticDescriptor MustBeARequestOrNotification { get; } = new DiagnosticDescriptor( + "JRPC1006", "Type must implement a request or notification interface", + "Type {0} must implement a request or notification interface.", "JsonRPC", DiagnosticSeverity.Error, true + ); + public static DiagnosticDescriptor MustInheritFromCanBeResolved { get; } = new DiagnosticDescriptor( "LSP1001", "The target class must implement ICanBeResolved", "The target class must implement ICanBeResolved", "LSP", DiagnosticSeverity.Error, true diff --git a/src/JsonRpc.Generators/Helpers.cs b/src/JsonRpc.Generators/Helpers.cs index f7559140d..7ce048f46 100644 --- a/src/JsonRpc.Generators/Helpers.cs +++ b/src/JsonRpc.Generators/Helpers.cs @@ -30,8 +30,8 @@ public static bool IsRequest(TypeDeclarationSyntax symbol) => 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: "IPartialItemRequest" or "IPartialItemWithInitialValueRequest" }, Arity: 2 } + or { Identifier: { Text: "IPartialItemsRequest" or "IPartialItemsWithInitialValueRequest" }, Arity: 2 } or { Identifier: { Text: "IRequest" }, Arity: 1 } or { Identifier: { Text: "IJsonRpcRequest" }, Arity: 0 } ) @@ -51,15 +51,18 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT TypeSyntax? type = null!; foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) { - 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 + 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" or "IPartialItemWithInitialValueRequest" }, Arity: 2 } => gns.TypeArgumentList.Arguments[0], + { Identifier: { Text: "IPartialItemsRequest" or "IPartialItemsWithInitialValueRequest" }, Arity: 2 } => gns.TypeArgumentList.Arguments + [0], + { Identifier: { Text: "IRequest" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0], + _ => null }, SimpleNameSyntax and { Identifier: { Text: "IRequest" } } => ParseName("MediatR.Unit"), SimpleNameSyntax and { Identifier: { Text: "IJsonRpcRequest" } } => ParseName("MediatR.Unit"), @@ -89,7 +92,8 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT .OfType() .FirstOrDefault()?.Type; } - else if (syntax.BaseList?.Types.Select(z => z.Type).OfType().Any(z => z.Identifier.Text == "IRequest" || z.Identifier.Text == "IJsonRpcRequest") + 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); @@ -98,17 +102,23 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT { foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) { - type = baseType.Type switch { - GenericNameSyntax gns => gns switch { + 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" }, Arity: 1 } => IdentifierName(syntax.Identifier.Text), - { Identifier: { Text: "IRequest" }, Arity: 0 } => IdentifierName(syntax.Identifier.Text), - { Identifier: { Text: "IJsonRpcRequest" } } => IdentifierName(syntax.Identifier.Text), - { Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } => IdentifierName(syntax.Identifier.Text), - { Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } => IdentifierName(syntax.Identifier.Text), - _ => null, + { Identifier: { Text: "IRequest" }, Arity: 1 } => IdentifierName(syntax.Identifier.Text), + { Identifier: { Text: "IRequest" }, Arity: 0 } => IdentifierName(syntax.Identifier.Text), + { Identifier: { Text: "IJsonRpcRequest" } } => IdentifierName(syntax.Identifier.Text), + { Identifier: { Text: "IPartialItemRequest" or "IPartialItemWithInitialValueRequest" }, Arity: 2 } => IdentifierName( + syntax.Identifier.Text + ), + { Identifier: { Text: "IPartialItemsRequest" or "IPartialItemsWithInitialValueRequest" }, Arity: 2 } => IdentifierName( + syntax.Identifier.Text + ), + _ => null, }, _ => null, }; @@ -150,8 +160,10 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT TypeSyntax? type = null!; foreach (var baseType in syntax.BaseList?.Types.AsEnumerable() ?? Array.Empty()) { - type = baseType.Type switch { - GenericNameSyntax gns => gns switch { + 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 @@ -190,9 +202,10 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT 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 + type = baseType.Type switch + { + GenericNameSyntax gns and { Identifier: { Text: "IRegistration" }, Arity: > 0 } => gns.TypeArgumentList.Arguments[0], + _ => null }; if (type != null) break; } @@ -222,35 +235,42 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT public static SyntaxSymbol? GetPartialItems(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType) { - var handlerInterface = symbol.AllInterfaces - .FirstOrDefault(z => z.Name == "IPartialItems" && z.TypeArguments.Length == 1) - ?? requestType.Symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IPartialItems" && z.TypeArguments.Length == 1); + var handlerInterface = symbol.AllInterfaces.Concat(requestType.Symbol.AllInterfaces).FirstOrDefault( + z => z is { Name: "IPartialItems", TypeArguments.Length: 1 } or { Name: "IPartialItemsWithInitialValue", TypeArguments.Length: 2 } + ); 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) + .Where(z => z is { Identifier.Text: "IPartialItemsRequest" or "IPartialItemsWithInitialValueRequest", Arity: 2 }) .Select(z => z!.TypeArgumentList.Arguments[1]) .FirstOrDefault(); return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol); } - public static SyntaxSymbol? GetPartialItem(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType) + public static (SyntaxSymbol? partialItem, bool inheritsFromSelf) GetPartialItem( + TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType, Compilation compilation + ) { - 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 handlerInterface = symbol.AllInterfaces.Concat(requestType.Symbol.AllInterfaces) + .FirstOrDefault( + z => z is { Name: "IPartialItem", TypeArguments.Length: 1 } or + { Name: "IPartialItemWithInitialValue", TypeArguments.Length: 2 } + ); var localSymbol = handlerInterface?.TypeArguments[0] as INamedTypeSymbol; - if (localSymbol == null) return null; + if (localSymbol == null) return ( null, false ); 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) + .Where(z => z is { Identifier.Text: "IPartialItemRequest" or "IPartialItemWithInitialValueRequest", Arity: 2 }) .Select(z => z!.TypeArgumentList.Arguments[1]) .FirstOrDefault(); - return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol); + return ( + new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol), + handlerInterface!.TypeArguments.Length == 2 && compilation.HasImplicitConversion(handlerInterface!.TypeArguments[1], handlerInterface.TypeArguments[0]) + ); } public static NameSyntax ResolveTypeName(ITypeSymbol symbol) @@ -270,12 +290,16 @@ public static NameSyntax ResolveTypeName(ITypeSymbol symbol) return IdentifierName(symbol.Name); } - public static GenericNameSyntax CreatePartialAction(TypeSyntax requestType, TypeSyntax partialType, bool withCancellationToken, params TypeSyntax[] types) + public static GenericNameSyntax CreatePartialAction( + TypeSyntax requestType, TypeSyntax partialType, bool withCancellationToken, params TypeSyntax[] types + ) { - var typeArguments = new List { + var typeArguments = new List + { requestType, GenericName("IObserver").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { partialType }))), }; + typeArguments.AddRange(types); if (withCancellationToken) { @@ -286,7 +310,9 @@ public static GenericNameSyntax CreatePartialAction(TypeSyntax requestType, Type .WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments))); } - public static ExpressionStatementSyntax EnsureRegistrationOptionsIsSet(NameSyntax registrationOptionsName, TypeSyntax registrationOptionsType, bool hasCapability) => + public static ExpressionStatementSyntax EnsureRegistrationOptionsIsSet( + NameSyntax registrationOptionsName, TypeSyntax registrationOptionsType, bool hasCapability + ) => ExpressionStatement( AssignmentExpression( SyntaxKind.CoalesceAssignmentExpression, @@ -322,31 +348,39 @@ public static InvocationExpressionSyntax AddHandler(ExpressionSyntax syntax, par private static ArgumentListSyntax GetHandlerArgumentList() => ArgumentList( SeparatedList( - new[] { + new[] + { HandlerArgument } ) ); public static ArgumentListSyntax GetRegistrationHandlerArgumentList( - TypeSyntax registrationOptionsName, TypeSyntax registrationType, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType, bool includeId + TypeSyntax registrationOptionsName, TypeSyntax registrationType, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument, + TypeSyntax? capabilityType, bool includeId ) => ArgumentList( SeparatedList( - includeId - ? new[] { + ( includeId + ? new[] + { Argument(IdentifierName("id")), + initialArgument!, handlerArgument, Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)) } - : new[] { + : new[] + { + initialArgument!, handlerArgument, Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)) - } + } ) + .Where(z => z is not null) ) ); public static ArgumentSyntax HandlerArgument = Argument(IdentifierName("handler")); + public static ArgumentSyntax InitialHandlerArgument = Argument(IdentifierName("initialHandler")); public static ArgumentSyntax ResolveHandlerArgument = Argument(IdentifierName("resolveHandler")); public static ArgumentSyntax GetHandlerAdapterArgument( @@ -393,55 +427,62 @@ public static InvocationExpressionSyntax GetRegistrationOptionsAdapter( .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(registrationOptionsName)))); } - private static ArgumentListSyntax GetPartialResultArgumentList(TypeSyntax responseName, ArgumentSyntax handlerArgument) => - ArgumentList( - SeparatedList( - new[] { - handlerArgument, - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("_"), - GenericName(Identifier("GetService")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) - ) - ) - ), - Argument( + private static SeparatedSyntaxList GetPartialResultArgumentList( + TypeSyntax responseName, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument + ) => + SeparatedList( + new[] + { + initialArgument!, + handlerArgument, + Argument( + InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - responseName.EnsureNotNullable(), - IdentifierName("From") + IdentifierName("_"), + GenericName(Identifier("GetService")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) ) ) - } - ) - ); + ), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + responseName.EnsureNotNullable(), + IdentifierName("From") + ) + ) + }.Where(z => z is not null) + )!; - private static ArgumentListSyntax GetPartialItemsArgumentList(TypeSyntax responseName, ArgumentSyntax handlerArgument) => + private static ArgumentListSyntax GetPartialItemsArgumentList( + TypeSyntax responseName, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument + ) => ArgumentList( SeparatedList( - new[] { - handlerArgument, - Argument( - InvocationExpression( + new[] + { + initialArgument!, + handlerArgument, + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("_"), + GenericName(Identifier("GetService")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) + ) + ) + ), + Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("_"), - GenericName(Identifier("GetService")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("IProgressManager")))) + responseName.EnsureNotNullable(), + IdentifierName("From") ) ) - ), - Argument( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - responseName.EnsureNotNullable(), - IdentifierName("From") - ) - ) - } + } + .Where(z => z is not null) ) ); @@ -456,7 +497,9 @@ public static ObjectCreationExpressionSyntax CreateHandlerArgument(NameSyntax cl 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) + public static ArrowExpressionClauseSyntax GetNotificationCapabilityHandlerExpression( + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax capabilityName + ) { return ArrowExpressionClause( AddHandler( @@ -540,7 +583,7 @@ TypeSyntax capability public static ArrowExpressionClauseSyntax GetPartialResultCapabilityHandlerExpression( ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax itemType, TypeSyntax responseType, - TypeSyntax capabilityName + TypeSyntax capabilityName, bool requestPartialHasInitialValue ) { return ArrowExpressionClause( @@ -553,20 +596,30 @@ TypeSyntax capabilityName ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResultCapability", + requestPartialHasInitialValue ? "PartialResultCapabilityWithInitialValue" : "PartialResultCapability", requestName, responseType, itemType, capabilityName ) .WithArgumentList( - GetPartialResultArgumentList( - responseType, - GetHandlerAdapterArgument( - TypeArgumentList(SeparatedList(new[] { requestName, itemType })), - HandlerArgument, - capabilityName, - true + ArgumentList( + GetPartialResultArgumentList( + responseType, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, itemType })), + HandlerArgument, + capabilityName, + true + ), + requestPartialHasInitialValue + ? GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, responseType })), + InitialHandlerArgument, + capabilityName, + false + ) + : null ) ) ) @@ -577,7 +630,7 @@ TypeSyntax capabilityName } public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression( - ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax partialItem, TypeSyntax responseType + ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax partialItem, TypeSyntax responseType, bool requestPartialHasInitialValue ) { return ArrowExpressionClause( @@ -590,12 +643,18 @@ public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression( ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResult", + requestPartialHasInitialValue ? "PartialResultWithInitialValue" : "PartialResult", requestName, responseType, partialItem ) - .WithArgumentList(GetPartialResultArgumentList(responseType, HandlerArgument)) + .WithArgumentList( + ArgumentList( + GetPartialResultArgumentList( + responseType, HandlerArgument, requestPartialHasInitialValue ? InitialHandlerArgument : null + ) + ) + ) ) ) ) @@ -604,7 +663,7 @@ public static ArrowExpressionClauseSyntax GetPartialResultHandlerExpression( public static ArrowExpressionClauseSyntax GetPartialResultsCapabilityHandlerExpression( ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax responseType, - TypeSyntax itemName, TypeSyntax capabilityName + TypeSyntax itemName, TypeSyntax capabilityName, bool requestPartialHasInitialValue ) { return ArrowExpressionClause( @@ -617,20 +676,30 @@ public static ArrowExpressionClauseSyntax GetPartialResultsCapabilityHandlerExpr ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResultsCapability", + requestPartialHasInitialValue ? "PartialResultsCapabilityWithInitialValue" : "PartialResultsCapability", requestName, responseType, itemName, capabilityName ) .WithArgumentList( - GetPartialResultArgumentList( - responseType, - GetHandlerAdapterArgument( - TypeArgumentList(SeparatedList(new[] { requestName, itemName })), - HandlerArgument, - capabilityName, - true + ArgumentList( + GetPartialResultArgumentList( + responseType, + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, itemName })), + HandlerArgument, + capabilityName, + true + ), + requestPartialHasInitialValue + ? GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, responseType })), + InitialHandlerArgument, + capabilityName, + false + ) + : null ) ) ) @@ -642,7 +711,7 @@ public static ArrowExpressionClauseSyntax GetPartialResultsCapabilityHandlerExpr public static ArrowExpressionClauseSyntax GetPartialResultsHandlerExpression( ExpressionSyntax nameExpression, TypeSyntax requestName, TypeSyntax itemName, - TypeSyntax responseType + TypeSyntax responseType, bool requestPartialHasInitialValue ) { return ArrowExpressionClause( @@ -655,7 +724,7 @@ TypeSyntax responseType ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResults", + requestPartialHasInitialValue ? "PartialResultsWithInitialValue" : "PartialResults", requestName, responseType, itemName @@ -668,7 +737,15 @@ TypeSyntax responseType HandlerArgument, null, true - ) + ), + requestPartialHasInitialValue + ? GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new[] { requestName, responseType })), + InitialHandlerArgument, + null, + false + ) + : null ) ) ) @@ -689,7 +766,8 @@ public static ArrowExpressionClauseSyntax GetNotificationHandlerExpression(Expre .WithArgumentList( ArgumentList( SeparatedList( - new SyntaxNodeOrToken[] { + new SyntaxNodeOrToken[] + { Argument(nameExpression), Token(SyntaxKind.CommaToken), Argument( @@ -723,7 +801,8 @@ ExpressionSyntax nameExpression .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(nameExpression), Argument( item.IsUnit @@ -773,7 +852,8 @@ public static ArrowExpressionClauseSyntax GetNotificationInvokeExpression() => .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName(@"request")) } ) @@ -793,7 +873,8 @@ public static ArrowExpressionClauseSyntax GetRequestInvokeExpression() => .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName(@"request")), Argument(IdentifierName("cancellationToken")) } @@ -802,39 +883,70 @@ public static ArrowExpressionClauseSyntax GetRequestInvokeExpression() => ) ); - public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(TypeSyntax responseType, TypeSyntax? partialItemType) + public static ArrowExpressionClauseSyntax GetRequestReturningInvokeExpression(ExpressionSyntax requestName, TypeSyntax responseType) => + ArrowExpressionClause( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("client"), + IdentifierName("SendRequest"))) + .WithArgumentList( + ArgumentList( + SeparatedList( + new []{ + Argument(requestName), + Argument((IdentifierName(@"request")))}))), + GenericName( + Identifier("Returning")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList(responseType))))) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + IdentifierName("cancellationToken"))))) + ); + + public static ArrowExpressionClauseSyntax GetPartialInvokeExpression( + TypeSyntax responseType, TypeSyntax? partialItemType, bool partialItemTypeInheritsFromSelf + ) { var realResponseType = responseType is NullableTypeSyntax nts ? nts.ElementType : responseType; var factoryArgument = Argument( - SimpleLambdaExpression( - Parameter(Identifier("value")), - ObjectCreationExpression(realResponseType) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("value"))))) + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + realResponseType.EnsureNotNullable(), + IdentifierName("From") ) ); - var arguments = new[] { - Argument( - IdentifierName(@"request") - ), + var arguments = new[] + { + Argument(IdentifierName(@"request")), factoryArgument, Argument(IdentifierName("cancellationToken")) }; - if (partialItemType is {}) + if (partialItemType is { } && !partialItemTypeInheritsFromSelf) { var realPartialItemType = partialItemType is NullableTypeSyntax nts2 ? nts2.ElementType : partialItemType; - arguments = new[] { + arguments = new[] + { arguments[0], arguments[1], Argument( - SimpleLambdaExpression( - Parameter(Identifier("value")), - ObjectCreationExpression(realPartialItemType) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("value"))))) + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + realPartialItemType.EnsureNotNullable(), + IdentifierName("From") ) ), arguments[2] }; } + return ArrowExpressionClause( InvocationExpression( MemberAccessExpression( @@ -893,14 +1005,17 @@ public static string SpecialCasedHandlerName(INamedTypeSymbol symbol) } public static SeparatedSyntaxList HandlerIdentityConstraint { get; } = SeparatedList( - new TypeParameterConstraintSyntax[] { + new TypeParameterConstraintSyntax[] + { ClassOrStructConstraint(SyntaxKind.ClassConstraint) .WithQuestionToken(Token(SyntaxKind.QuestionToken)), TypeConstraint(NullableType(IdentifierName("IHandlerIdentity"))), } ); - public static SyntaxList HandlerIdentityConstraintClause(bool withHandlerIdentity, IdentifierNameSyntax? openGenericType = null) + public static SyntaxList HandlerIdentityConstraintClause( + bool withHandlerIdentity, IdentifierNameSyntax? openGenericType = null + ) { if (!withHandlerIdentity) return SingletonList( @@ -946,7 +1061,8 @@ public static class CommonElements private static readonly Lazy GetSetAccessorLazy = LazyFactory.Create( () => AccessorList( List( - new[] { + new[] + { AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) } @@ -957,7 +1073,8 @@ public static class CommonElements private static readonly Lazy GetInitAccessorLazy = LazyFactory.Create( () => AccessorList( List( - new[] { + new[] + { AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), AccessorDeclaration(SyntaxKind.InitAccessorDeclaration) @@ -972,7 +1089,8 @@ public static class CommonElements private static readonly Lazy GetAccessorLazy = LazyFactory.Create( () => AccessorList( List( - new[] { + new[] + { AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) } ) @@ -989,7 +1107,8 @@ public static class SyntaxExtensions public static string? GetSyntaxName(this TypeSyntax typeSyntax) { - return typeSyntax switch { + return typeSyntax switch + { SimpleNameSyntax sns => sns.Identifier.Text, QualifiedNameSyntax qns => qns.Right.Identifier.Text, NullableTypeSyntax nts => nts.ElementType.GetSyntaxName() + "?", @@ -1091,19 +1210,25 @@ public static BaseMethodDeclarationSyntax MakeMethodNullable(this BaseMethodDecl if (syntax.ExpressionBody is not null) { - syntax = syntax.WithExpressionBody(syntax.ExpressionBody.WithExpression(syntax.ExpressionBody.Expression.InsideNullableSwitchExpression(identifierNameSyntax))); + 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())) + 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")), + QualifiedName( + QualifiedName(IdentifierName("System"), IdentifierName("Diagnostics")), IdentifierName("CodeAnalysis") + ), IdentifierName("NotNullIfNotNull") ) ) @@ -1130,7 +1255,9 @@ public static MethodDeclarationSyntax MakeMethodNullable(this MethodDeclarationS return ( MakeMethodNullable(syntax as BaseMethodDeclarationSyntax, identifierNameSyntax) as MethodDeclarationSyntax )!; } - public static ConversionOperatorDeclarationSyntax MakeMethodNullable(this ConversionOperatorDeclarationSyntax syntax, IdentifierNameSyntax identifierNameSyntax) + public static ConversionOperatorDeclarationSyntax MakeMethodNullable( + this ConversionOperatorDeclarationSyntax syntax, IdentifierNameSyntax identifierNameSyntax + ) { return ( MakeMethodNullable(syntax as BaseMethodDeclarationSyntax, identifierNameSyntax) as ConversionOperatorDeclarationSyntax )!; } @@ -1140,7 +1267,8 @@ public static SwitchExpressionSyntax InsideNullableSwitchExpression(this Express return SwitchExpression(name) .WithArms( SeparatedList( - new[] { + new[] + { SwitchExpressionArm( UnaryPattern(ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression))), creationExpression diff --git a/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs b/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs index 2c36fcf4f..fc3bfddf8 100644 --- a/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs +++ b/src/JsonRpc.Generators/RegistrationOptionsGenerator.cs @@ -23,8 +23,11 @@ public class RegistrationOptionsGenerator : IIncrementalGenerator }; private record AttributeData( - INamedTypeSymbol RegistrationOptionsInterfaceSymbol, INamedTypeSymbol TextDocumentRegistrationOptionsInterfaceSymbol, - INamedTypeSymbol WorkDoneProgressOptionsInterfaceSymbol, INamedTypeSymbol StaticRegistrationOptionsInterfaceSymbol + INamedTypeSymbol RegistrationOptionsInterfaceSymbol, + INamedTypeSymbol TextDocumentRegistrationOptionsInterfaceSymbol, + INamedTypeSymbol NotebookDocumentRegistrationOptionsInterfaceSymbol, + INamedTypeSymbol WorkDoneProgressOptionsInterfaceSymbol, + INamedTypeSymbol StaticRegistrationOptionsInterfaceSymbol ); public void Initialize(IncrementalGeneratorInitializationContext context) @@ -39,6 +42,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) compilation.GetTypeByMetadataName( "OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions" )!; + var notebookDocumentRegistrationOptionsInterfaceSymbol = + compilation.GetTypeByMetadataName( + "OmniSharp.Extensions.LanguageServer.Protocol.Models.INotebookDocumentRegistrationOptions" + )!; var workDoneProgressOptionsInterfaceSymbol = compilation.GetTypeByMetadataName( "OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions" @@ -48,8 +55,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) "OmniSharp.Extensions.LanguageServer.Protocol.Models.IStaticRegistrationOptions" )!; return new AttributeData( - registrationOptionsInterfaceSymbol, textDocumentRegistrationOptionsInterfaceSymbol, - workDoneProgressOptionsInterfaceSymbol, staticRegistrationOptionsInterfaceSymbol + registrationOptionsInterfaceSymbol, + textDocumentRegistrationOptionsInterfaceSymbol, + notebookDocumentRegistrationOptionsInterfaceSymbol, + workDoneProgressOptionsInterfaceSymbol, + staticRegistrationOptionsInterfaceSymbol ); } ); @@ -162,7 +172,7 @@ private void GenerateRegistrationOptions( staticRegistrationOptions = staticRegistrationOptions.AddAttributeLists(attributeList); } - if (data.SupportsDocumentSelector && !data.ImplementsDocumentSelector) + if (data.SupportsTextDocumentSelector && !data.ImplementsTextDocumentSelector) { if (registrationOptions.BaseList?.Types.Any( z => z.Type.ToFullString().Contains(attributes.TextDocumentRegistrationOptionsInterfaceSymbol.Name) @@ -174,7 +184,37 @@ private void GenerateRegistrationOptions( } extendedRegistrationOptions = extendedRegistrationOptions.AddMembers( - PropertyDeclaration(NullableType(IdentifierName("DocumentSelector")), Identifier("DocumentSelector")) + PropertyDeclaration(NullableType(IdentifierName("TextDocumentSelector")), 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 (data.SupportsNotebookDocumentSelector && !data.ImplementsNotebookDocumentSelector) + { + if (registrationOptions.BaseList?.Types.Any( + z => z.Type.ToFullString().Contains(attributes.NotebookDocumentRegistrationOptionsInterfaceSymbol.Name) + ) != true) + { + extendedRegistrationOptions = ExtendAndImplementInterface( + extendedRegistrationOptions, attributes.NotebookDocumentRegistrationOptionsInterfaceSymbol + ); + } + + extendedRegistrationOptions = extendedRegistrationOptions.AddMembers( + PropertyDeclaration(NullableType(IdentifierName("NotebookDocumentSelector")), Identifier("DocumentSelector")) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithAccessorList( AccessorList( @@ -272,7 +312,7 @@ private void GenerateRegistrationOptions( catch (Exception e) { context.ReportDiagnostic( - Diagnostic.Create(GeneratorDiagnostics.Exception, registrationOptions.GetLocation(), e.Message, e.StackTrace ?? string.Empty) + Diagnostic.Create(GeneratorDiagnostics.Exception, registrationOptions.GetLocation(), e.Message, e.StackTrace?.Replace("\n", " ") ?? string.Empty, e.ToString()) ); Debug.WriteLine(e); Debug.WriteLine(e.StackTrace); diff --git a/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs b/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs index 08a0b1368..b96ee20c0 100644 --- a/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs @@ -260,6 +260,30 @@ public IEnumerable Apply(SourceProductionContext contex } members.Add(handlerClass); + + if (resolver is { LspAttributes: { GenerateTypedData: true } }) + { + members.Add( + GenerateTypedPartialItemHandler( + handlerClass, + request, + resolver, + request.PartialItem + ) + ); + } + + if (request is { LspAttributes: { GenerateTypedData: true } }) + { + members.Add( + GenerateTypedPartialItemHandler( + handlerClass, + request, + request, + request.PartialItem + ) + ); + } } else if (request is { PartialItems: { } partialItems }) { @@ -297,7 +321,7 @@ public IEnumerable Apply(SourceProductionContext contex if (resolver is { LspAttributes: { GenerateTypedData: true } }) { members.Add( - GenerateTypedPartialHandler( + GenerateTypedPartialItemsHandler( handlerClass, request, resolver, @@ -309,7 +333,7 @@ public IEnumerable Apply(SourceProductionContext contex if (request is { LspAttributes: { GenerateTypedData: true } }) { members.Add( - GenerateTypedPartialHandler( + GenerateTypedPartialItemsHandler( handlerClass, request, request, @@ -401,7 +425,7 @@ private static TypeSyntax GetPartialResultBaseClass(RequestItem request, SyntaxS return QualifiedName( IdentifierName("AbstractHandlers"), - GenericName($"PartialResult{( onlyCapability ? "Capability" : "" )}") + GenericName($"PartialResult{( request.PartialHasInitialValue ? "WithInitialValue" : "" )}{( onlyCapability ? "Capability" : "" )}") .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) ); } @@ -423,7 +447,7 @@ private static TypeSyntax GetPartialResultsBaseClass(RequestItem request, Syntax return QualifiedName( IdentifierName("AbstractHandlers"), - GenericName($"PartialResults{( onlyCapability ? "Capability" : "" )}") + GenericName($"PartialResults{( request.PartialHasInitialValue ? "WithInitialValue" : "" )}{( onlyCapability ? "Capability" : "" )}") .WithTypeArgumentList(TypeArgumentList(SeparatedList(types))) ); } @@ -597,11 +621,11 @@ private static IEnumerable AddConstructors(RequestItem } } - private static TypeDeclarationSyntax GenerateTypedPartialHandler( + private static TypeDeclarationSyntax GenerateTypedPartialItemHandler( TypeDeclarationSyntax classDeclarationSyntax, RequestItem item, RequestItem resolver, - SyntaxSymbol partialItems + SyntaxSymbol partialItem ) { return ClassDeclaration(classDeclarationSyntax.Identifier) @@ -673,13 +697,8 @@ SyntaxSymbol partialItems GenericName(Identifier("IObserver")) .WithTypeArgumentList( TypeArgumentList( - SingletonSeparatedList( - GenericName(Identifier("IEnumerable")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(partialItems.Syntax))) - ) - ) - ) - ), + SingletonSeparatedList(partialItem.Syntax))) + ), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) } ) @@ -712,7 +731,7 @@ SyntaxSymbol partialItems ) ) ), - partialItems.Syntax + partialItem.Syntax } ) ) @@ -729,7 +748,7 @@ SyntaxSymbol partialItems Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - partialItems.Syntax, + partialItem.Syntax, IdentifierName("From") ) ) @@ -831,10 +850,6 @@ SyntaxSymbol partialItems .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( - GenericName(Identifier("IEnumerable")) - .WithTypeArgumentList( - TypeArgumentList( - SingletonSeparatedList( GenericName(Identifier(resolver.Request.Symbol.Name)) .WithTypeArgumentList( TypeArgumentList( @@ -843,9 +858,6 @@ SyntaxSymbol partialItems ) ) ) - ) - ) - ) ) ) ) @@ -899,21 +911,14 @@ SyntaxSymbol partialItems ); } - private static TypeDeclarationSyntax GenerateTypedHandler( + + private static TypeDeclarationSyntax GenerateTypedPartialItemsHandler( TypeDeclarationSyntax classDeclarationSyntax, RequestItem item, - RequestItem resolver + RequestItem resolver, + SyntaxSymbol partialItems ) { - 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) @@ -922,45 +927,74 @@ RequestItem resolver .AddMembers( ConstructorDeclaration(classDeclarationSyntax.Identifier) .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword))) - .WithParameterList(ParameterList(SingletonSeparatedList(Parameter(Identifier("id")).WithType(IdentifierName("Guid"))))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] { + Parameter(Identifier("id")).WithType(IdentifierName("Guid")), + Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager")) + } + ) + ) + ) .WithInitializer( ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, - ArgumentList(SingletonSeparatedList(Argument(IdentifierName("id")))) + 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( - SingletonSeparatedList( - Argument( - InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Guid"), IdentifierName("NewGuid")) + SeparatedList( + new[] { + Argument( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Guid"), IdentifierName("NewGuid")) + ) + ), + Argument( + IdentifierName("progressManager") ) - ) + } ) ) ) ) .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) - ) - ) + 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")) } ) @@ -968,101 +1002,137 @@ RequestItem resolver ) .WithExpressionBody( ArrowExpressionClause( - AwaitExpression( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - InvocationExpression(IdentifierName("HandleParams")) - .WithArgumentList( - ArgumentList( - SeparatedList( - new[] { - Argument(IdentifierName("request")), - Argument(IdentifierName("cancellationToken")) - } + InvocationExpression(IdentifierName("Handle")) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[] { + Argument(IdentifierName("request")), + Argument( + ObjectCreationExpression( + QualifiedName( + IdentifierName("LanguageProtocolDelegatingHandlers"), + GenericName( + Identifier("TypedPartialObserver") + ) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] { + 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") + ) + ) + } + ) + ) ) - ) ), - IdentifierName("ConfigureAwait") - ) - ) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument( - LiteralExpression( - SyntaxKind.FalseLiteralExpression - ) - ) - ) + Argument(IdentifierName("cancellationToken")) + } ) ) - ) + ) ) ) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), MethodDeclaration( - GenericName(Identifier("Task")).WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolver.Response.Syntax))), + 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) - ) + 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("request")).WithType(resolver.Request.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") + .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))) + ) ) - } ) ) - ), - IdentifierName("ConfigureAwait") - ) - ) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument( - LiteralExpression( - SyntaxKind.FalseLiteralExpression - ) ) - ) ) ) - ) + ), + ReturnStatement(IdentifierName("response")) ) - ) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + ), MethodDeclaration( - GenericName(Identifier("Task")) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(responseType))), - Identifier("HandleParams") + PredefinedType(Token(SyntaxKind.VoidKeyword)), + Identifier("Handle") ) .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))) .WithParameterList( @@ -1070,21 +1140,50 @@ RequestItem resolver 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) - ), + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), MethodDeclaration( GenericName(Identifier("Task")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( - GenericName(Identifier(resolver.Response.Symbol.Name)) - .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))) + GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) ) ) ), @@ -1097,9 +1196,14 @@ RequestItem resolver new[] { Parameter(Identifier("request")) .WithType( - GenericName(Identifier(resolver.Response.Symbol.Name)).WithTypeArgumentList( - TypeArgumentList(SingletonSeparatedList(IdentifierName("T"))) - ) + GenericName(Identifier(resolver.Request.Symbol.Name)) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName("T") + ) + ) + ) ), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) } @@ -1109,5 +1213,217 @@ RequestItem resolver .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) ); } + + private static TypeDeclarationSyntax GenerateTypedHandler( + TypeDeclarationSyntax 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")))); + } + + var typeDeclarationSyntax = 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)) + ); + return typeDeclarationSyntax; + } } } diff --git a/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs index b4f0324bc..925d615b3 100644 --- a/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -138,6 +138,7 @@ private static BlockSyntax GetNotificationRegistrationHandlerExpression( capabilityName, false ), + null, capabilityName, false ) diff --git a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs index 7ad741a03..b369106b4 100644 --- a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -44,9 +44,9 @@ public IEnumerable Apply(SourceProductionContext contex ) ); - if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri) + if (request is { Response.Symbol: ITypeParameterSymbol }) { - method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name)); + method = method.AddTypeParameterListParameters(TypeParameter(request.Response.Symbol.Name)); } if (request.IsUnit) @@ -65,24 +65,27 @@ public IEnumerable Apply(SourceProductionContext contex var methodFactory = MakeFactory( extensionMethodContext.GetRegistryParameterList(), registrationOptions.Syntax, - item.Capability?.Syntax + request.Capability?.Syntax, + request.PartialHasInitialValue ); 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)) + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + null ); yield return factory( CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax), - resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + null ); 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); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, false, IdentifierName("T")), null, null); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T")), null, null); } { @@ -90,13 +93,14 @@ public IEnumerable Apply(SourceProductionContext contex { 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + null ); if (allowDerivedRequests) { var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); - yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T"), capability.Syntax), null); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T"), capability.Syntax), null, null); } } } @@ -120,24 +124,29 @@ public IEnumerable Apply(SourceProductionContext contex yield return factory( CreatePartialAction(request.Request.Syntax, partialItemsSyntax, false), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.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); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItemsSyntax, false), null, + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax)); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItemsSyntax, true), null, + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax)); } 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); } } @@ -160,47 +169,61 @@ public IEnumerable Apply(SourceProductionContext contex yield return factory( CreatePartialAction(request.Request.Syntax, partialItem.Syntax, false), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.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); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, false), null, + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax)); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true), null, + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax)); } 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); if (allowDerivedRequests) { var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); - yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null, + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax)); } } } } - private static Func> MakeFactory( - ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName + private static Func> MakeFactory( + ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName, bool partialHasInitialValue ) { - return method => (syntax, resolveSyntax) => GenerateMethod(method, syntax, resolveSyntax); + return method => (syntax, resolveSyntax, initialHandlerSyntax) => generateMethod(method, syntax, resolveSyntax, initialHandlerSyntax); - MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, ParameterSyntax registrationParameter) + MethodDeclarationSyntax methodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax, ParameterSyntax registrationParameter) { return method .WithParameterList( preParameterList + .AddParameters( + partialHasInitialValue && initialHandlerSyntax is {} + ? new[] { + Parameter(Identifier("initialHandler")) + .WithType(initialHandlerSyntax) + } + : Array.Empty() + ) .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) .AddParameters( resolveSyntax is { } @@ -208,18 +231,18 @@ resolveSyntax is { } Parameter(Identifier("resolveHandler")) .WithType(resolveSyntax) } - : new ParameterSyntax[] { } + : Array.Empty() ) .AddParameters(registrationParameter) ); } - MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + MethodDeclarationSyntax generateMethod(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax) { if (capabilityName is { }) { - return MethodFactory( - method, syntax, resolveSyntax, + return methodFactory( + method, syntax, resolveSyntax, initialHandlerSyntax, Parameter(Identifier("registrationOptions")) .WithType( GenericName(Identifier("RegistrationOptionsDelegate")).WithTypeArgumentList( @@ -229,8 +252,8 @@ MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSynta ); } - return MethodFactory( - method, syntax, resolveSyntax, + return methodFactory( + method, syntax, resolveSyntax, initialHandlerSyntax, Parameter(Identifier("registrationOptions")) .WithType( GenericName(Identifier("RegistrationOptionsDelegate")) @@ -272,6 +295,7 @@ private static BlockSyntax GetRequestHandlerExpression( capabilityName, false ), + null, capabilityName, resolve is not null ) @@ -315,6 +339,7 @@ private static BlockSyntax GetVoidRequestHandlerExpression( capabilityName, false ), + null, capabilityName, resolve is not null ) @@ -354,7 +379,7 @@ private static BlockSyntax GetPartialResultsHandlerExpression( ), CreateHandlerArgument( IdentifierName("LanguageProtocolDelegatingHandlers"), - "PartialResults", + item.PartialHasInitialValue ? "PartialResultsWithInitialValue" : "PartialResults", args.ToArray() ) .WithArgumentList( @@ -368,6 +393,13 @@ private static BlockSyntax GetPartialResultsHandlerExpression( capabilityName, true ), + item.PartialHasInitialValue ? + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList( new [] { item.Request.Syntax, item.Response.Syntax } )), + InitialHandlerArgument, + capabilityName, + false + ): null, capabilityName ) ) @@ -405,7 +437,7 @@ private static BlockSyntax GetPartialResultHandlerExpression( Parameter( Identifier("_") ), - CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), "PartialResult", args.ToArray()) + CreateHandlerArgument(IdentifierName("LanguageProtocolDelegatingHandlers"), item.PartialHasInitialValue ? "PartialResultWithInitialValue" : "PartialResult", args.ToArray()) .WithArgumentList( GetPartialResultArgumentList( IdentifierName("registrationOptions"), @@ -417,6 +449,13 @@ private static BlockSyntax GetPartialResultHandlerExpression( capabilityName, true ), + item.PartialHasInitialValue ? + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(new [] { item.Request.Syntax, item.Response.Syntax })), + InitialHandlerArgument, + capabilityName, + false + ): null, capabilityName ) ) @@ -466,6 +505,7 @@ private static void InsertResolveHandler( capabilityName, false ), + null, capabilityName, true ) @@ -476,11 +516,12 @@ private static void InsertResolveHandler( } private static ArgumentListSyntax GetPartialItemsArgumentList( - TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType + TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument, TypeSyntax? capabilityType ) => ArgumentList( SeparatedList( new[] { + initialArgument!, handlerArgument, Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)), Argument( @@ -500,16 +541,17 @@ private static ArgumentListSyntax GetPartialItemsArgumentList( IdentifierName("From") ) ) - } + }.Where(z => z is not null) ) ); private static ArgumentListSyntax GetPartialResultArgumentList( - TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, TypeSyntax? capabilityType + TypeSyntax registrationOptionsName, TypeSyntax registrationType, TypeSyntax responseName, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument, TypeSyntax? capabilityType ) => ArgumentList( SeparatedList( new[] { + initialArgument!, handlerArgument, Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType)), Argument( @@ -529,7 +571,7 @@ private static ArgumentListSyntax GetPartialResultArgumentList( IdentifierName("From") ) ) - } + }.Where(z => z is not null) ) ); } diff --git a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs index 0bdcdccaa..2bfb25e58 100644 --- a/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/OnRequestMethodGeneratorWithoutRegistrationOptionsStrategy.cs @@ -46,16 +46,18 @@ public IEnumerable Apply(SourceProductionContext contex method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name)); } - var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList()); + var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList(), request.PartialHasInitialValue); 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)) + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + null ); yield return factory( CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax), - resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + resolve.ReturnIfNotNull(static r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + null ); if (allowDerivedRequests) @@ -63,9 +65,11 @@ public IEnumerable Apply(SourceProductionContext contex var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); yield return genericFactory( - CreateAsyncFunc(request.Response.Syntax, false, IdentifierName("T")), null + CreateAsyncFunc(request.Response.Syntax, false, IdentifierName("T")), null, + null ); - yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T")), null); + yield return genericFactory(CreateAsyncFunc(request.Response.Syntax, true, IdentifierName("T")), null, + null); } { @@ -94,7 +98,8 @@ public IEnumerable Apply(SourceProductionContext contex 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + null ); if (allowDerivedRequests) @@ -102,7 +107,8 @@ public IEnumerable Apply(SourceProductionContext contex 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + null ); } } @@ -117,29 +123,33 @@ public IEnumerable Apply(SourceProductionContext contex .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) .WithExpressionBody( GetPartialResultsHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItems.Syntax, request.Response.Syntax + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItems.Syntax, request.Response.Syntax, request.PartialHasInitialValue ) ) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItemsSyntax, false), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax) ); yield return genericFactory( CreatePartialAction(IdentifierName("T"), partialItemsSyntax, true), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); } @@ -151,13 +161,14 @@ public IEnumerable Apply(SourceProductionContext contex .WithExpressionBody( GetPartialResultsCapabilityHandlerExpression( GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, request.Response.Syntax, - partialItems.Syntax, capability.Syntax + partialItems.Syntax, capability.Syntax, request.PartialHasInitialValue ) ) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItemsSyntax, true, capability.Syntax), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); if (allowDerivedRequests) @@ -165,7 +176,8 @@ public IEnumerable Apply(SourceProductionContext contex 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); } } @@ -176,24 +188,28 @@ public IEnumerable Apply(SourceProductionContext contex factory = methodFactory( method.WithExpressionBody( GetPartialResultHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax, request.PartialHasInitialValue ) ) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItem.Syntax, false), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, false, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, false, request.Request.Syntax) ); yield return factory( CreatePartialAction(request.Request.Syntax, partialItem.Syntax, true), - resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.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); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, false), null, + CreateAsyncFunc(request.Response.Syntax, false, request.Response.Syntax, partialItem.Syntax)); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true), null, + CreateAsyncFunc(request.Response.Syntax, true, request.Response.Syntax, partialItem.Syntax)); } if (request.Capability is { } capability) @@ -201,35 +217,45 @@ public IEnumerable Apply(SourceProductionContext contex factory = methodFactory( method.WithExpressionBody( GetPartialResultCapabilityHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax, capability.Syntax + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), request.Request.Syntax, partialItem.Syntax, request.Response.Syntax, capability.Syntax, request.PartialHasInitialValue ) ) ); 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)) + resolve.ReturnIfNotNull(r => CreateAsyncFunc(r.Response.Syntax, true, r.Request.Syntax, capability.Syntax)), + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax) ); if (allowDerivedRequests) { var genericFactory = MakeGenericFactory(factory, request.Request.Syntax); - yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null); + yield return genericFactory(CreatePartialAction(IdentifierName("T"), partialItem.Syntax, true, capability.Syntax), null, + CreateAsyncFunc(request.Response.Syntax, true, request.Request.Syntax)); } } } } - private static Func> MakeFactory( - ParameterListSyntax preParameterList + private static Func> MakeFactory( + ParameterListSyntax preParameterList, bool partialHasInitialValue ) { - return method => (syntax, resolveSyntax) => GenerateMethods(method, syntax, resolveSyntax); + return method => (syntax, resolveSyntax, initialHandlerSyntax) => generateMethods(method, syntax, resolveSyntax, initialHandlerSyntax); - MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) + MethodDeclarationSyntax methodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax) { return method .WithParameterList( preParameterList + .AddParameters( + partialHasInitialValue && initialHandlerSyntax is {} + ? new[] { + Parameter(Identifier("initialHandler")) + .WithType(initialHandlerSyntax) + } + : Array.Empty() + ) .AddParameters(Parameter(Identifier("handler")).WithType(syntax)) .AddParameters( resolveSyntax is { } @@ -237,12 +263,12 @@ resolveSyntax is { } Parameter(Identifier("resolveHandler")) .WithType(resolveSyntax) } - : new ParameterSyntax[] { } + : Array.Empty() ) ); } - MethodDeclarationSyntax GenerateMethods(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax) => MethodFactory(method, syntax, resolveSyntax); + MethodDeclarationSyntax generateMethods(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax) => methodFactory(method, syntax, resolveSyntax, initialHandlerSyntax); } } } diff --git a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs index 303f9908d..09773d9e7 100644 --- a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithRegistrationOptionsStrategy.cs @@ -42,6 +42,7 @@ public IEnumerable Apply(SourceProductionContext contex 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) @@ -66,17 +67,20 @@ public IEnumerable Apply(SourceProductionContext contex var methodFactory = MakeFactory( extensionMethodContext.GetRegistryParameterList(), registrationOptions.Syntax, - item.Capability?.Syntax + item.Capability?.Syntax, + request.PartialHasInitialValue ); var factory = methodFactory(method); yield return factory( CreateAsyncFunc(responseType, false, requestType), - CreateAsyncFunc(resolveType, false, resolveType) + CreateAsyncFunc(resolveType, false, resolveType), + null ); yield return factory( CreateAsyncFunc(responseType, true, requestType), - CreateAsyncFunc(resolveType, true, resolveType) + CreateAsyncFunc(resolveType, true, resolveType), + null ); { @@ -84,7 +88,8 @@ public IEnumerable Apply(SourceProductionContext contex { yield return factory( CreateAsyncFunc(responseType, true, requestType, capability.Syntax), - CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax), + null ); } } @@ -101,6 +106,7 @@ public IEnumerable Apply(SourceProductionContext contex request, requestType, resolveType, + responseType, registrationOptions.Syntax, item.Capability?.Syntax ) @@ -109,18 +115,21 @@ public IEnumerable Apply(SourceProductionContext contex yield return factory( CreatePartialAction(requestType, enumerableType, false), - CreateAsyncFunc(resolveType, false, resolveType) + CreateAsyncFunc(resolveType, false, resolveType), + CreateAsyncFunc(responseType, false, requestType) ); yield return factory( CreatePartialAction(requestType, enumerableType, true), - CreateAsyncFunc(resolveType, true, resolveType) + CreateAsyncFunc(resolveType, true, resolveType), + CreateAsyncFunc(responseType, true, requestType) ); if (request.Capability is { } capability) { yield return factory( CreatePartialAction(requestType, enumerableType, true, capability.Syntax), - CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax), + CreateAsyncFunc(responseType, true, requestType) ); } } @@ -135,6 +144,7 @@ public IEnumerable Apply(SourceProductionContext contex request, requestType, resolveType, + responseType, registrationOptions.Syntax, item.Capability?.Syntax ) @@ -143,53 +153,67 @@ public IEnumerable Apply(SourceProductionContext contex yield return factory( CreatePartialAction(requestType, resolveType, false), - CreateAsyncFunc(resolveType, false, resolveType) + CreateAsyncFunc(resolveType, false, resolveType), + CreateAsyncFunc(responseType, false, requestType) ); yield return factory( CreatePartialAction(requestType, resolveType, true), - CreateAsyncFunc(resolveType, true, resolveType) + CreateAsyncFunc(resolveType, true, resolveType), + CreateAsyncFunc(responseType, true, requestType) ); if (request.Capability is { } capability) { yield return factory( CreatePartialAction(requestType, resolveType, true, capability.Syntax), - CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax) + CreateAsyncFunc(resolveType, true, resolveType, capability.Syntax), + CreateAsyncFunc(responseType, true, requestType) ); } } } - private static Func> MakeFactory( - ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName + private static Func> MakeFactory( + ParameterListSyntax preParameterList, TypeSyntax registrationOptions, TypeSyntax? capabilityName, bool partialHasInitialValue ) { - return method => (syntax, resolveSyntax) => GenerateMethod(method, syntax, resolveSyntax); + return method => (syntax, resolveSyntax, initialValueSyntax) => GenerateMethod(method, syntax, resolveSyntax, initialValueSyntax); - MethodDeclarationSyntax MethodFactory(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, ParameterSyntax registrationParameter) + MethodDeclarationSyntax MethodFactory( + MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax, 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) - ); + .WithParameterList( + preParameterList + .AddParameters( + partialHasInitialValue && initialHandlerSyntax is {} + ? new[] { + Parameter(Identifier("initialHandler")) + .WithType(initialHandlerSyntax) + } + : Array.Empty() + ) + .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) + MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSyntax syntax, TypeSyntax? resolveSyntax, TypeSyntax? initialHandlerSyntax) { if (capabilityName is { }) { return MethodFactory( - method, syntax, resolveSyntax, + method, syntax, resolveSyntax, initialHandlerSyntax, Parameter(Identifier("registrationOptions")) .WithType( GenericName(Identifier("RegistrationOptionsDelegate")).WithTypeArgumentList( @@ -200,7 +224,7 @@ MethodDeclarationSyntax GenerateMethod(MethodDeclarationSyntax method, TypeSynta } return MethodFactory( - method, syntax, resolveSyntax, + method, syntax, resolveSyntax, initialHandlerSyntax, Parameter(Identifier("registrationOptions")) .WithType( GenericName(Identifier("RegistrationOptionsDelegate")) @@ -229,29 +253,32 @@ private static BlockSyntax GetRequestHandlerExpression( 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())) - ) - ) - ) - ) - )); + 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 responseSyntax, TypeSyntax registrationOptions, TypeSyntax? capabilityName ) @@ -259,33 +286,46 @@ private static BlockSyntax GetPartialHandlerExpression( var typeArgs = ImmutableArray.Create(registrationOptions); var handlerAdapterArgs = ImmutableArray.Create(requestSyntax, resolveSyntax); var resolveAdapterArgs = ImmutableArray.Create(resolveSyntax, resolveSyntax); + var initialValueAdapterArgs = ImmutableArray.Create(requestSyntax, responseSyntax); 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())) - ) - ) + 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())) + ).AddArguments( + request.PartialHasInitialValue + ? new[] + { + GetHandlerAdapterArgument( + TypeArgumentList(SeparatedList(initialValueAdapterArgs)), + InitialHandlerArgument, + capabilityName, + false + ) + } + : Array.Empty() + ) ) - ) - ) - )); + ) + ) + ) + ) + ); } public static ArgumentListSyntax HandlerArgumentList( @@ -298,7 +338,8 @@ TypeArgumentListSyntax registrationAdapterArgs ) => ArgumentList( SeparatedList( - new[] { + new[] + { Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityName)), GetHandlerAdapterArgument( handlerAdapterArgs, @@ -326,7 +367,8 @@ TypeArgumentListSyntax registrationAdapterArgs ) => ArgumentList( SeparatedList( - new[] { + new[] + { Argument( InvocationExpression( MemberAccessExpression( diff --git a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs index a7f88defc..9b6a83b3f 100644 --- a/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/OnRequestTypedResolveMethodGeneratorWithoutRegistrationOptionsStrategy.cs @@ -118,7 +118,7 @@ public IEnumerable Apply(SourceProductionContext contex .WithIdentifier(Identifier(item.JsonRpcAttributes.PartialHandlerMethodName)) .WithExpressionBody( GetPartialResultsHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, partialItems.Syntax, responseType + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, partialItems.Syntax, responseType, request.PartialHasInitialValue ) ) ); @@ -140,7 +140,7 @@ public IEnumerable Apply(SourceProductionContext contex .WithExpressionBody( GetPartialResultsCapabilityHandlerExpression( GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, responseType, - resolveType, capability.Syntax + resolveType, capability.Syntax, request.PartialHasInitialValue ) ) ); @@ -157,7 +157,7 @@ public IEnumerable Apply(SourceProductionContext contex factory = methodFactory( method.WithExpressionBody( GetPartialResultHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType, request.PartialHasInitialValue ) ) ); @@ -175,7 +175,7 @@ public IEnumerable Apply(SourceProductionContext contex factory = methodFactory( method.WithExpressionBody( GetPartialResultCapabilityHandlerExpression( - GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType, capability.Syntax + GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration), requestType, observerType, responseType, capability.Syntax, request.PartialHasInitialValue ) ) ); diff --git a/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs b/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs index 265473f86..9ae36ef86 100644 --- a/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/SendMethodNotificationStrategy.cs @@ -25,19 +25,19 @@ public IEnumerable Apply(SourceProductionContext contex .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) - } - ) - ) - ); + .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 index 7bbc19ce3..b7d2f28a4 100644 --- a/src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs @@ -16,7 +16,8 @@ public IEnumerable Apply(SourceProductionContext contex var parameterList = ParameterList( SeparatedList( - new[] { + new[] + { Parameter(Identifier("mediator")) .WithType(extensionMethodContext.Item) .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))), @@ -43,7 +44,8 @@ public IEnumerable Apply(SourceProductionContext contex .WithTypeArgumentList( TypeArgumentList( SeparatedList( - new[] { + new[] + { request.PartialItem.Syntax, request.Response!.Syntax } @@ -59,7 +61,13 @@ public IEnumerable Apply(SourceProductionContext contex ) ) .WithParameterList(parameterList) - .WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax, request.PartialItem.Syntax)) + .WithExpressionBody( + Helpers.GetPartialInvokeExpression( + request.Response.Syntax, + request.PartialHasInitialValue ? null : request.PartialItem.Syntax, + request.PartialItemInheritsFromSelf + ) + ) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); yield break; } @@ -67,7 +75,8 @@ public IEnumerable Apply(SourceProductionContext contex if (request.PartialItems is not null) { request.AdditionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); - var partialItemsSyntax = GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { request.PartialItems!.Syntax }))); + var partialItemsSyntax = + GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { request.PartialItems!.Syntax }))); yield return MethodDeclaration( GenericName( Identifier("IRequestProgressObservable") @@ -75,7 +84,8 @@ public IEnumerable Apply(SourceProductionContext contex .WithTypeArgumentList( TypeArgumentList( SeparatedList( - new[] { + new[] + { partialItemsSyntax, request.Response!.Syntax } @@ -91,7 +101,7 @@ public IEnumerable Apply(SourceProductionContext contex ) ) .WithParameterList(parameterList) - .WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax, default)) + .WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax, default, false)) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); yield break; } @@ -115,6 +125,7 @@ public IEnumerable Apply(SourceProductionContext contex .WithParameterList(parameterList) .WithExpressionBody(Helpers.GetRequestInvokeExpression()) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } } } diff --git a/src/JsonRpc.Generators/Strategies/SendMethodTypedResolveRequestStrategy.cs b/src/JsonRpc.Generators/Strategies/SendMethodTypedResolveRequestStrategy.cs new file mode 100644 index 000000000..e0191d84b --- /dev/null +++ b/src/JsonRpc.Generators/Strategies/SendMethodTypedResolveRequestStrategy.cs @@ -0,0 +1,133 @@ +using System.Net; +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 SendMethodTypedResolveRequestStrategy : IExtensionMethodContextGeneratorStrategy +{ + public IEnumerable Apply(SourceProductionContext context, ExtensionMethodContext extensionMethodContext, GeneratorData item) + { + if (item is not RequestItem request) yield break; + if (extensionMethodContext is not { IsProxy: true }) yield break; + if (item.JsonRpcAttributes.AllowDerivedRequests) yield break; + if (item is not { LspAttributes: { Resolver: { } } }) yield break; + if (request.Response.Syntax.GetSyntaxName() == "Unit") yield break; +// if (request.Request.Symbol.Name != "OutlayHintParams") yield break; + + TypeSyntax requestType = item.Request.Syntax; + TypeSyntax responseType = GenericName(Identifier(request.Response.Symbol.Name)) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(IdentifierName("T")))); + + responseType = request.Response.Syntax is NullableTypeSyntax ? NullableType(responseType) : responseType; + + var parameterList = ParameterList( + SeparatedList( + new[] + { + Parameter(Identifier("mediator")) + .WithType(extensionMethodContext.Item) + .WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))), + Parameter(Identifier("request")) + .WithType(requestType), + Parameter(Identifier("cancellationToken")) + .WithType(IdentifierName("CancellationToken")) + .WithDefault( + EqualsValueClause( + LiteralExpression(SyntaxKind.DefaultLiteralExpression, Token(SyntaxKind.DefaultKeyword)) + ) + ) + } + ) + ); +// +// if (request.PartialItem is not null) +// { +// request.AdditionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); +// yield return MethodDeclaration( +// GenericName( +// Identifier("IRequestProgressObservable") +// ) +// .WithTypeArgumentList( +// TypeArgumentList( +// SeparatedList( +// new[] +// { +// request.PartialItem.Syntax, +// responseType +// } +// ) +// ) +// ), +// Identifier(item.JsonRpcAttributes.RequestMethodName) +// ) +// .WithModifiers( +// TokenList( +// Token(SyntaxKind.PublicKeyword), +// Token(SyntaxKind.StaticKeyword) +// ) +// ) +// .WithParameterList(parameterList) +// .WithExpressionBody( +// Helpers.GetPartialInvokeExpression( +// request.Response.Syntax, +// request.PartialHasInitialValue ? null : request.PartialItem.Syntax, +// request.PartialItemInheritsFromSelf +// ) +// ) +// .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); +// yield break; +// } +// +// if (request.PartialItems is not null) +// { +// request.AdditionalUsings.Add("OmniSharp.Extensions.LanguageServer.Protocol.Progress"); +// var partialItemsSyntax = +// GenericName("IEnumerable").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { request.PartialItems!.Syntax }))); +// yield return MethodDeclaration( +// GenericName( +// Identifier("IRequestProgressObservable") +// ) +// .WithTypeArgumentList( +// TypeArgumentList( +// SeparatedList( +// new[] +// { +// partialItemsSyntax, +// responseType +// } +// ) +// ) +// ), +// Identifier(item.JsonRpcAttributes.RequestMethodName) +// ) +// .WithModifiers( +// TokenList( +// Token(SyntaxKind.PublicKeyword), +// Token(SyntaxKind.StaticKeyword) +// ) +// ) +// .WithParameterList(parameterList) +// .WithExpressionBody(Helpers.GetPartialInvokeExpression(responseType, default, false)) +// .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); +// yield break; +// } + + + var responseSyntax = GenericName("Task").WithTypeArgumentList(TypeArgumentList(SeparatedList(new[] { responseType }))); + yield return MethodDeclaration(responseSyntax, item.JsonRpcAttributes.RequestMethodName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithTypeParameterList(TypeParameterList(SingletonSeparatedList(TypeParameter("T")))) + .WithParameterList(parameterList) + .WithExpressionBody(Helpers.GetRequestReturningInvokeExpression(Helpers.GetJsonRpcMethodName(item.TypeDeclaration), responseType)) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + } +} diff --git a/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs b/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs index 21d7b9905..cca004233 100644 --- a/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs +++ b/src/JsonRpc.Generators/Strategies/TypedDelegatingHandlerStrategy.cs @@ -71,7 +71,8 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI .WithTypeArgumentList( TypeArgumentList( SeparatedList( - new[] { + new[] + { item.RegistrationOptions.Syntax, item.Capability.Syntax } @@ -80,14 +81,17 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI ); handler = handler.AddMembers( - FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + 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[] { + new[] + { Parameter(Identifier("capability")).WithType(item.Capability.Syntax), Parameter(Identifier("clientCapabilities")).WithType(IdentifierName("ClientCapabilities")) } @@ -100,7 +104,8 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName("capability")), Argument(IdentifierName("clientCapabilities")) } @@ -119,7 +124,9 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.RegistrationOptions.Syntax))); handler = handler.AddMembers( - FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + 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))) @@ -129,7 +136,8 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName("capability")), Argument(IdentifierName("clientCapabilities")) } @@ -239,7 +247,8 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI .WithParameterList( ParameterList( SeparatedList( - new[] { + new[] + { Parameter(Identifier("request")).WithType(requestType), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) } @@ -253,12 +262,14 @@ private TypeDeclarationSyntax CreateDelegatingHandler(RequestItem item, RequestI ArgumentList( SeparatedList( item.Capability is { } - ? new[] { + ? new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("Capability")), Argument(IdentifierName("cancellationToken")) } - : new[] { + : new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("cancellationToken")) } @@ -280,7 +291,8 @@ item.Capability is { } .WithParameterList( ParameterList( SeparatedList( - new[] { + new[] + { Parameter(Identifier("request")).WithType(resolveType), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) } @@ -294,12 +306,14 @@ item.Capability is { } ArgumentList( SeparatedList( item.Capability is { } - ? new[] { + ? new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("Capability")), Argument(IdentifierName("cancellationToken")) } - : new[] { + : new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("cancellationToken")) } @@ -378,7 +392,8 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R ) ); - var constructorParams = ParameterList(SingletonSeparatedList(Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager")))); + var constructorParams = + ParameterList(SingletonSeparatedList(Parameter(Identifier("progressManager")).WithType(IdentifierName("IProgressManager")))); if (item.RegistrationOptions is { }) { @@ -388,7 +403,8 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R .WithTypeArgumentList( TypeArgumentList( SeparatedList( - new[] { + new[] + { item.RegistrationOptions.Syntax, item.Capability.Syntax } @@ -397,14 +413,17 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R ); handler = handler.AddMembers( - FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + 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[] { + new[] + { Parameter(Identifier("capability")).WithType(item.Capability.Syntax), Parameter(Identifier("clientCapabilities")).WithType(IdentifierName("ClientCapabilities")) } @@ -418,7 +437,8 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R ArgumentList( SeparatedList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName("capability")), Argument(IdentifierName("clientCapabilities")) } @@ -438,7 +458,9 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.RegistrationOptions.Syntax))); handler = handler.AddMembers( - FieldDeclaration(VariableDeclaration(type).WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_registrationOptionsFactory"))))) + 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))) @@ -448,7 +470,8 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R .WithArgumentList( ArgumentList( SeparatedList( - new[] { + new[] + { Argument(IdentifierName("capability")), Argument(IdentifierName("clientCapabilities")) } @@ -490,6 +513,20 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R Parameter(Identifier("handleResolve")) .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType, item.Capability.Syntax)) ); + if (item is { PartialHasInitialValue: true }) + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType, item.Capability.Syntax)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleInitialValue")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handleInitialValue")) + .WithType(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType, item.Capability.Syntax)) + ); + } } else { @@ -512,49 +549,81 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R Parameter(Identifier("handleResolve")) .WithType(DelegateHelpers.CreateAsyncFunc(resolveType, true, resolveType)) ); + if (item is { PartialHasInitialValue: true }) + { + handler = handler.AddMembers( + FieldDeclaration( + VariableDeclaration(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType)) + .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier("_handleInitialValue")))) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword))) + ); + constructorParams = constructorParams.AddParameters( + Parameter(Identifier("handleInitialValue")) + .WithType(DelegateHelpers.CreateAsyncFunc(responseType, true, requestType)) + ); + } } - 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") - ) + var constructorDeclaration = 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") + ) + ) + ) + ); + + if (item is { PartialHasInitialValue: true }) + { + constructorDeclaration = constructorDeclaration.WithBody( + constructorDeclaration.Body!.AddStatements( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_handleInitialValue"), + IdentifierName("handleInitialValue") ) ) - ), + ) + ); + } + + handler = handler.AddMembers( + constructorDeclaration, MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Handle")) .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))) .WithParameterList( ParameterList( SeparatedList( - new[] { + new[] + { Parameter(Identifier("request")).WithType(requestType), Parameter(Identifier("results")).WithType(observerType), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) @@ -569,13 +638,15 @@ private TypeDeclarationSyntax CreateDelegatingPartialHandler(RequestItem item, R ArgumentList( SeparatedList( item.Capability is { } - ? new[] { + ? new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("results")), Argument(IdentifierName("Capability")), Argument(IdentifierName("cancellationToken")) } - : new[] { + : new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("results")), Argument(IdentifierName("cancellationToken")) @@ -585,9 +656,7 @@ item.Capability is { } ) ) ) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - ); - handler = handler.AddMembers( + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), MethodDeclaration( GenericName(Identifier("Task")) .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(resolveType))), @@ -597,7 +666,8 @@ item.Capability is { } .WithParameterList( ParameterList( SeparatedList( - new[] { + new[] + { Parameter(Identifier("request")).WithType(resolveType), Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) } @@ -611,12 +681,14 @@ item.Capability is { } ArgumentList( SeparatedList( item.Capability is { } - ? new[] { + ? new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("Capability")), Argument(IdentifierName("cancellationToken")) } - : new[] { + : new[] + { Argument(IdentifierName("request")), Argument(IdentifierName("cancellationToken")) } @@ -627,6 +699,71 @@ item.Capability is { } ) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) ); + if (item is { PartialHasInitialValue: true }) + { + handler = handler.AddMembers( + MethodDeclaration( + GenericName(Identifier("Task")) + .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(item.Response.Syntax))), + Identifier("HandleInitialValue") + ) + .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword), Token(SyntaxKind.AsyncKeyword))) + .WithParameterList( + ParameterList( + SeparatedList( + new[] + { + Parameter(Identifier("request")).WithType(requestType), + Parameter(Identifier("cancellationToken")).WithType(IdentifierName("CancellationToken")) + } + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + AwaitExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression(IdentifierName("_handleInitialValue")) + .WithArgumentList( + ArgumentList( + SeparatedList( + item.Capability is { } + ? new[] + { + Argument(IdentifierName("request")), + Argument(IdentifierName("Capability")), + Argument(IdentifierName("cancellationToken")) + } + : new[] + { + Argument(IdentifierName("request")), + Argument(IdentifierName("cancellationToken")) + } + ) + ) + ), + IdentifierName("ConfigureAwait") + ) + ) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + LiteralExpression( + SyntaxKind.FalseLiteralExpression + ) + ) + ) + ) + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + ); + } return handler; diff --git a/src/JsonRpc.Generators/StronglyTypedGenerator.cs b/src/JsonRpc.Generators/StronglyTypedGenerator.cs index 299cd4f25..2ef2d9f0f 100644 --- a/src/JsonRpc.Generators/StronglyTypedGenerator.cs +++ b/src/JsonRpc.Generators/StronglyTypedGenerator.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Operations; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static OmniSharp.Extensions.JsonRpc.Generators.Helpers; @@ -47,6 +49,15 @@ TypeDeclarationSyntax typeDeclarationSyntax and (ClassDeclarationSyntax or Recor }, (syntaxContext, _) => syntaxContext ); + var typedParamsCandidatesSyntaxProvider = context.SyntaxProvider.CreateSyntaxProvider( + (syntaxNode, _) => syntaxNode switch + { + TypeDeclarationSyntax typeDeclarationSyntax and (ClassDeclarationSyntax or RecordDeclarationSyntax) when typeDeclarationSyntax + .AttributeLists.ContainsAttribute("GenerateRequestMethods") => true, + _ => false + }, (syntaxContext, _) => syntaxContext + ); + var canBeResolvedSyntaxProvider = context.SyntaxProvider.CreateSyntaxProvider( (syntaxNode, _) => syntaxNode is TypeDeclarationSyntax { BaseList: { } } typeDeclarationSyntax and (ClassDeclarationSyntax or RecordDeclarationSyntax) @@ -67,6 +78,18 @@ TypeDeclarationSyntax typeDeclarationSyntax and (ClassDeclarationSyntax or Recor context.RegisterSourceOutput(createContainersSyntaxProvider.Combine(attributes), GenerateContainerClass); context.RegisterSourceOutput(canBeResolvedSyntaxProvider.Combine(attributes), GenerateCanBeResolvedClass); context.RegisterSourceOutput(canHaveDataSyntaxProvider.Combine(attributes), GenerateCanHaveDataClass); + // TODO: Add support for generating handler methods and interfaces that take in the strongly typed data. +// context.RegisterSourceOutput( +// typedParamsCandidatesSyntaxProvider +// .Combine(canBeResolvedSyntaxProvider.Select((z, _) => (TypeDeclarationSyntax)z.Node).Collect()) +// .Combine(canHaveDataSyntaxProvider.Select((z, _) => (TypeDeclarationSyntax)z.Node).Collect()) +// .Combine(createContainersSyntaxProvider.Select((z, _) => (TypeDeclarationSyntax)z.Node).Collect()) +// .Select( +// (tuple, token) => ( candidate: tuple.Left.Left.Left, +// resolvedItems: tuple.Left.Left.Right.Concat(tuple.Left.Right).Concat(tuple.Right).ToImmutableArray() ) +// ), +// GenerateTypedParams +// ); } private void GenerateContainerClass(SourceProductionContext context, (GeneratorSyntaxContext syntaxContext, AttributeData attributeData) valueTuple) @@ -221,62 +244,68 @@ bool includeHandlerIdentity if (container is { }) { 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 - .AddMembers( - ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), IdentifierName(typedContainer.Identifier)) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(Identifier("container")) - .WithType(GenericName(typedContainer.Identifier).WithTypeArgumentList(typedArgumentList)) + + if (!( container is { NamedArguments: { Length: > 0 } namedArguments } + && namedArguments.FirstOrDefault(z => z.Key == "GenerateImplicitConversion") is { Value.Value: false } )) + { + typedContainer = typedContainer + .AddMembers( + ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), IdentifierName(typedContainer.Identifier)) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("container")) + .WithType(GenericName(typedContainer.Identifier).WithTypeArgumentList(typedArgumentList)) + ) ) ) - ) - .WithExpressionBody( - ArrowExpressionClause( - ObjectCreationExpression(IdentifierName(typedContainer.Identifier)) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("container"), - IdentifierName("Select") + .WithExpressionBody( + ArrowExpressionClause( + ObjectCreationExpression(IdentifierName(typedContainer.Identifier)) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("container"), + IdentifierName("Select") + ) ) - ) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument( - SimpleLambdaExpression(Parameter(Identifier("value"))) - .WithExpressionBody( - CastExpression( - IdentifierName(candidate.Identifier), - IdentifierName("value") + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + SimpleLambdaExpression(Parameter(Identifier("value"))) + .WithExpressionBody( + CastExpression( + IdentifierName(candidate.Identifier), + IdentifierName("value") + ) ) - ) + ) ) ) ) - ) + ) ) ) ) - ) + ) ) - ) - .MakeMethodNullable(IdentifierName("container")) - .WithSemicolonToken( - Token(SyntaxKind.SemicolonToken) - ) - ); + .MakeMethodNullable(IdentifierName("container")) + .WithSemicolonToken( + Token(SyntaxKind.SemicolonToken) + ) + ); + } compilationMembers.Add(typedContainer); } diff --git a/src/JsonRpc/JsonRpc.csproj b/src/JsonRpc/JsonRpc.csproj index 29782f6dc..efa5b2beb 100644 --- a/src/JsonRpc/JsonRpc.csproj +++ b/src/JsonRpc/JsonRpc.csproj @@ -17,67 +17,48 @@ - + - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.JsonRpc.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.JsonRpc.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageServer.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageServer.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageClient, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageClient, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Server, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Server, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.DebugAdapter.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.DebugAdapter.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f diff --git a/src/JsonRpc/Server/ErrorCodes.cs b/src/JsonRpc/Server/ErrorCodes.cs index a33a53c7f..99bfcb5a0 100644 --- a/src/JsonRpc/Server/ErrorCodes.cs +++ b/src/JsonRpc/Server/ErrorCodes.cs @@ -51,8 +51,25 @@ public static class ErrorCodes public const int RequestCancelled = -32800; /// - /// Request was cancelled. + /// Content was modified /// public const int ContentModified = -32801; + + /// + /// A request failed but it was syntactically correct, e.g the + /// method name was known and the parameters were valid. The error + /// message should contain human readable information about why + /// the request failed. + /// @since 3.17.0 + /// + public const int RequestFailed = -32803; + + /// + /// The server cancelled the request. This error code should + /// only be used for requests that explicitly support being + /// server cancellable. + /// @since 3.17.0 + /// + public const int ServerCancelled = -32802; } } diff --git a/src/JsonRpc/Server/RequestFailedException.cs b/src/JsonRpc/Server/RequestFailedException.cs new file mode 100644 index 000000000..8ea568a5f --- /dev/null +++ b/src/JsonRpc/Server/RequestFailedException.cs @@ -0,0 +1,87 @@ +using System.Runtime.Serialization; + +namespace OmniSharp.Extensions.JsonRpc.Server; + +/// +/// Exception raised when request parameters are invalid according to the target method. +/// +[Serializable] +public class RequestFailedException + : TaskCanceledException, IRequestException +{ + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + public RequestFailedException(object? requestId) + : this(ErrorCodes.RequestFailed, requestId?.ToString() ?? "(unknown)", "Content not modified.", null!) + { + } + + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + /// + /// The exception that caused this exception to be raised. + /// + public RequestFailedException(object? requestId, Exception inner) + : this(ErrorCodes.RequestFailed, requestId?.ToString() ?? "(unknown)", "Content not modified.", inner) + { + } + + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC error code. + /// + /// + /// The exception message. + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + /// + /// The exception that caused this exception to be raised. + /// + public RequestFailedException(int errorCode, string message, string requestId, Exception inner) : base(message, inner) + { + RequestId = !string.IsNullOrWhiteSpace(requestId) ? requestId : UnknownRequestId; + ErrorCode = errorCode; + } + + /// + /// Serialisation constructor. + /// + /// + /// The serialisation data-store. + /// + /// + /// The serialisation streaming context. + /// + protected RequestFailedException(SerializationInfo info, StreamingContext context) + { + RequestId = info.GetString(nameof(RequestId)); + ErrorCode = info.GetInt32(nameof(ErrorCode)); + } + + /// + /// The LSP / JSON-RPC request Id (if known). + /// + public object RequestId { get; } + + /// + /// The LSP / JSON-RPC error code. + /// + public int ErrorCode { get; } + + /// + /// The request Id used when no valid request Id was supplied. + /// + public const string UnknownRequestId = "(unknown)"; +} diff --git a/src/JsonRpc/Server/ServerCancelledException.cs b/src/JsonRpc/Server/ServerCancelledException.cs new file mode 100644 index 000000000..8a7338928 --- /dev/null +++ b/src/JsonRpc/Server/ServerCancelledException.cs @@ -0,0 +1,87 @@ +using System.Runtime.Serialization; + +namespace OmniSharp.Extensions.JsonRpc.Server; + +/// +/// Exception raised when request parameters are invalid according to the target method. +/// +[Serializable] +public class ServerCancelledException + : TaskCanceledException, IRequestException +{ + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + public ServerCancelledException(object? requestId) + : this(ErrorCodes.ServerCancelled, requestId?.ToString() ?? "(unknown)", "Content not modified.", null!) + { + } + + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + /// + /// The exception that caused this exception to be raised. + /// + public ServerCancelledException(object? requestId, Exception inner) + : this(ErrorCodes.ServerCancelled, requestId?.ToString() ?? "(unknown)", "Content not modified.", inner) + { + } + + /// + /// Create a new . + /// + /// + /// The LSP / JSON-RPC error code. + /// + /// + /// The exception message. + /// + /// + /// The LSP / JSON-RPC request Id (if known). + /// + /// + /// The exception that caused this exception to be raised. + /// + public ServerCancelledException(int errorCode, string message, string requestId, Exception inner) : base(message, inner) + { + RequestId = !string.IsNullOrWhiteSpace(requestId) ? requestId : UnknownRequestId; + ErrorCode = errorCode; + } + + /// + /// Serialisation constructor. + /// + /// + /// The serialisation data-store. + /// + /// + /// The serialisation streaming context. + /// + protected ServerCancelledException(SerializationInfo info, StreamingContext context) + { + RequestId = info.GetString(nameof(RequestId)); + ErrorCode = info.GetInt32(nameof(ErrorCode)); + } + + /// + /// The LSP / JSON-RPC request Id (if known). + /// + public object RequestId { get; } + + /// + /// The LSP / JSON-RPC error code. + /// + public int ErrorCode { get; } + + /// + /// The request Id used when no valid request Id was supplied. + /// + public const string UnknownRequestId = "(unknown)"; +} diff --git a/src/Protocol/AbstractHandlers.Base.cs b/src/Protocol/AbstractHandlers.Base.cs new file mode 100644 index 000000000..739ff577b --- /dev/null +++ b/src/Protocol/AbstractHandlers.Base.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class AbstractHandlers + { + public abstract class Base : + IRegistration, + ICapability + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; + protected TCapability Capability { get; private set; } = default!; + protected ClientCapabilities ClientCapabilities { 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; + ClientCapabilities = clientCapabilities; + return RegistrationOptions = CreateRegistrationOptions(capability, clientCapabilities); + } + + void ICapability.SetCapability(TCapability capability, ClientCapabilities clientCapabilities) + { + ClientCapabilities = clientCapabilities; + Capability = capability; + } + } + + public abstract class BaseCapability : + ICapability + where TCapability : ICapability + { + protected TCapability Capability { get; private set; } = default!; + protected ClientCapabilities ClientCapabilities { get; private set; } = default!; + + void ICapability.SetCapability(TCapability capability, ClientCapabilities clientCapabilities) + { + ClientCapabilities = clientCapabilities; + Capability = capability; + } + } + + public abstract class Base : + IRegistration + where TRegistrationOptions : class, new() + { + protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; + protected ClientCapabilities ClientCapabilities { 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; + ClientCapabilities = clientCapabilities; + return RegistrationOptions = CreateRegistrationOptions(clientCapabilities); + } + } + } +} diff --git a/src/Protocol/AbstractHandlers.Notification.cs b/src/Protocol/AbstractHandlers.Notification.cs new file mode 100644 index 000000000..89b2c4f36 --- /dev/null +++ b/src/Protocol/AbstractHandlers.Notification.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class AbstractHandlers + { + 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/AbstractHandlers.cs b/src/Protocol/AbstractHandlers.Partial.cs similarity index 63% rename from src/Protocol/AbstractHandlers.cs rename to src/Protocol/AbstractHandlers.Partial.cs index 4fa7cc9c3..132a470a3 100644 --- a/src/Protocol/AbstractHandlers.cs +++ b/src/Protocol/AbstractHandlers.Partial.cs @@ -14,101 +14,8 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { - public static class AbstractHandlers + public static partial class AbstractHandlers { - public abstract class Base : - IRegistration, - ICapability - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; - protected TCapability Capability { get; private set; } = default!; - protected ClientCapabilities ClientCapabilities { 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; - ClientCapabilities = clientCapabilities; - return RegistrationOptions = CreateRegistrationOptions(capability, clientCapabilities); - } - - void ICapability.SetCapability(TCapability capability, ClientCapabilities clientCapabilities) - { - ClientCapabilities = clientCapabilities; - Capability = capability; - } - } - - public abstract class BaseCapability : - ICapability - where TCapability : ICapability - { - protected TCapability Capability { get; private set; } = default!; - protected ClientCapabilities ClientCapabilities { get; private set; } = default!; - - void ICapability.SetCapability(TCapability capability, ClientCapabilities clientCapabilities) - { - ClientCapabilities = clientCapabilities; - Capability = capability; - } - } - - public abstract class Base : - IRegistration - where TRegistrationOptions : class, new() - { - protected TRegistrationOptions RegistrationOptions { get; private set; } = default!; - protected ClientCapabilities ClientCapabilities { 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; - ClientCapabilities = clientCapabilities; - return RegistrationOptions = CreateRegistrationOptions(clientCapabilities); - } - } - - public abstract class Request : - IJsonRpcRequestHandler - where TParams : IRequest - { - public abstract Task Handle(TParams request, CancellationToken cancellationToken); - } - - public abstract class Request : - Base, - IJsonRpcRequestHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - { - public abstract Task Handle(TParams request, CancellationToken cancellationToken); - } - - 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 @@ -137,10 +44,10 @@ CancellationToken cancellationToken { Handle(request, observer, cancellationToken); await observer; - return _factory(default(TItem)); + return default; } - var subject = new AsyncSubject(); + using var subject = new AsyncSubject(); var task = subject .Select(_factory) .ToTask(cancellationToken, _progressManager.Scheduler) @@ -181,10 +88,10 @@ CancellationToken cancellationToken { Handle(request, observer, cancellationToken); await observer; - return _factory(default); + return default; } - var subject = new AsyncSubject(); + using var subject = new AsyncSubject(); var task = subject .Select(_factory) .ToTask(cancellationToken, _progressManager.Scheduler) @@ -225,10 +132,10 @@ CancellationToken cancellationToken { Handle(request, observer, cancellationToken); await observer; - return _factory(default); + return default; } - var subject = new AsyncSubject(); + using var subject = new AsyncSubject(); var task = subject .Select(_factory) .ToTask(cancellationToken, _progressManager.Scheduler) @@ -266,13 +173,14 @@ protected PartialResults(IProgressManager progressManager, Func()); + return default; } - var subject = new Subject>(); + using var subject = new Subject>(); var task = subject .Aggregate( - new List(), (acc, items) => { + new List(), (acc, items) => + { acc.AddRange(items); return acc; } @@ -310,13 +218,14 @@ protected PartialResults(IProgressManager progressManager, Func()); + return default; } - var subject = new Subject>(); + using var subject = new Subject>(); var task = subject .Aggregate( - new List(), (acc, items) => { + new List(), (acc, items) => + { acc.AddRange(items); return acc; } @@ -354,13 +263,14 @@ protected PartialResultsCapability(IProgressManager progressManager, Func()); + return default; } - var subject = new Subject>(); + using var subject = new Subject>(); var task = subject .Aggregate( - new List(), (acc, items) => { + new List(), (acc, items) => + { acc.AddRange(items); return acc; } @@ -375,38 +285,5 @@ protected PartialResultsCapability(IProgressManager progressManager, Func> results, CancellationToken cancellationToken); } - 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/AbstractHandlers.PartialWithInitialValue.cs b/src/Protocol/AbstractHandlers.PartialWithInitialValue.cs new file mode 100644 index 000000000..870020020 --- /dev/null +++ b/src/Protocol/AbstractHandlers.PartialWithInitialValue.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class AbstractHandlers + { + public abstract class PartialResultWithInitialValue : + Base, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemWithInitialValueRequest + where TResponse : TItem? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly IProgressManager _progressManager; + private readonly Func _factory; + + protected PartialResultWithInitialValue(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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + Handle(request, subject, cancellationToken); + return await task; + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); + } + + public abstract class PartialResultWithInitialValue : + Base, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemWithInitialValueRequest + where TResponse : TItem? + where TRegistrationOptions : class, new() + { + private readonly IProgressManager _progressManager; + private readonly Func _factory; + + protected PartialResultWithInitialValue(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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + Handle(request, subject, cancellationToken); + return await task; + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); + } + + public abstract class PartialResultWithInitialValueCapability : + BaseCapability, + IJsonRpcRequestHandler + where TItem : class? + where TParams : IPartialItemWithInitialValueRequest + where TResponse : TItem? + where TCapability : ICapability + { + private readonly IProgressManager _progressManager; + private readonly Func _factory; + + protected PartialResultWithInitialValueCapability(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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + Handle(request, subject, cancellationToken); + return await task; + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver results, CancellationToken cancellationToken); + } + + public abstract class PartialResultsWithInitialValue : + Base, + IJsonRpcRequestHandler + where TParams : IPartialItemsWithInitialValueRequest + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + + protected PartialResultsWithInitialValue( + 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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + { + using var subject = new Subject>(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + Handle(request, subject, cancellationToken); + return await task; + } + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); + } + + public abstract class PartialResultsWithInitialValue : + Base, + IJsonRpcRequestHandler + where TParams : IPartialItemsWithInitialValueRequest + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + { + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + + protected PartialResultsWithInitialValue( + 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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + { + using var subject = new Subject>(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + Handle(request, subject, cancellationToken); + return await task; + } + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); + } + + public abstract class PartialResultsWithInitialValueCapability : + BaseCapability, + IJsonRpcRequestHandler + where TParams : IPartialItemsWithInitialValueRequest + where TResponse : IEnumerable? + where TCapability : ICapability + { + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + + protected PartialResultsWithInitialValueCapability( + 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) + { + observer.OnNext(await HandleInitialValue(request, cancellationToken)); + Handle(request, observer, cancellationToken); + await observer; + return default; + } + + { + using var subject = new Subject>(); + var task = subject + .Aggregate(await HandleInitialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + Handle(request, subject, cancellationToken); + return await task; + } + } + + protected abstract Task HandleInitialValue(TParams request, CancellationToken cancellationToken); + protected abstract void Handle(TParams request, IObserver> results, CancellationToken cancellationToken); + } + } +} diff --git a/src/Protocol/AbstractHandlers.Request.cs b/src/Protocol/AbstractHandlers.Request.cs new file mode 100644 index 000000000..475f6f1e8 --- /dev/null +++ b/src/Protocol/AbstractHandlers.Request.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class AbstractHandlers + { + + public abstract class Request : + IJsonRpcRequestHandler + where TParams : IRequest + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + public abstract class Request : + Base, + IJsonRpcRequestHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + public abstract Task Handle(TParams request, CancellationToken cancellationToken); + } + + 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); + } + } +} diff --git a/src/Protocol/Client/Capabilities/ClientCapabilities.cs b/src/Protocol/Client/Capabilities/ClientCapabilities.cs index 07be4f2f9..53884be40 100644 --- a/src/Protocol/Client/Capabilities/ClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/ClientCapabilities.cs @@ -18,6 +18,14 @@ public class ClientCapabilities : CapabilitiesBase, IClientCapabilities [Optional] public TextDocumentClientCapabilities? TextDocument { get; set; } + /// + /// Capabilities specific to the notebook document support. + /// + /// @since 3.17.0 + /// + [Optional] + public NotebookDocumentClientCapabilities? NotebookDocument { get; set; } + /// /// Window specific client capabilities. /// diff --git a/src/Protocol/Client/Capabilities/GeneralClientCapabilities.cs b/src/Protocol/Client/Capabilities/GeneralClientCapabilities.cs index f7f2ca959..2d1eb66aa 100644 --- a/src/Protocol/Client/Capabilities/GeneralClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/GeneralClientCapabilities.cs @@ -1,4 +1,5 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities { @@ -20,6 +21,41 @@ public class GeneralClientCapabilities : CapabilitiesBase, IGeneralClientCapabil /// /// @since 3.16.0 /// - [Optional] public MarkdownClientCapabilities? Markdown { get; set; } + [Optional] + public MarkdownClientCapabilities? Markdown { get; set; } + + /// + /// Client capability that signals how the client + /// handles stale requests (e.g. a request + /// for which the client will not process the response + /// anymore since the information is outdated). + /// + /// @since 3.17.0 + /// + [Optional] + public StaleRequestSupportClientCapabilities? StaleRequestSupport { get; set; } + + /// + /// The position encodings supported by the client. Client and server + /// have to agree on the same position encoding to ensure that offsets + /// (e.g. character position in a line) are interpreted the same on both + /// side. + /// + /// To keep the protocol backwards compatible the following applies: if + /// the value 'utf-16' is missing from the array of position encodings + /// servers can assume that the client supports UTF-16. UTF-16 is + /// therefore a mandatory encoding. + /// + /// If omitted it defaults to ['utf-16']. + /// + /// Implementation considerations: since the conversion from one encoding + /// into another requires the content of the file / line the conversion + /// is best done where the file is read which is usually on the server + /// side. + /// + /// @since 3.17.0 + /// + [Optional] + public Container? PositionEncodings { get; set; } } -} \ No newline at end of file +} diff --git a/src/Protocol/Client/Capabilities/IGeneralClientCapabilities.cs b/src/Protocol/Client/Capabilities/IGeneralClientCapabilities.cs index 06c15abfe..c036a4cad 100644 --- a/src/Protocol/Client/Capabilities/IGeneralClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/IGeneralClientCapabilities.cs @@ -1,4 +1,6 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities { public interface IGeneralClientCapabilities { @@ -15,5 +17,37 @@ public interface IGeneralClientCapabilities /// @since 3.16.0 /// MarkdownClientCapabilities? Markdown { get; set; } + + /// + /// Client capability that signals how the client + /// handles stale requests (e.g. a request + /// for which the client will not process the response + /// anymore since the information is outdated). + /// + /// @since 3.17.0 + /// + StaleRequestSupportClientCapabilities? StaleRequestSupport { get; set; } + + /// + /// The position encodings supported by the client. Client and server + /// have to agree on the same position encoding to ensure that offsets + /// (e.g. character position in a line) are interpreted the same on both + /// side. + /// + /// To keep the protocol backwards compatible the following applies: if + /// the value 'utf-16' is missing from the array of position encodings + /// servers can assume that the client supports UTF-16. UTF-16 is + /// therefore a mandatory encoding. + /// + /// If omitted it defaults to ['utf-16']. + /// + /// Implementation considerations: since the conversion from one encoding + /// into another requires the content of the file / line the conversion + /// is best done where the file is read which is usually on the server + /// side. + /// + /// @since 3.17.0 + /// + Container? PositionEncodings { get; set; } } -} \ No newline at end of file +} diff --git a/src/Protocol/Client/Capabilities/ITextDocumentClientCapabilities.cs b/src/Protocol/Client/Capabilities/ITextDocumentClientCapabilities.cs index 943dc8e52..fb7104c29 100644 --- a/src/Protocol/Client/Capabilities/ITextDocumentClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/ITextDocumentClientCapabilities.cs @@ -2,7 +2,7 @@ { public interface ITextDocumentClientCapabilities : ICapabilitiesBase { - Supports Synchronization { get; set; } + Supports Synchronization { get; set; } /// /// Capabilities specific to the `textDocument/completion` @@ -146,5 +146,33 @@ public interface ITextDocumentClientCapabilities : ICapabilitiesBase /// @since 3.16.0 /// Supports Moniker { get; set; } + + /// + /// Capabilities specific to the various type hierarchy requests. + /// + /// @since 3.17.0 + /// + Supports TypeHierarchy { get; set; } + + /// + /// Capabilities specific to the `textDocument/inlineValue` request. + /// + /// @since 3.17.0 + /// + Supports InlineValue { get; set; } + + /// + /// Capability specific to the `textDocument/inlayHint` request. + /// + /// @since 3.17.0 + /// + Supports InlayHint { get; set; } + + /// + /// Capability specific to the diagnostic pull model. + /// + /// @since 3.17.0 + /// + Supports Diagnostic { get; set; } } -} \ No newline at end of file +} diff --git a/src/Protocol/Client/Capabilities/IWindowClientCapabilities.cs b/src/Protocol/Client/Capabilities/IWindowClientCapabilities.cs index 764287c43..900bff3ea 100644 --- a/src/Protocol/Client/Capabilities/IWindowClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/IWindowClientCapabilities.cs @@ -3,7 +3,7 @@ public interface IWindowClientCapabilities : ICapabilitiesBase { /// - /// Whether client supports handling progress notifications. + /// Whether the client supports server initiated progress using the `window/workDoneProgress/create` request. /// Supports WorkDoneProgress { get; set; } @@ -21,4 +21,4 @@ public interface IWindowClientCapabilities : ICapabilitiesBase /// Supports ShowDocument { get; set; } } -} \ No newline at end of file +} diff --git a/src/Protocol/Client/Capabilities/MarkdownClientCapabilities.cs b/src/Protocol/Client/Capabilities/MarkdownClientCapabilities.cs index 608e196e1..177d69a1a 100644 --- a/src/Protocol/Client/Capabilities/MarkdownClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/MarkdownClientCapabilities.cs @@ -1,3 +1,4 @@ +using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities @@ -12,12 +13,21 @@ public class MarkdownClientCapabilities /// /// The name of the parser. /// - public string Parser { get; set; } + public string Parser { get; set; } = null!; /// /// The version of the parser. /// [Optional] public string? Version { get; set; } + + /// + /// A list of HTML tags that the client allows / supports in + /// Markdown. + /// + /// @since 3.17.0 + /// + [Optional] + public Container? AllowedTags { get; set; } } } diff --git a/src/Protocol/Client/Capabilities/NotebookDocumentClientCapabilities.cs b/src/Protocol/Client/Capabilities/NotebookDocumentClientCapabilities.cs new file mode 100644 index 000000000..b86d035e2 --- /dev/null +++ b/src/Protocol/Client/Capabilities/NotebookDocumentClientCapabilities.cs @@ -0,0 +1,16 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; + +/// +/// Capabilities specific to the notebook document support. +/// +/// @since 3.17.0 +/// +public class NotebookDocumentClientCapabilities +{ + /// + /// Capabilities specific to notebook document synchronization + /// + /// @since 3.17.0 + /// + public Supports Synchronization { get; set; } +} diff --git a/src/Protocol/Client/Capabilities/StaleRequestSupportClientCapabilities.cs b/src/Protocol/Client/Capabilities/StaleRequestSupportClientCapabilities.cs new file mode 100644 index 000000000..64577a4d2 --- /dev/null +++ b/src/Protocol/Client/Capabilities/StaleRequestSupportClientCapabilities.cs @@ -0,0 +1,26 @@ +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; + +/// +/// Client capability that signals how the client +/// handles stale requests (e.g. a request +/// for which the client will not process the response +/// anymore since the information is outdated). +/// +/// @since 3.17.0 +/// +public class StaleRequestSupportClientCapabilities +{ + /// + /// The client will actively cancel the request. + /// + public bool Cancel { get; set; } + + /// + /// The list of requests for which the client + /// will retry the request if it receives a + /// response with error code `ContentModified`` + /// + public Container RetryOnContentModified { get; set; } = new(); +} diff --git a/src/Protocol/Client/Capabilities/SymbolKindCapabilityOptions.cs b/src/Protocol/Client/Capabilities/SymbolKindCapabilityOptions.cs deleted file mode 100644 index 043c3781c..000000000 --- a/src/Protocol/Client/Capabilities/SymbolKindCapabilityOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// Specific capabilities for the `SymbolKind`. - /// - public class SymbolKindCapabilityOptions - { - /// - /// The symbol 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 symbol kinds from `File` to `Array` as defined in - /// the initial version of the protocol. - /// - [Optional] - public Container? ValueSet { get; set; } - } -} diff --git a/src/Protocol/Client/Capabilities/TagSupportCapabilityOptions.cs b/src/Protocol/Client/Capabilities/TagSupportCapabilityOptions.cs deleted file mode 100644 index f0bbaeb7d..000000000 --- a/src/Protocol/Client/Capabilities/TagSupportCapabilityOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities -{ - /// - /// 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 - /// - public class TagSupportCapabilityOptions - { - /// - /// The tags supported by the client. - /// - public Container ValueSet { get; set; } = null!; - } -} diff --git a/src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs b/src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs index f74b73634..c8b70d5d5 100644 --- a/src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/TextDocumentClientCapabilities.cs @@ -2,7 +2,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities { public class TextDocumentClientCapabilities : CapabilitiesBase, ITextDocumentClientCapabilities { - public Supports Synchronization { get; set; } + public Supports Synchronization { get; set; } /// /// Capabilities specific to the `textDocument/completion` @@ -146,5 +146,33 @@ public class TextDocumentClientCapabilities : CapabilitiesBase, ITextDocumentCli /// @since 3.16.0 /// public Supports Moniker { get; set; } + + /// + /// Capabilities specific to the various type hierarchy requests. + /// + /// @since 3.17.0 + /// + public Supports TypeHierarchy { get; set; } + + /// + /// Capabilities specific to the `textDocument/inlineValue` request. + /// + /// @since 3.17.0 + /// + public Supports InlineValue { get; set; } + + /// + /// Capability specific to the `textDocument/inlayHint` request. + /// + /// @since 3.17.0 + /// + public Supports InlayHint { get; set; } + + /// + /// Capability specific to the diagnostic pull model. + /// + /// @since 3.17.0 + /// + public Supports Diagnostic { get; set; } } } diff --git a/src/Protocol/Client/Capabilities/WindowClientCapabilities.cs b/src/Protocol/Client/Capabilities/WindowClientCapabilities.cs index 24ba5cebc..ba40b2e0f 100644 --- a/src/Protocol/Client/Capabilities/WindowClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/WindowClientCapabilities.cs @@ -6,7 +6,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities public class WindowClientCapabilities : CapabilitiesBase, IWindowClientCapabilities { /// - /// Whether client supports handling progress notifications. + /// Whether the client supports server initiated progress using the `window/workDoneProgress/create` request. /// public Supports WorkDoneProgress { get; set; } diff --git a/src/Protocol/Client/Capabilities/WorkspaceClientCapabilities.cs b/src/Protocol/Client/Capabilities/WorkspaceClientCapabilities.cs index 94dd06b5c..0f8d22833 100644 --- a/src/Protocol/Client/Capabilities/WorkspaceClientCapabilities.cs +++ b/src/Protocol/Client/Capabilities/WorkspaceClientCapabilities.cs @@ -54,6 +54,27 @@ public class WorkspaceClientCapabilities : CapabilitiesBase /// public Supports FileOperations { get; set; } + /// + /// Client workspace capabilities specific to inline values. + /// + /// @since 3.17.0 + /// + public Supports InlineValue { get; set; } + + /// + /// Client workspace capabilities specific to inlay hints. + /// + /// @since 3.17.0 + /// + public Supports InlayHint { get; set; } + + /// + /// Client workspace capabilities specific to diagnostics. + /// + /// @since 3.17.0. + /// + public Supports Diagnostics { get; set; } + /// /// The client has support for workspace folders. /// @@ -68,6 +89,4 @@ public class WorkspaceClientCapabilities : CapabilitiesBase /// public Supports Configuration { get; set; } } - - } diff --git a/src/Protocol/Client/ILanguageClientFacade.cs b/src/Protocol/Client/ILanguageClientFacade.cs index 8b29aaeee..48e6817e4 100644 --- a/src/Protocol/Client/ILanguageClientFacade.cs +++ b/src/Protocol/Client/ILanguageClientFacade.cs @@ -5,6 +5,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client public interface ILanguageClientFacade : ILanguageClientProxy, IJsonRpcHandlerInstance { ITextDocumentLanguageClient TextDocument { get; } + INotebookDocumentLanguageClient NotebookDocument { get; } IClientLanguageClient Client { get; } IGeneralLanguageClient General { get; } IWindowLanguageClient Window { get; } diff --git a/src/Protocol/Client/INotebookDocumentLanguageClient.cs b/src/Protocol/Client/INotebookDocumentLanguageClient.cs new file mode 100644 index 000000000..f1be3c184 --- /dev/null +++ b/src/Protocol/Client/INotebookDocumentLanguageClient.cs @@ -0,0 +1,5 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client; + +public interface INotebookDocumentLanguageClient : ILanguageClientProxy +{ +} diff --git a/src/Protocol/Client/NotebookDocumentLanguageClient.cs b/src/Protocol/Client/NotebookDocumentLanguageClient.cs new file mode 100644 index 000000000..8c2202c9c --- /dev/null +++ b/src/Protocol/Client/NotebookDocumentLanguageClient.cs @@ -0,0 +1,15 @@ +using DryIoc; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Client; + +internal class NotebookDocumentLanguageClient : LanguageProtocolProxy, INotebookDocumentLanguageClient +{ + public NotebookDocumentLanguageClient( + IResponseRouter requestRouter, IResolverContext resolverContext, IProgressManager progressManager, + ILanguageProtocolSettings languageProtocolSettings + ) : base(requestRouter, resolverContext, progressManager, languageProtocolSettings) + { + } +} diff --git a/src/Protocol/Client/WorkDone/WorkDoneProxyExtensions.cs b/src/Protocol/Client/WorkDone/WorkDoneProxyExtensions.cs index 53b97c59f..6312c00d9 100644 --- a/src/Protocol/Client/WorkDone/WorkDoneProxyExtensions.cs +++ b/src/Protocol/Client/WorkDone/WorkDoneProxyExtensions.cs @@ -60,6 +60,24 @@ public static TResult ObserveWorkDone( DoObserveWorkDone(proxy, @params, observer); return func(proxy, @params); } + + public static TResult ObserveWorkDone( + this INotebookDocumentLanguageClient proxy, T @params, Func func, IObserver observer + ) + where T : IWorkDoneProgressParams + { + DoObserveWorkDone(proxy, @params, observer); + return func(proxy, @params); + } + + public static TResult ObserveWorkDone( + this INotebookDocumentLanguageClient proxy, T @params, Func func, IWorkDoneProgressObserver observer + ) + where T : IWorkDoneProgressParams + { + DoObserveWorkDone(proxy, @params, observer); + return func(proxy, @params); + } public static TResult ObserveWorkDone( this IWindowLanguageClient proxy, T @params, Func func, IObserver observer diff --git a/src/Protocol/Document/INotebookDocumentIdentifier.cs b/src/Protocol/Document/INotebookDocumentIdentifier.cs new file mode 100644 index 000000000..082ce481e --- /dev/null +++ b/src/Protocol/Document/INotebookDocumentIdentifier.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reactive.Disposables; + +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ + public interface INotebookDocumentIdentifier + { + /// + /// Returns the attributes for the document at the given URI. This can return null. + /// + /// + /// + NotebookDocumentAttributes GetNotebookDocumentAttributes(DocumentUri uri); + } + + public abstract class NotebookDocumentIdentifierBase : INotebookDocumentIdentifier + { + public NotebookDocumentAttributes GetNotebookDocumentAttributes(DocumentUri uri) + { + var (languageId, schema) = GetAttributes(uri); + return new NotebookDocumentAttributes(uri, languageId, schema); + } + + protected abstract (string notebookType, string schema) GetAttributes(DocumentUri uri); + } + + public class NotebookDocumentIdentifiers : IEnumerable + { + private readonly HashSet _NotebookDocumentIdentifiers = new HashSet(); + public IEnumerator GetEnumerator() => _NotebookDocumentIdentifiers.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public IDisposable Add(params INotebookDocumentIdentifier[] identifiers) + { + foreach (var item in identifiers) + _NotebookDocumentIdentifiers.Add(item); + return Disposable.Create( + () => { + foreach (var NotebookDocumentIdentifier in identifiers) + { + _NotebookDocumentIdentifiers.Remove(NotebookDocumentIdentifier); + } + } + ); + } + } +} diff --git a/src/Protocol/Document/NotebookDocumentAttributes.cs b/src/Protocol/Document/NotebookDocumentAttributes.cs new file mode 100644 index 000000000..b7f39c32c --- /dev/null +++ b/src/Protocol/Document/NotebookDocumentAttributes.cs @@ -0,0 +1,69 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document; + +public class NotebookDocumentAttributes : IEquatable +{ + public NotebookDocumentAttributes(DocumentUri uri, string notebookType) + { + Uri = uri; + NotebookType = notebookType; + } + + public NotebookDocumentAttributes(DocumentUri uri) + { + Uri = uri; + } + + public NotebookDocumentAttributes(string language) + { + Language = language; + } + + public NotebookDocumentAttributes(string language, DocumentUri uri) + { + Language = language; + Uri = uri; + } + + public NotebookDocumentAttributes(DocumentUri uri, string scheme, string notebookType) + { + Uri = uri; + Scheme = scheme; + NotebookType = notebookType; + } + + public DocumentUri Uri { get; } + public string? Scheme { get; } + public string? NotebookType { get; } + public string? Language { get; } + + public bool Equals(NotebookDocumentAttributes? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Uri.Equals(other.Uri) && Scheme == other.Scheme && NotebookType == other.NotebookType; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((NotebookDocumentAttributes) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = Uri.GetHashCode(); + hashCode = ( hashCode * 397 ) ^ ( Scheme != null ? Scheme.GetHashCode() : 0 ); + hashCode = ( hashCode * 397 ) ^ ( NotebookType != null ? NotebookType.GetHashCode() : 0 ); + hashCode = ( hashCode * 397 ) ^ ( Language != null ? Language.GetHashCode() : 0 ); + return hashCode; + } + } + + public static bool operator ==(NotebookDocumentAttributes? left, NotebookDocumentAttributes? right) => Equals(left, right); + + public static bool operator !=(NotebookDocumentAttributes? left, NotebookDocumentAttributes? right) => !Equals(left, right); +} diff --git a/src/Protocol/Features/Document/CallHierarchyFeature.cs b/src/Protocol/Features/Document/CallHierarchyFeature.cs index 73f0949dd..6e49ee177 100644 --- a/src/Protocol/Features/Document/CallHierarchyFeature.cs +++ b/src/Protocol/Features/Document/CallHierarchyFeature.cs @@ -112,8 +112,8 @@ public abstract record CallHierarchyBaseCallParams : ICanBeResolved JToken? ICanBeResolved.Data { - get => Item.GetRawData(); - init => Item.SetRawData(value); + get => Item?.GetRawData(); + init => Item?.SetRawData(value); } } @@ -124,8 +124,8 @@ public abstract record CallHierarchyBaseCallParams : ICanBeResolved JToken? ICanBeResolved.Data { - get => Item.GetRawData(); - init => Item.SetRawData(value); + get => Item?.GetRawData(); + init => Item?.SetRawData(value); } } diff --git a/src/Protocol/Features/Document/CodeActionFeature.cs b/src/Protocol/Features/Document/CodeActionFeature.cs index 19bf652b9..36ca7aac9 100644 --- a/src/Protocol/Features/Document/CodeActionFeature.cs +++ b/src/Protocol/Features/Document/CodeActionFeature.cs @@ -30,7 +30,7 @@ namespace Models [RegistrationOptions(typeof(CodeActionRegistrationOptions))] [Capability(typeof(CodeActionCapability))] [Resolver(typeof(CodeAction))] - public partial record CodeActionParams : ITextDocumentIdentifierParams, IPartialItemsRequest, + public partial record CodeActionParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams { /// @@ -49,6 +49,9 @@ public partial record CodeActionParams : ITextDocumentIdentifierParams, IPartial public CodeActionContext Context { get; init; } = null!; } + // marker class is required + public partial class CommandOrCodeActionContainer {} + /// /// Contains additional diagnostic information about the context in which /// a code action is run. @@ -72,6 +75,14 @@ public record CodeActionContext /// [Optional] public Container? Only { get; init; } + + /// + /// The reason why code actions were requested. + /// + /// @since 3.17.0 + /// + [Optional] + public CodeActionTriggerKind? TriggerKind { get; init; } } [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] @@ -414,6 +425,35 @@ public readonly partial struct CodeActionKind /// Base kind for an organize imports source action: `source.organizeImports` /// public static CodeActionKind SourceOrganizeImports { get; } = new CodeActionKind("source.organizeImports"); + + /// + /// Base kind for a 'fix all' source action: `source.fixAll`. + /// + /// 'Fix all' actions automatically fix errors that have a clear fix that + /// do not require user input. They should not suppress errors or perform + /// unsafe fixes such as generating new types or classes. + /// + /// @since 3.17.0 + /// + public static CodeActionKind SourceFixAll { get; } = new CodeActionKind("source.fixAll"); + } + + + [JsonConverter(typeof(NumberEnumConverter))] + public enum CodeActionTriggerKind + { + /// + /// Code actions were explicitly requested by the user or by an extension. + /// + Invoked = 1, + + /// + /// Code actions were requested automatically. + /// + /// This typically happens when current selection in a file changes, but can + /// also be triggered when file content changes. + /// + Automatic = 2 } } diff --git a/src/Protocol/Features/Document/CodeLensFeature.cs b/src/Protocol/Features/Document/CodeLensFeature.cs index 66d7ea1d5..fa9af0f21 100644 --- a/src/Protocol/Features/Document/CodeLensFeature.cs +++ b/src/Protocol/Features/Document/CodeLensFeature.cs @@ -25,7 +25,7 @@ namespace Models [RegistrationOptions(typeof(CodeLensRegistrationOptions))] [Capability(typeof(CodeLensCapability))] [Resolver(typeof(CodeLens))] - public partial record CodeLensParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, IPartialItemsRequest + public partial record CodeLensParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, IPartialItemsRequest { /// /// The document to request code lens for. @@ -33,6 +33,9 @@ public partial record CodeLensParams : ITextDocumentIdentifierParams, IWorkDoneP public TextDocumentIdentifier TextDocument { get; init; } = null!; } + // marker class is required + public partial class CodeLensContainer {} + /// /// 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. @@ -108,10 +111,7 @@ public override StaticOptions Convert(CodeLensRegistrationOptions source) } } } - } - - namespace Models - { + [Parallel] [Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace")] diff --git a/src/Protocol/Features/Document/ColorFeature.cs b/src/Protocol/Features/Document/ColorFeature.cs index ee8d60b24..457691592 100644 --- a/src/Protocol/Features/Document/ColorFeature.cs +++ b/src/Protocol/Features/Document/ColorFeature.cs @@ -20,7 +20,7 @@ namespace Models [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(DocumentColorRegistrationOptions))] [Capability(typeof(ColorProviderCapability))] - public partial record DocumentColorParams : IPartialItemsRequest, ColorInformation>, IWorkDoneProgressParams + public partial record DocumentColorParams : IPartialItemsRequest?, ColorInformation>, IWorkDoneProgressParams { /// /// The text document. @@ -76,7 +76,7 @@ public partial record ColorPresentation /// /// An [edit](#TextEdit) which is applied to a document when selecting - /// this presentation for the color. When `falsy` the [label](#ColorPresentation.label) + /// this presentation for the color. When omitted the [label](#ColorPresentation.label) /// is used. /// [Optional] diff --git a/src/Protocol/Features/Document/CompletionFeature.cs b/src/Protocol/Features/Document/CompletionFeature.cs index 0f13e8824..d3e2a8246 100644 --- a/src/Protocol/Features/Document/CompletionFeature.cs +++ b/src/Protocol/Features/Document/CompletionFeature.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection; using MediatR; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -28,7 +29,7 @@ namespace Models GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) ] [RegistrationOptions(typeof(CompletionRegistrationOptions)), Capability(typeof(CompletionCapability)), Resolver(typeof(CompletionItem))] - public partial record CompletionParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + public partial record CompletionParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsWithInitialValueRequest { /// /// The completion context. This is only available it the client specifies to send @@ -45,7 +46,7 @@ public partial record CompletionParams : TextDocumentPositionParams, IWorkDonePr GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "CompletionResolve"), GenerateHandlerMethods, GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)), - GenerateContainer("CompletionList"), + GenerateContainer("CompletionList", GenerateImplicitConversion = false), GenerateTypedData ] [Capability(typeof(CompletionCapability))] @@ -58,6 +59,14 @@ public partial record CompletionItem : ICanBeResolved, IRequest, /// public string Label { get; init; } + /// + /// Additional details for the label + /// + /// @since 3.17.0 - proposed state + /// + [Optional] + public CompletionItemLabelDetails? LabelDetails { get; init; } + /// /// The kind of this completion item. Based of the kind /// an icon is chosen by the editor. @@ -104,14 +113,14 @@ public partial record CompletionItem : ICanBeResolved, IRequest, /// /// A string that shoud be used when comparing this item - /// with other items. When `falsy` the label is used. + /// with other items. When omitted the label is used. /// [Optional] public string? SortText { get; init; } /// /// A string that should be used when filtering a set of - /// completion items. When `falsy` the label is used. + /// completion items. When omitted the label is used. /// [Optional] @@ -119,7 +128,7 @@ public partial record CompletionItem : ICanBeResolved, IRequest, /// /// A string that should be inserted a document when selecting - /// this completion. When `falsy` the label is used. + /// this completion. When omitted the label is used. /// [Optional] @@ -168,6 +177,21 @@ public partial record CompletionItem : ICanBeResolved, IRequest, [Optional] public TextEditOrInsertReplaceEdit? TextEdit { get; init; } + /// + /// The edit text used if the completion item is part of a CompletionList and + /// CompletionList defines an item default for the text edit range. + /// + /// Clients will only honor this property if they opt into completion list + /// item defaults using the capability `completionList.itemDefaults`. + /// + /// If not provided and a list's default range is provided the label + /// property is used as a text. + /// + /// @since 3.17.0 + /// + [Optional] + public string? TextEditText { get; init; } + /// /// An optional array of additional text edits that are applied when /// selecting this completion. Edits must not overlap with the main edit @@ -199,7 +223,7 @@ public partial record CompletionItem : ICanBeResolved, IRequest, [Optional] public JToken? Data { get; init; } - private string DebuggerDisplay => $"[{Kind}] {Label}{( Tags?.Any() == true ? $" tags: {string.Join(", ", Tags.Select(z => z.ToString()))}" : "" )}"; + private string DebuggerDisplay => $"[{Kind}] {Label}{(Tags?.Any() == true ? $" tags: {string.Join(", ", Tags.Select(z => z.ToString()))}" : "")}"; /// public override string ToString() => DebuggerDisplay; @@ -288,6 +312,15 @@ public partial class CompletionRegistrationOptions : IWorkDoneProgressOptions, I [Optional] public Container? AllCommitCharacters { get; set; } + /// + /// The server supports the following `CompletionItem` specific + /// capabilities. + /// + /// @since 3.17.0 - proposed state + /// + [Optional] + public CompletionRegistrationCompletionItemOptions? CompletionItem { get; set; } + class CompletionRegistrationOptionsConverter : RegistrationOptionsConverterBase { private readonly IHandlersManager _handlersManager; @@ -299,16 +332,31 @@ public CompletionRegistrationOptionsConverter(IHandlersManager handlersManager) public override StaticOptions Convert(CompletionRegistrationOptions source) { - return new() { + return new() + { ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ICompletionResolveHandler)), AllCommitCharacters = source.AllCommitCharacters, TriggerCharacters = source.TriggerCharacters, WorkDoneProgress = source.WorkDoneProgress, + CompletionItem = source.CompletionItem }; } } } + public class CompletionRegistrationCompletionItemOptions + { + /// + /// The server has support for completion item label + /// details (see also `CompletionItemLabelDetails`) when receiving + /// a completion item in a resolve call. + /// + /// @since 3.17.0 + /// + [Optional] + public bool? LabelDetailsSupport { get; set; } + } + public record CompletionContext { /// @@ -353,7 +401,7 @@ public enum CompletionTriggerKind /// Represents a collection of [completion items](#CompletionItem) to be presented /// in the editor. /// - [JsonConverter(typeof(CompletionListConverter))] + [JsonConverter(typeof(Converter))] public partial class CompletionList { public CompletionList(bool isIncomplete) : this(Enumerable.Empty(), isIncomplete) @@ -377,13 +425,99 @@ public CompletionList(IEnumerable items, bool isIncomplete) : ba /// public IEnumerable Items => this; + /// + /// In many cases the items of an actual completion result share the same + /// value for properties like `commitCharacters` or the range of a text + /// edit. A completion list can therefore define item defaults which will + /// be used if a completion item itself doesn't specify the value. + /// + /// If a completion list specifies a default value and a completion item + /// also specifies a corresponding value the one from the item is used. + /// + /// Servers are only allowed to return default values if the client + /// signals support for this via the `completionList.itemDefaults` + /// capability. + /// + /// @since 3.17.0 + /// + [Optional] + public CompletionListItemDefaults? ItemDefaults { get; set; } + public static CompletionList? From(CompletionList? list) where T : class?, IHandlerIdentity? - => list switch { - not null => new(list.Items.Select(CompletionItem.From)!, list.IsIncomplete), - _ => null + => list switch + { + not null => new(list.Items.Select(CompletionItem.From)!, list.IsIncomplete) + { + ItemDefaults = list.ItemDefaults + }, + _ => null + }; + + public static CompletionList From(CompletionList? source, IEnumerable? result) + => new((source?.Items ?? Array.Empty()).Concat(result ?? Array.Empty())) + { + ItemDefaults = source?.ItemDefaults }; + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, CompletionList? value, JsonSerializer serializer) + { + if (!value.IsIncomplete && value.ItemDefaults is null) + { + serializer.Serialize(writer, value.Items.ToArray()); + return; + } + + writer.WriteStartObject(); + writer.WritePropertyName("isIncomplete"); + writer.WriteValue(value.IsIncomplete); + + writer.WritePropertyName("items"); + writer.WriteStartArray(); + foreach (var item in value.Items) + { + serializer.Serialize(writer, item); + } + writer.WriteEndArray(); + + if (value.ItemDefaults is { }) + { + writer.WritePropertyName("itemDefaults"); + serializer.Serialize(writer, value.ItemDefaults); + } + + writer.WriteEndObject(); + } + + public override CompletionList? ReadJson( + JsonReader reader, Type objectType, CompletionList? existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.StartArray) + { + var array = JArray.Load(reader).ToObject>(serializer); + return new CompletionList(array); + } + + if (reader.TokenType == JsonToken.Null) + { + return null; + } + + var result = JObject.Load(reader); + var items = result["items"].ToObject>(serializer); + return new CompletionList(items, result["isIncomplete"]?.Value() ?? false) + { + ItemDefaults = result["itemDefaults"]?.ToObject() + }; + } + + public override bool CanRead => true; + } } + [JsonConverter(typeof(TypedCompletionListConverter))] public partial class CompletionList { public CompletionList(bool isIncomplete) : this(isIncomplete, Enumerable.Empty>()) @@ -412,12 +546,133 @@ public CompletionList(bool isIncomplete, params CompletionItem[] items) : bas /// public IEnumerable> Items => this; + /// + /// In many cases the items of an actual completion result share the same + /// value for properties like `commitCharacters` or the range of a text + /// edit. A completion list can therefore define item defaults which will + /// be used if a completion item itself doesn't specify the value. + /// + /// If a completion list specifies a default value and a completion item + /// also specifies a corresponding value the one from the item is used. + /// + /// Servers are only allowed to return default values if the client + /// signals support for this via the `completionList.itemDefaults` + /// capability. + /// + /// @since 3.17.0 + /// + [Optional] + public CompletionListItemDefaults? ItemDefaults { get; set; } + public static CompletionList? Create(CompletionList? list) - => list switch { + => list switch + { not null => - new(list.IsIncomplete, list.Items.Select(CompletionItem.From)!), + new(list.IsIncomplete, list.Items.Select(CompletionItem.From)!) + { + ItemDefaults = list.ItemDefaults + }, _ => null }; + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("container")] + public static implicit operator CompletionList?(CompletionList? container) => container switch + { + not null => new CompletionList(container.Select(value => (CompletionItem)value), container.IsIncomplete) + { + ItemDefaults = container.ItemDefaults + }, + _ => null + }; + + } + + internal class TypedCompletionListConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + serializer.Serialize(writer, (CompletionList?)value); + } + + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + { + var completionList = serializer.Deserialize(reader); + return objectType.GetMethod(nameof(CompletionList.Create), BindingFlags.Static | BindingFlags.Public)! + .Invoke(null, new object[] { completionList })!; + } + + public override bool CanConvert(Type objectType) + { + return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(CompletionList<>); + } + + public override bool CanRead => true; + } + + public record CompletionListItemDefaults + { + /// + /// A default commit character set. + /// + /// @since 3.17.0 + /// + [Optional] + public Container? CommitCharacters { get; init; } + + /// + /// A default edit range + /// + /// @since 3.17.0 + /// + [Optional] + public RangeOrEditRange? EditRange { get; init; } + + /// + /// A default insert text format + /// + /// @since 3.17.0 + /// + [Optional] + public InsertTextFormat? InsertTextFormat { get; init; } + + /// + /// A default insert text mode + /// + /// @since 3.17.0 + /// + public InsertTextMode? InsertTextMode { get; init; } + + /// + /// A default data value. + /// + /// @since 3.17.0 + /// + [Optional] + public JToken? Data { get; init; } + } + + /// + /// Additional details for a completion item label. + /// + /// @since 3.17.0 - proposed state + /// + public record CompletionItemLabelDetails + { + /// + /// An optional string which is rendered less prominently directly after + /// {@link CompletionItem.label label}, without any spacing. Should be + /// used for function signatures or type annotations. + /// + [Optional] + public string? Detail { get; init; } + + /// + /// An optional string which is rendered less prominently after + /// {@link CompletionItemLabelDetails.detail}. Should be used for fully qualified + /// names or file path. + /// + [Optional] + public string? Description { get; init; } } } @@ -444,6 +699,46 @@ public partial class CompletionCapability : DynamicCapability /// [Optional] public bool ContextSupport { get; set; } + + /// + /// The client's default when the completion item doesn't provide a + /// `insertTextMode` property. + /// + /// @since 3.17.0 + /// + [Optional] + public InsertTextMode? InsertTextMode { get; set; } + + /// + /// The client supports the following `CompletionList` specific + /// capabilities. + /// + /// @since 3.17.0 + /// + [Optional] + public CompletionListCapabilityOptions? CompletionList { get; set; } + } + + /// + /// The client supports the following `CompletionList` specific + /// capabilities. + /// + /// @since 3.17.0 + /// + public class CompletionListCapabilityOptions + { + /// + /// The client supports the following itemDefaults on + /// a completion list. + /// + /// The value lists the supported property names of the + /// `CompletionList.itemDefaults` object. If omitted + /// no properties are supported. + /// + /// @since 3.17.0 + /// + [Optional] + public Container? ItemDefaults { get; set; } } public class CompletionItemCapabilityOptions @@ -532,6 +827,15 @@ public class CompletionItemCapabilityOptions /// [Optional] public CompletionItemInsertTextModeSupportCapabilityOptions? InsertTextModeSupport { get; set; } + + /// + /// The client has support for completion item label + /// details (see also `CompletionItemLabelDetails`). + /// + /// @since 3.17.0 + /// + [Optional] + public bool LabelDetailsSupport { get; set; } } public class CompletionItemInsertTextModeSupportCapabilityOptions diff --git a/src/Protocol/Features/Document/DeclarationFeature.cs b/src/Protocol/Features/Document/DeclarationFeature.cs index 38654f594..f959bad58 100644 --- a/src/Protocol/Features/Document/DeclarationFeature.cs +++ b/src/Protocol/Features/Document/DeclarationFeature.cs @@ -18,7 +18,7 @@ namespace Models [RegistrationOptions(typeof(DeclarationRegistrationOptions))] [Capability(typeof(DeclarationCapability))] public partial record DeclarationParams : TextDocumentPositionParams, IWorkDoneProgressParams, - IPartialItemsRequest; + IPartialItemsRequest; [GenerateRegistrationOptions(nameof(ServerCapabilities.DeclarationProvider))] [RegistrationName(TextDocumentNames.Declaration)] diff --git a/src/Protocol/Features/Document/DefinitionFeature.cs b/src/Protocol/Features/Document/DefinitionFeature.cs index 8da8b62d4..ea10d2a37 100644 --- a/src/Protocol/Features/Document/DefinitionFeature.cs +++ b/src/Protocol/Features/Document/DefinitionFeature.cs @@ -18,7 +18,7 @@ namespace Models [RegistrationOptions(typeof(DefinitionRegistrationOptions))] [Capability(typeof(DefinitionCapability))] public partial record DefinitionParams : TextDocumentPositionParams, IWorkDoneProgressParams, - IPartialItemsRequest; + IPartialItemsRequest; [GenerateRegistrationOptions(nameof(ServerCapabilities.DefinitionProvider))] [RegistrationName(TextDocumentNames.Definition)] diff --git a/src/Protocol/Features/Document/DiagnosticsFeature.cs b/src/Protocol/Features/Document/DiagnosticsFeature.cs new file mode 100644 index 000000000..bf7cce533 --- /dev/null +++ b/src/Protocol/Features/Document/DiagnosticsFeature.cs @@ -0,0 +1,533 @@ +using System.Collections.Immutable; +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.Generation; +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.Diagnostics, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(DiagnosticsRegistrationOptions))] + [Capability(typeof(DiagnosticClientCapabilities))] + public partial record DocumentDiagnosticParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, + IPartialItemWithInitialValueRequest + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; init; } = null!; + + /// + /// The additional identifier provided during registration. + /// + [Optional] + public string? Identifier { get; init; } + + /// + /// The result id of a previous response if provided. + /// + [Optional] + public string? PreviousResultId { get; init; } + } + + [Parallel] + [Method(WorkspaceNames.Diagnostics, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(DiagnosticsRegistrationOptions))] + [Capability(typeof(DiagnosticWorkspaceClientCapabilities))] + public partial record WorkspaceDiagnosticParams : IWorkDoneProgressParams, + IPartialItemWithInitialValueRequest + { + /// + /// The additional identifier provided during registration. + /// + [Optional] + public string? Identifier { get; init; } + + /// + /// The result id of a previous response if provided. + /// + public Container PreviousResultIds { get; init; } + } + + + [Parallel] + [Method(WorkspaceNames.DiagnosticRefresh, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(CodeLensWorkspaceClientCapabilities))] + public partial record DiagnosticRefreshParams : IRequest; + + public interface IDiagnosticReport + { + /// + /// A full document diagnostic report. + /// + DocumentDiagnosticReportKind Kind { get; } + } + + /// + /// The result of a document diagnostic pull request. A report can + /// either be a full report containing all diagnostics for the + /// requested document or a unchanged report indicating that nothing + /// has changed in terms of diagnostics in comparison to the last + /// pull request. + /// + /// @since 3.17.0 + /// + [JsonConverter(typeof(Converter))] + public abstract partial record RelatedDocumentDiagnosticReport(DocumentDiagnosticReportKind Kind) : DocumentDiagnosticReportPartialResult, + IDiagnosticReport + { + /// + /// The report kind + /// + public DocumentDiagnosticReportKind Kind { get; } = Kind; + + public static RelatedDocumentDiagnosticReport From(RelatedDocumentDiagnosticReport original, DocumentDiagnosticReportPartialResult? result) + { + var docs = original.RelatedDocuments?.ToBuilder() ?? ImmutableDictionary.Empty.ToBuilder(); + foreach (var item in result?.RelatedDocuments ?? ImmutableDictionary.Empty) + { + if (docs.ContainsKey(item.Key)) + { + docs[item.Key] = item.Value; + } + else + { + docs.Add(item); + } + } + + return original with { RelatedDocuments = docs.ToImmutable() }; + } + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, RelatedDocumentDiagnosticReport? value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override RelatedDocumentDiagnosticReport ReadJson( + JsonReader reader, Type objectType, RelatedDocumentDiagnosticReport? existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + } + } + + [JsonConverter(typeof(Converter))] + public abstract partial record DocumentDiagnosticReport(DocumentDiagnosticReportKind Kind) : IDiagnosticReport + { + /// + /// The report kind + /// + public DocumentDiagnosticReportKind Kind { get; } = Kind; + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, DocumentDiagnosticReport value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override DocumentDiagnosticReport ReadJson( + JsonReader reader, Type objectType, DocumentDiagnosticReport existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + } + } + + /// + /// The document diagnostic report kinds. + /// + /// @since 3.17.0 + /// + [StringEnum] + public readonly partial struct DocumentDiagnosticReportKind + { + /// + /// A diagnostic report with a full + /// set of problems. + /// + public static DocumentDiagnosticReportKind Full { get; } = new("full"); + + /// + /// A report indicating that the last + /// returned report is still accurate. + /// + public static DocumentDiagnosticReportKind Unchanged { get; } = new("unchanged"); + } + + /// + /// A diagnostic report with a full set of problems. + /// + /// @since 3.17.0 + /// + public interface IFullDocumentDiagnosticReport : IDiagnosticReport + { + /// + /// An optional result id. If provided it will + /// be sent on the next diagnostic request for the + /// same document. + /// + string? ResultId { get; init; } + + /// + /// The actual items. + /// + Container Items { get; init; } + } + + /// + /// A diagnostic report with a full set of problems. + /// + /// @since 3.17.0 + /// + public partial record FullDocumentDiagnosticReport() : DocumentDiagnosticReport(DocumentDiagnosticReportKind.Full), IFullDocumentDiagnosticReport + { + /// + /// An optional result id. If provided it will + /// be sent on the next diagnostic request for the + /// same document. + /// + [Optional] + public string? ResultId { get; init; } + + /// + /// The actual items. + /// + public Container Items { get; init; } + } + + /// + /// A diagnostic report indicating that the last returned + /// report is still accurate. + /// + /// @since 3.17.0 + /// + public interface IUnchangedDocumentDiagnosticReport : IDiagnosticReport + { + /// + /// A result id which will be sent on the next + /// diagnostic request for the same document. + /// + string ResultId { get; init; } + } + + /// + /// A diagnostic report indicating that the last returned + /// report is still accurate. + /// + /// @since 3.17.0 + /// + public partial record UnchangedDocumentDiagnosticReport() : DocumentDiagnosticReport(DocumentDiagnosticReportKind.Unchanged), + IUnchangedDocumentDiagnosticReport + { + /// + /// A result id which will be sent on the next + /// diagnostic request for the same document. + /// + public string ResultId { get; init; } + } + + /// + /// A full diagnostic report with a set of related documents. + /// + /// @since 3.17.0 + /// + public partial record RelatedFullDocumentDiagnosticReport() : RelatedDocumentDiagnosticReport(DocumentDiagnosticReportKind.Full), + IFullDocumentDiagnosticReport + { + /// + /// The actual items. + /// + public Container Items { get; init; } + + /// + /// An optional result id. If provided it will + /// be sent on the next diagnostic request for the + /// same document. + /// + public string? ResultId { get; init; } + } + + /// + /// An unchanged diagnostic report with a set of related documents. + /// + /// @since 3.17.0 + /// + public partial record RelatedUnchangedDocumentDiagnosticReport() : RelatedDocumentDiagnosticReport(DocumentDiagnosticReportKind.Unchanged), + IUnchangedDocumentDiagnosticReport + { + /// + /// A result id which will be sent on the next + /// diagnostic request for the same document. + /// + public string ResultId { get; init; } + } + + /// + /// A partial result for a document diagnostic report. + /// + /// @since 3.17.0 + /// + public partial record DocumentDiagnosticReportPartialResult + { + /// + /// Diagnostics of related documents. This information is useful + /// in programming languages where code in a file A can generate + /// diagnostics in a file B which A depends on. An example of + /// such a language is C/C++ where marco definitions in a file + /// a.cpp and result in errors in a header file b.hpp. + /// + /// @since 3.17.0 + /// + public ImmutableDictionary? RelatedDocuments { get; init; } + + public static DocumentDiagnosticReportPartialResult? From(DocumentDiagnosticReport? result) + { + if (result is null) + { + return null; + } + + return null; + } + } + + /// + /// Cancellation data returned from a diagnostic request. + /// + /// @since 3.17.0 + /// + public partial record DiagnosticServerCancellationData + { + public bool RetriggerRequest { get; init; } + } + + /// + /// A previous result id in a workspace pull request. + /// + /// @since 3.17.0 + /// + public partial record PreviousResultId + { + /// + /// The URI for which the client knowns a + /// result id. + /// + public DocumentUri Uri { get; init; } + + /// + /// The value of the previous result id. + /// + public string Value { get; init; } + } + + /// + /// A workspace diagnostic report. + /// + /// @since 3.17.0 + /// + public partial record WorkspaceDiagnosticReport : WorkspaceDiagnosticReportPartialResult + { + internal WorkspaceDiagnosticReport() + { + } + + internal WorkspaceDiagnosticReport(WorkspaceDiagnosticReportPartialResult partialResult) + { + Items = partialResult.Items; + } + + public static WorkspaceDiagnosticReport From(WorkspaceDiagnosticReport original, WorkspaceDiagnosticReportPartialResult? result) + { + return new WorkspaceDiagnosticReport() + { + Items = new Container( + original.Items.Concat(result?.Items ?? Array.Empty()) + ) + }; + } + } + + + [JsonConverter(typeof(Converter))] + public abstract partial record WorkspaceDocumentDiagnosticReport(DocumentDiagnosticReportKind Kind) : IDiagnosticReport + { + /// + /// The report kind + /// + public DocumentDiagnosticReportKind Kind { get; } = Kind; + + /// + /// The URI for which diagnostic information is reported. + /// + public DocumentUri Uri { get; init; } + + /// + /// The version number for which the diagnostics are reported. + /// If the document is not marked as open `null` can be provided. + /// + public int? Version { get; init; } + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, WorkspaceDocumentDiagnosticReport value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override WorkspaceDocumentDiagnosticReport ReadJson( + JsonReader reader, Type objectType, WorkspaceDocumentDiagnosticReport existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + throw new NotImplementedException(); + } + } + } + + /// + /// A full document diagnostic report for a workspace diagnostic result. + /// + /// @since 3.17.0 + /// + public partial record WorkspaceFullDocumentDiagnosticReport() : WorkspaceDocumentDiagnosticReport(DocumentDiagnosticReportKind.Full), + IFullDocumentDiagnosticReport + { + /// + /// An optional result id. If provided it will + /// be sent on the next diagnostic request for the + /// same document. + /// + public string? ResultId { get; init; } + + /// + /// The actual items. + /// + public Container Items { get; init; } + } + + /// + /// An unchanged document diagnostic report for a workspace diagnostic result. + /// + /// @since 3.17.0 + /// + public partial record WorkspaceUnchangedDocumentDiagnosticReport() : WorkspaceDocumentDiagnosticReport(DocumentDiagnosticReportKind.Unchanged), + IUnchangedDocumentDiagnosticReport + { + /// + /// A result id which will be sent on the next + /// diagnostic request for the same document. + /// + public string ResultId { get; init; } + }; + + /// + /// A partial result for a workspace diagnostic report. + /// + /// @since 3.17.0 + /// + public partial record WorkspaceDiagnosticReportPartialResult + { + public Container Items { get; init; } + + internal WorkspaceDiagnosticReportPartialResult() + { + } + + internal WorkspaceDiagnosticReportPartialResult(WorkspaceDiagnosticReport partialResult) + { + Items = partialResult.Items; + } + } + + + [GenerateRegistrationOptions(nameof(ServerCapabilities.DiagnosticProvider))] + [RegistrationName(TextDocumentNames.Diagnostics)] + public partial class DiagnosticsRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// An optional identifier under which the diagnostics are + /// managed by the client. + /// + [Optional] + public string? Identifier { get; set; } + + /// + /// Whether the language has inter file dependencies meaning that + /// editing code in one file can result in a different diagnostic + /// set in another file. Inter file dependencies are common for + /// most programming languages and typically uncommon for linters. + /// + public bool InterFileDependencies { get; set; } + + /// + /// The server provides support for workspace diagnostics as well. + /// + public bool WorkspaceDiagnostics { get; set; } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Diagnostic))] + public partial class DiagnosticClientCapabilities : DynamicCapability + { + /// + /// Whether the clients supports related documents for document diagnostic + /// pulls. + /// + [Optional] + public bool RelatedDocumentSupport { get; set; } + } + + /// + /// Capabilities specific to the code lens requests scoped to the + /// workspace. + /// + /// @since 3.17.0. + /// + [CapabilityKey(nameof(ClientCapabilities.Workspace), nameof(WorkspaceClientCapabilities.Diagnostics))] + public class DiagnosticWorkspaceClientCapabilities : ICapability + { + /// + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// pulled diagnostics currently shown. It should be used with absolute care + /// and is useful for situation where a server for example detects a project + /// wide change that requires such a calculation. + /// + [Optional] + public bool RefreshSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/DocumentHighlightFeature.cs b/src/Protocol/Features/Document/DocumentHighlightFeature.cs index 552354a3d..484a1edaf 100644 --- a/src/Protocol/Features/Document/DocumentHighlightFeature.cs +++ b/src/Protocol/Features/Document/DocumentHighlightFeature.cs @@ -21,6 +21,8 @@ namespace Models [Capability(typeof(DocumentHighlightCapability))] public partial record DocumentHighlightParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest; + + public partial class DocumentHighlightContainer { } /// /// A document highlight is a range inside a text document which deserves diff --git a/src/Protocol/Features/Document/DocumentLinkFeature.cs b/src/Protocol/Features/Document/DocumentLinkFeature.cs index 5dd5dd796..eeb025de4 100644 --- a/src/Protocol/Features/Document/DocumentLinkFeature.cs +++ b/src/Protocol/Features/Document/DocumentLinkFeature.cs @@ -24,7 +24,7 @@ namespace Models [RegistrationOptions(typeof(DocumentLinkRegistrationOptions))] [Capability(typeof(DocumentLinkCapability))] [Resolver(typeof(DocumentLink))] - public partial record DocumentLinkParams : ITextDocumentIdentifierParams, IPartialItemsRequest, + public partial record DocumentLinkParams : ITextDocumentIdentifierParams, IPartialItemsRequest, IWorkDoneProgressParams { /// @@ -33,6 +33,8 @@ public partial record DocumentLinkParams : ITextDocumentIdentifierParams, IParti public TextDocumentIdentifier TextDocument { get; init; } = null!; } + public partial class DocumentLinkContainer { } + /// /// 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. diff --git a/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs b/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs index 548d6704d..ab924e992 100644 --- a/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs +++ b/src/Protocol/Features/Document/DocumentOnTypeFormattingFeature.cs @@ -28,18 +28,23 @@ public partial record DocumentOnTypeFormattingParams : ITextDocumentIdentifierPa public TextDocumentIdentifier TextDocument { get; init; } = null!; /// - /// The position at which this request was sent. + /// The position around which the on type formatting should happen. + /// This is not necessarily the exact position where the character denoted + /// by the property `ch` got typed. /// public Position Position { get; init; } = null!; /// - /// The character that has been typed. + /// The character that has been typed that triggered the formatting + /// on type request.That is not necessarily the last character that + /// got inserted into the document since the client could auto insert + /// characters as well(e.g.like automatic brace completion). /// [JsonProperty("ch")] public string Character { get; init; } = null!; /// - /// The format options. + /// The formatting options. /// public FormattingOptions Options { get; init; } = null!; } @@ -49,7 +54,7 @@ public partial record DocumentOnTypeFormattingParams : ITextDocumentIdentifierPa public partial class DocumentOnTypeFormattingRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { /// - /// A character on which formatting should be triggered, like `}`. + /// A character on which formatting should be triggered, like `{`. /// public string FirstTriggerCharacter { get; set; } = null!; diff --git a/src/Protocol/Features/Document/DocumentSymbolFeature.cs b/src/Protocol/Features/Document/DocumentSymbolFeature.cs index 067e65fbd..2ed9ad534 100644 --- a/src/Protocol/Features/Document/DocumentSymbolFeature.cs +++ b/src/Protocol/Features/Document/DocumentSymbolFeature.cs @@ -22,7 +22,7 @@ namespace Models [RegistrationOptions(typeof(DocumentSymbolRegistrationOptions))] [Capability(typeof(DocumentSymbolCapability))] public partial record DocumentSymbolParams : ITextDocumentIdentifierParams, - IPartialItemsRequest, + IPartialItemsRequest, IWorkDoneProgressParams { /// @@ -30,6 +30,8 @@ public partial record DocumentSymbolParams : ITextDocumentIdentifierParams, /// public TextDocumentIdentifier TextDocument { get; init; } = null!; } + + public partial class SymbolInformationOrDocumentSymbolContainer {} [JsonConverter(typeof(SymbolInformationOrDocumentSymbolConverter))] [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] diff --git a/src/Protocol/Features/Document/FoldingRangeFeature.cs b/src/Protocol/Features/Document/FoldingRangeFeature.cs index 344114a6c..cafe80829 100644 --- a/src/Protocol/Features/Document/FoldingRangeFeature.cs +++ b/src/Protocol/Features/Document/FoldingRangeFeature.cs @@ -7,6 +7,7 @@ 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; @@ -79,6 +80,16 @@ public partial record FoldingRange [Optional] public FoldingRangeKind? Kind { get; init; } + /// + /// The text that the client should show when the specified range is + /// collapsed. If not defined or not supported by the client, a default + /// will be chosen by the client. + /// + /// @since 3.17.0 - proposed + /// + [Optional] + public string? CollapsedText { get; init; } + private string DebuggerDisplay => $"[start: (line: {StartLine}{( StartCharacter.HasValue ? $", char: {StartCharacter}" : string.Empty )}), end: (line: {EndLine}, char: {( EndCharacter.HasValue ? $", char: {EndCharacter}" : string.Empty )})]"; @@ -92,23 +103,23 @@ public override string ToString() /// /// Enum of known range kinds /// - [JsonConverter(typeof(StringEnumConverter))] - public enum FoldingRangeKind + [StringEnum] + public readonly partial struct FoldingRangeKind { /// /// Folding range for a comment /// - [EnumMember(Value = "comment")] Comment, + public static FoldingRangeKind Comment { get; } = new FoldingRangeKind("comment"); /// /// Folding range for a imports or includes /// - [EnumMember(Value = "imports")] Imports, + public static FoldingRangeKind Imports { get; } = new FoldingRangeKind("imports"); /// /// Folding range for a region (e.g. `#region`) /// - [EnumMember(Value = "region")] Region + public static FoldingRangeKind Region { get; } = new FoldingRangeKind("region"); } [GenerateRegistrationOptions(nameof(ServerCapabilities.FoldingRangeProvider))] @@ -137,7 +148,47 @@ public partial class FoldingRangeCapability : DynamicCapability /// 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. /// + [Optional] public bool LineFoldingOnly { get; set; } + + /// + /// Specific options for the folding range kind. + /// + /// @since 3.17.0 + /// + [Optional] + public FoldingRangeCapabilityFoldingRangeKind? FoldingRangeKind { get; set; } + + /// + /// Specific options for the folding range. + /// @since 3.17.0 + /// + [Optional] + public FoldingRangeCapabilityFoldingRange? FoldingRange { get; set; } + } + + public partial class FoldingRangeCapabilityFoldingRangeKind + { + /// + /// The folding range 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. + /// + [Optional] + public Container? ValueSet { get; set; } + } + + public partial class FoldingRangeCapabilityFoldingRange + { + /// + /// If set, the client signals that it supports setting collapsedText on + /// folding ranges to display custom labels instead of the default text. + /// + /// @since 3.17.0 + /// + [Optional] + public bool CollapsedText { get; set; } } } diff --git a/src/Protocol/Features/Document/ImplementationFeature.cs b/src/Protocol/Features/Document/ImplementationFeature.cs index 0d0bf5394..cacc80ac8 100644 --- a/src/Protocol/Features/Document/ImplementationFeature.cs +++ b/src/Protocol/Features/Document/ImplementationFeature.cs @@ -18,7 +18,7 @@ namespace Models [RegistrationOptions(typeof(ImplementationRegistrationOptions))] [Capability(typeof(ImplementationCapability))] public partial record ImplementationParams : TextDocumentPositionParams, IWorkDoneProgressParams, - IPartialItemsRequest; + IPartialItemsRequest; [GenerateRegistrationOptions(nameof(ServerCapabilities.ImplementationProvider))] [RegistrationName(TextDocumentNames.Implementation)] diff --git a/src/Protocol/Features/Document/InlayHintFeature.cs b/src/Protocol/Features/Document/InlayHintFeature.cs new file mode 100644 index 000000000..4fcb3544f --- /dev/null +++ b/src/Protocol/Features/Document/InlayHintFeature.cs @@ -0,0 +1,330 @@ +using System.Collections.ObjectModel; +using System.Diagnostics; +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.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.InlayHint, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "InlayHints"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(InlayHintRegistrationOptions)), Capability(typeof(InlayHintWorkspaceClientCapabilities))] + [Resolver(typeof(InlayHint))] + public partial record InlayHintParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, + IRequest + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; init; } + + /// + /// The visible document range for which inlay hints should be computed. + /// + public Range Range { get; init; } + } + + /// + /// Inlay hint information. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(TextDocumentNames.InlayHintResolve, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "InlayHintResolve")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateTypedData] + [GenerateContainer] + [Capability(typeof(InlayHintWorkspaceClientCapabilities))] + public partial record InlayHint : ICanBeResolved, IRequest, IDoesNotParticipateInRegistration + { + /// + /// The position of this hint. + /// + public Position Position { get; init; } + + /// + /// The label of this hint. A human readable string or an array of + /// InlayHintLabelPart label parts. + /// + /// *Note* that neither the string nor the label part can be empty. + /// + public StringOrInlayHintLabelParts Label { get; init; } + + /// + /// The kind of this hint. Can be omitted in which case the client + /// should fall back to a reasonable default. + /// + public InlayHintKind? Kind { get; init; } + + /// + /// Optional text edits that are performed when accepting this inlay hint. + /// + /// *Note* that edits are expected to change the document so that the inlay + /// hint (or its nearest variant) is now part of the document and the inlay + /// hint itself is now obsolete. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Container? TextEdits { get; init; } + + /// + /// The tooltip text when you hover over this item. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public StringOrMarkupContent? Tooltip { get; init; } + + /// + /// Render padding before the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingLeft { get; init; } + + /// + /// Render padding after the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingRight { get; init; } + + /// + /// A data entry field that is preserved on a document link between a + /// DocumentLinkRequest and a DocumentLinkResolveRequest. + /// + [Optional] + public JToken? Data { get; init; } + + private string DebuggerDisplay => ToString(); + } + + public partial class InlayHintContainer { } + + /// + /// An inlay hint label part allows for interactive and composite labels + /// of inlay hints. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public partial record InlayHintLabelPart + { + /// + /// The value of this label part. + /// + public string Value { get; init; } + + /// + /// The tooltip text when you hover over this label part. Depending on + /// the client capability `inlayHint.resolveSupport` clients might resolve + /// this property late using the resolve request. + /// + [Optional] + public StringOrMarkupContent? Tooltip { get; init; } + + /// + /// An optional source code location that represents this + /// label part. + /// + /// The editor will use this location for the hover and for code navigation + /// features: This part will become a clickable link that resolves to the + /// definition of the symbol at the given location (not necessarily the + /// location itself), it shows the hover that shows at the given location, + /// and it shows a context menu with further code navigation commands. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Location? Location { get; init; } + + /// + /// An optional command for this label part. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Command? Command { get; init; } + + private string DebuggerDisplay => ToString(); + } + + [JsonConverter(typeof(Converter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public record StringOrInlayHintLabelParts + { + public StringOrInlayHintLabelParts(string value) => String = value; + + public StringOrInlayHintLabelParts(IEnumerable inlayHintLabelParts) => InlayHintLabelParts = new(inlayHintLabelParts); + public StringOrInlayHintLabelParts(Container inlayHintLabelParts) => InlayHintLabelParts = new(inlayHintLabelParts); + + public string? String { get; } + public bool HasString => InlayHintLabelParts is null; + public Container? InlayHintLabelParts { get; } + public bool HasInlayHintLabelParts => InlayHintLabelParts is { }; + + public static implicit operator StringOrInlayHintLabelParts?(string? value) => value is null ? null : new StringOrInlayHintLabelParts(value); + + public static implicit operator StringOrInlayHintLabelParts?(Container? parts) => + parts is null ? null : new StringOrInlayHintLabelParts(parts); + public static implicit operator StringOrInlayHintLabelParts?(List? parts) => + parts is null ? null : new StringOrInlayHintLabelParts(parts); + public static implicit operator StringOrInlayHintLabelParts?(Collection? parts) => + parts is null ? null : new StringOrInlayHintLabelParts(parts); + + private string DebuggerDisplay => + $"{( HasString ? String : HasInlayHintLabelParts ? string.Join(", ", InlayHintLabelParts!.Select(z => z.ToString())) : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, StringOrInlayHintLabelParts value, JsonSerializer serializer) + { + if (value.HasString) + { + writer.WriteValue(value.String); + } + else + { + serializer.Serialize(writer, value.InlayHintLabelParts ?? Array.Empty()); + } + } + + public override StringOrInlayHintLabelParts ReadJson( + JsonReader reader, Type objectType, StringOrInlayHintLabelParts existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.StartArray) + { + var result = JArray.Load(reader); + return new StringOrInlayHintLabelParts(result.ToObject>()); + } + + if (reader.TokenType == JsonToken.String) + { + return new StringOrInlayHintLabelParts(( reader.Value as string )!); + } + + return ""; + } + + public override bool CanRead => true; + } + } + + /// + /// Inlay hint kinds. + /// + /// @since 3.17.0 + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum InlayHintKind + { + /// + /// An inlay hint that for a type annotation. + /// + Type = 1, + + /// + /// An inlay hint that is for a parameter. + /// + Parameter = 2 + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.InlayHintProvider))] + [RegistrationOptionsConverter(typeof(InlayHintRegistrationOptionsConverter))] + [RegistrationName(TextDocumentNames.InlayHint)] + public partial class InlayHintRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + /// + /// The server provides support to resolve additional + /// information for an inlay hint item. + /// + [Optional] + public bool ResolveProvider { get; set; } + + private class InlayHintRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public InlayHintRegistrationOptionsConverter(IHandlersManager handlersManager) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(InlayHintRegistrationOptions source) + { + return new() + { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IInlayHintResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } + } + } + + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.InlayHint))] + public partial class InlayHintWorkspaceClientCapabilities : DynamicCapability + { + /// + /// Indicates which properties a client can resolve lazily on a inlay + /// hint. + /// + [Optional] + public InlayHintCapabilityResolveSupport? ResolveSupport { get; set; } + } + + /// + /// Indicates which properties a client can resolve lazily on a inlay + /// hint. + /// + public class InlayHintCapabilityResolveSupport + { + /// + /// The properties that a client can resolve lazily. + /// + public Container Properties { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/InlineValueFeature.cs b/src/Protocol/Features/Document/InlineValueFeature.cs new file mode 100644 index 000000000..769806c78 --- /dev/null +++ b/src/Protocol/Features/Document/InlineValueFeature.cs @@ -0,0 +1,218 @@ +using System.Diagnostics; +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.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.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.InlineValue, Direction.ClientToServer)] + [ + GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "InlineValues"), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(InlineValueRegistrationOptions)), Capability(typeof(InlineValueWorkspaceClientCapabilities))] + public partial record InlineValueParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, + IRequest?> + { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; init; } + + /// + /// The document range for which inline values should be computed. + /// + public Range Range { get; init; } + + /// + /// Additional information about the context in which inline values were + /// requested. + /// + public InlineValueContext Context { get; init; } + } + + /// + /// @since 3.17.0 + /// + public partial record InlineValueContext + { + /// + /// The stack frame (as a DAP Id) where the execution has stopped. + /// + public int FrameId { get; set; } + + /// + /// The document range where execution has stopped. + /// Typically the end position of the range denotes the line where the + /// inline values are shown. + /// + public Range StoppedLocation { get; set; } + } + + [Parallel] + [Method(WorkspaceNames.InlineValueRefresh, Direction.ServerToClient)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(CodeLensWorkspaceClientCapabilities))] + public partial record InlineValueRefreshParams : IRequest; + + [JsonConverter(typeof(Converter))] + public abstract partial record InlineValueBase + { + /// + /// The document range for which the inline value applies. + /// + public Range Range { get; init; } + + internal class Converter : JsonConverter + { + public override bool CanWrite => false; + + public override void WriteJson(JsonWriter writer, InlineValueBase value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override InlineValueBase ReadJson( + JsonReader reader, Type objectType, InlineValueBase existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + var result = JObject.Load(reader); + if (result.ContainsKey("text")) + { + return new InlineValueText() + { + Range = result["range"]!.ToObject()!, + Text = result["text"]!.Value()! + }; + } + + if (result.ContainsKey("variableName") || result.ContainsKey("caseSensitiveLookup")) + { + return new InlineValueVariableLookup() + { + Range = result["range"].ToObject()!, + VariableName = result["variableName"]!.Value()!, + CaseSensitiveLookup = result["caseSensitiveLookup"]?.Value() ?? false, + }; + } + + return new InlineValueEvaluatableExpression() + { + Range = result["range"].ToObject()!, + Expression = result["expression"]?.Value() + }; + } + } + } + + /// + /// Provide inline value as text. + /// + /// @since 3.17.0 + /// + public partial record InlineValueText : InlineValueBase + { + /// + /// The text of the inline value. + /// + public string Text { get; init; } + } + + /// + /// Provide inline value through a variable lookup. + /// + /// If only a range is specified, the variable name will be extracted from + /// the underlying document. + /// + /// An optional variable name can be used to override the extracted name. + /// + /// @since 3.17.0 + /// + public partial record InlineValueVariableLookup : InlineValueBase + { + /// + /// If specified the name of the variable to look up. + /// + [Optional] + public string? VariableName { get; init; } + + /// + /// How to perform the lookup. + /// + public bool CaseSensitiveLookup { get; init; } + } + + /// + /// Provide an inline value through an expression evaluation. + /// + /// If only a range is specified, the expression will be extracted from the + /// underlying document. + /// + /// An optional expression can be used to override the extracted expression. + /// + /// @since 3.17.0 + /// + public partial record InlineValueEvaluatableExpression : InlineValueBase + { + /// + /// If specified the expression overrides the extracted expression. + /// + public string? Expression { get; init; } + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.InlineValueProvider))] + [RegistrationName(TextDocumentNames.InlineValue)] + public partial class InlineValueRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions + { + } + } + + namespace Server.Capabilities + { + } + + namespace Client.Capabilities + { + /// + /// Client workspace capabilities specific to inline values. + /// + /// @since 3.17.0 + /// + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.InlineValue))] + public partial class InlineValueWorkspaceClientCapabilities : ICapability + { + /// + /// Whether the client implementation supports a refresh request sent from + /// the server to the client. + /// + /// Note that this event is global and will force the client to refresh all + /// inline values currently shown. It should be used with absolute care and + /// is useful for situation where a server for example detect a project wide + /// change that requires such a calculation. + /// + [Optional] + public bool RefreshSupport { get; set; } + } + } + + namespace Document + { + } +} diff --git a/src/Protocol/Features/Document/LinkedEditingRangeFeature.cs b/src/Protocol/Features/Document/LinkedEditingRangeFeature.cs index 36e2efaf5..9952ab97e 100644 --- a/src/Protocol/Features/Document/LinkedEditingRangeFeature.cs +++ b/src/Protocol/Features/Document/LinkedEditingRangeFeature.cs @@ -25,14 +25,15 @@ public partial record LinkedEditingRanges { /// /// A list of ranges that can be renamed together. The ranges must have - /// identical length and contain identical text content. The ranges cannot overlap. + /// identical length and contain identical text content. The ranges cannot + /// overlap. /// public Container Ranges { get; init; } = 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. + /// 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; init; } diff --git a/src/Protocol/Features/Document/MonikerFeature.cs b/src/Protocol/Features/Document/MonikerFeature.cs index fe9cfab03..336f42b30 100644 --- a/src/Protocol/Features/Document/MonikerFeature.cs +++ b/src/Protocol/Features/Document/MonikerFeature.cs @@ -23,7 +23,7 @@ namespace Models /// [Parallel] [Method(TextDocumentNames.Moniker, Direction.ClientToServer)] - [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "Monikers")] [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(MonikerRegistrationOptions))] diff --git a/src/Protocol/Features/Document/NotebookDocumentSyncFeature.cs b/src/Protocol/Features/Document/NotebookDocumentSyncFeature.cs new file mode 100644 index 000000000..ac8383d8d --- /dev/null +++ b/src/Protocol/Features/Document/NotebookDocumentSyncFeature.cs @@ -0,0 +1,1230 @@ +using System; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Minimatch; +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.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 + { + /// + /// The params sent in a open notebook document notification. + /// + /// @since 3.17.0 + /// + [Serial] + [Method(NotebookDocumentNames.DidOpen, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(INotebookDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(NotebookDocumentSyncOptions))] + [Capability(typeof(NotebookDocumentSyncClientCapabilities))] + public partial class DidOpenNotebookDocumentParams : IRequest + { + /// + /// The notebook document that got opened. + /// + public NotebookDocument NotebookDocument { get; set; } + + /// + /// The text documents that represent the content + /// of a notebook cell. + /// + public Container CellTextDocuments { get; set; } + } + + /// + /// The params sent in a change notebook document notification. + /// + /// @since 3.17.0 + /// + [Serial] + [Method(NotebookDocumentNames.DidChange, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(INotebookDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(NotebookDocumentSyncOptions))] + [Capability(typeof(NotebookDocumentSyncClientCapabilities))] + public partial record DidChangeNotebookDocumentParams : IRequest + { + /// + /// The notebook document that did change. The version number points + /// to the version after all provided changes have been applied. + /// + public VersionedNotebookDocumentIdentifier NotebookDocument { get; set; } + + /// + /// The actual changes to the notebook document. + /// + /// The change describes single state change to the notebook document. + /// So it moves a notebook document, its cells and its cell text document + /// contents from state S to S'. + /// + /// To mirror the content of a notebook using change events use the + /// following approach: + /// - start with the same initial content + /// - apply the 'notebookDocument/didChange' notifications in the order + /// you receive them. + /// + public NotebookDocumentChangeEvent Change { get; set; } + } + + [Serial] + [Method(NotebookDocumentNames.DidSave, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(INotebookDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(NotebookDocumentSyncOptions))] + [Capability(typeof(NotebookDocumentSyncClientCapabilities))] + public partial class DidSaveNotebookDocumentParams : INotebookDocumentIdentifierParams, IRequest + { + /// + /// The notebook document that got saved. + /// + public NotebookDocumentIdentifier NotebookDocument { get; set; } + } + + [Parallel] + [Method(NotebookDocumentNames.DidClose, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(INotebookDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(NotebookDocumentSyncOptions))] + [Capability(typeof(NotebookDocumentSyncClientCapabilities))] + public partial class DidCloseNotebookDocumentParams : INotebookDocumentIdentifierParams, IRequest + { + /// + /// The notebook document that got closed. + /// + public NotebookDocumentIdentifier NotebookDocument { get; set; } + + /// + /// The text documents that represent the content + /// of a notebook cell that got closed. + /// + public Container CellTextDocuments { get; set; } + } + + /// + /// A change event for a notebook document. + /// + /// @since 3.17.0 + /// + public partial record NotebookDocumentChangeEvent + { + /// + /// The changed meta data if any. + /// + public JObject? Metadata { get; init; } + + /// + /// Changes to cells + /// + public NotebookDocumentChangeEventCells Cells { get; init; } + } + + /// + /// Changes to cells + /// + public partial record NotebookDocumentChangeEventCells + { + /// + /// Changes to the cell structure to add or + /// remove cells. + /// + public NotebookDocumentChangeEventCellsStructure? Structure { get; init; } + + /// + /// Changes to notebook cells properties like its + /// kind, execution summary or metadata. + /// + public Container? Data { get; set; } + + /// + /// Changes to the text content of notebook cells. + /// + public NotebookDocumentChangeEventCellsTextContent TextContent { get; init; } + } + + /// + /// Changes to the cell structure to add or + /// remove cells. + /// + public partial record NotebookDocumentChangeEventCellsStructure + { + /// + /// The change to the cell array. + /// + public NotebookCellArrayChange Array { get; set; } + + /// + /// Additional opened cell text documents. + /// + public Container? DidOpen { get; set; } + + /// + /// Additional closed cell text documents. + /// + public Container? DidClose { get; set; } + } + + /// + /// A change describing how to move a `NotebookCell` + /// array from state S to S'. + /// + /// @since 3.17.0 + /// + public partial record NotebookCellArrayChange + { + /// + /// The start oftest of the cell that changed. + /// + public uint Start { get; set; } + + /// + /// The deleted cells + /// + public uint DeleteCount { get; set; } + + /// + /// The new cells, if any + /// + public Container? Cells { get; set; } + } + + /// + /// Changes to the text content of notebook cells. + /// + public partial record NotebookDocumentChangeEventCellsTextContent + { + public VersionedTextDocumentIdentifier Document { get; set; } + public Container Changes { 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 record NotebookDocumentContentChangeEvent + { + /// + /// The range of the document that changed. + /// + [Optional] + public Range? Range { get; init; } + + /// + /// The length of the range that got replaced. + /// + /// + /// in the LSP spec + /// + [Optional] + public int RangeLength { get; init; } + + /// + /// The new text of the document. + /// + public string Text { get; init; } = null!; + } + + /// + /// A notebook document. + /// + /// @since 3.17.0 + /// + public partial record NotebookDocument + { + /// + /// The notebook document's uri. + /// + public DocumentUri Uri { get; set; } + + /// + /// The type of the notebook. + /// + public string NotebookType { get; set; } + + /// + /// The version number of this document (it will increase after each + /// change, including undo/redo). + /// + public int Version { get; set; } + + /// + /// Additional metadata stored with the notebook + /// document. + /// + public JObject? Metadata { get; set; } + + /// + /// The cells of a notebook. + /// + public Container Cells { get; set; } + } + + + /// + /// A notebook cell. + /// + /// A cell's document URI must be unique across ALL notebook + /// cells and can therefore be used to uniquely identify a + /// notebook cell or the cell's text document. + /// + /// @since 3.17.0 + /// + public partial record NotebookCell + { + /// + /// The cell's kind + /// + public NotebookCellKind Kind { get; set; } + + /// + /// The URI of the cell's text document + /// content. + /// + public DocumentUri Document { get; set; } + + /// + /// Additional metadata stored with the cell. + /// + public JObject? Metadata { get; set; } + + /// + /// Additional execution summary information + /// if supported by the client. + /// + public ExecutionSummary? ExecutionSummary { get; set; } + } + + public partial record ExecutionSummary + { + /// + /// A strict monotonically increasing value + /// indicating the execution order of a cell + /// inside a notebook. + /// + public uint ExecutionOrder { get; set; } + + /// + /// Whether the execution was successful or + /// not if known by the client. + /// + public bool? Success { get; set; } + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public record NotebookCellTextDocumentFilter + { + /// + /// A filter that matches against the notebook + /// containing the notebook cell. If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + /// + public StringOrNotebookDocumentFilter Notebook { get; init; } + + /// + /// A language id like `python`. + /// + /// Will be matched against the language id of the + /// notebook cell document. '*' matches every language. + /// + [Optional] + public string? Language { get; init; } + + private string DebuggerDisplay => + $"{Notebook} {Language}"; + + /// + public override string ToString() => DebuggerDisplay; + } + + [JsonConverter(typeof(Converter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public record StringOrNotebookDocumentFilter + { + public StringOrNotebookDocumentFilter(string value) => String = value; + + public StringOrNotebookDocumentFilter(NotebookDocumentFilter notebookDocumentFilter) => NotebookDocumentFilter = notebookDocumentFilter; + + public string? String { get; } + public bool HasString => NotebookDocumentFilter is null; + public NotebookDocumentFilter? NotebookDocumentFilter { get; } + public bool HasNotebookDocumentFilter => NotebookDocumentFilter is { }; + + public static implicit operator StringOrNotebookDocumentFilter?(string? value) => value is null ? null : new StringOrNotebookDocumentFilter(value); + + public static implicit operator StringOrNotebookDocumentFilter?(NotebookDocumentFilter notebookDocumentFilter) => + notebookDocumentFilter is null ? null : new StringOrNotebookDocumentFilter(notebookDocumentFilter); + + private string DebuggerDisplay => + $"{( HasString ? String : HasNotebookDocumentFilter ? NotebookDocumentFilter : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, StringOrNotebookDocumentFilter value, JsonSerializer serializer) + { + if (value.HasString) + { + writer.WriteValue(value.String); + } + else + { + serializer.Serialize(writer, value.NotebookDocumentFilter); + } + } + + public override StringOrNotebookDocumentFilter ReadJson( + JsonReader reader, Type objectType, StringOrNotebookDocumentFilter existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.StartObject) + { + return new StringOrNotebookDocumentFilter(JObject.Load(reader).ToObject(serializer)); + } + + if (reader.TokenType == JsonToken.String) + { + return new StringOrNotebookDocumentFilter(( reader.Value as string )!); + } + + return new StringOrNotebookDocumentFilter(""); + } + + public override bool CanRead => true; + } + } + + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class NotebookDocumentFilter : IEquatable + { + public static NotebookDocumentFilter ForPattern(string wildcard) => new NotebookDocumentFilter { Pattern = wildcard }; + + public static NotebookDocumentFilter ForNotebookType(string notebookType) => new NotebookDocumentFilter { NotebookType = notebookType }; + + public static NotebookDocumentFilter ForScheme(string scheme) => new NotebookDocumentFilter { Scheme = scheme }; + + /// + /// A language id, like `typescript`. + /// + [Optional] + public string? NotebookType { get; init; } + + /// + /// does the document filter contains a language + /// + [JsonIgnore] + public bool HasNotebookType => NotebookType != null; + + /// + /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + /// + [Optional] + public string? Scheme { get; init; } + + /// + /// does the document filter contains a scheme + /// + [JsonIgnore] + public bool HasScheme => Scheme != null; + + /// + /// A glob pattern, like `*.{ts,js}`. + /// + [Optional] + public string? Pattern + { + get => _pattern; + init + { + _pattern = value; + _minimatcher = new Minimatcher(value!, new Options { MatchBase = true }); + } + } + + /// + /// does the document filter contains a paattern + /// + [JsonIgnore] + public bool HasPattern => Pattern != null; + + private string? _pattern; + private Minimatcher? _minimatcher; + + public static explicit operator string(NotebookDocumentFilter notebookDocumentFilter) + { + var items = new List(); + if (notebookDocumentFilter.HasNotebookType) + { + items.Add(notebookDocumentFilter.NotebookType!); + } + + if (notebookDocumentFilter.HasScheme) + { + items.Add(notebookDocumentFilter.Scheme!); + } + + if (notebookDocumentFilter.HasPattern) + { + items.Add(notebookDocumentFilter.Pattern!); + } + + return $"[{string.Join(", ", items)}]"; + } + + public bool IsMatch(NotebookDocumentAttributes attributes) + { + if (HasNotebookType && HasPattern && HasScheme) + { + return NotebookType == attributes.NotebookType && Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasNotebookType && HasPattern) + { + return NotebookType == attributes.NotebookType && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasNotebookType && HasScheme) + { + return NotebookType == attributes.NotebookType && Scheme == attributes.Scheme; + } + + if (HasPattern && HasScheme) + { + return Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasNotebookType) + { + return NotebookType == attributes.NotebookType; + } + + if (HasScheme) + { + return Scheme == attributes.Scheme; + } + + if (HasPattern) + { + return _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + return false; + } + + public bool Equals(NotebookDocumentFilter? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return _pattern == other._pattern && NotebookType == other.NotebookType && Scheme == other.Scheme; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((NotebookDocumentFilter)obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = _pattern != null ? _pattern.GetHashCode() : 0; + hashCode = ( hashCode * 397 ) ^ ( NotebookType != null ? NotebookType.GetHashCode() : 0 ); + hashCode = ( hashCode * 397 ) ^ ( Scheme != null ? Scheme.GetHashCode() : 0 ); + return hashCode; + } + } + + public static bool operator ==(NotebookDocumentFilter left, NotebookDocumentFilter right) => Equals(left, right); + + public static bool operator !=(NotebookDocumentFilter left, NotebookDocumentFilter right) => !Equals(left, right); + + private string DebuggerDisplay => (string)this; + + /// + public override string ToString() => DebuggerDisplay; + } + + public record NotebookSelectorCell + { + public string Language { get; init; } + } + + /// + /// The notebooks to be synced + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class NotebookSelector : IEquatable + { + /// + /// The notebook to be synced If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + /// + public StringOrNotebookDocumentFilter? Notebook { get; init; } + + public bool HasNotebook => Notebook is not null; + + /// + /// The cells of the matching notebook to be synced. + /// + public Container? Cells { get; init; } + + public bool HasCells => Cells is not null; + + public bool IsMatch(NotebookDocumentAttributes attributes) + { + return Notebook?.NotebookDocumentFilter?.IsMatch(attributes) == true + || ( attributes.Language is not null && Cells?.Any(z => z.Language == attributes.Language) == true ); + } + + private string DebuggerDisplay => (string)this; + + /// + public override string ToString() => DebuggerDisplay; + + public static explicit operator string(NotebookSelector notebookDocumentFilter) + { + var items = new List(); + if (notebookDocumentFilter.HasNotebook) + { + if (notebookDocumentFilter.Notebook.HasString) + { + items.Add(notebookDocumentFilter.Notebook.String); + } + else if (notebookDocumentFilter.Notebook.HasNotebookDocumentFilter) + { + items.Add((string)notebookDocumentFilter.Notebook.NotebookDocumentFilter!); + } + } + + if (notebookDocumentFilter.HasCells) + { + items.Add(string.Join(", ", notebookDocumentFilter.Cells!.Select(z => z.Language!))); + } + + return $"[{string.Join(", ", items)}]"; + } + + public bool Equals(NotebookSelector? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(Notebook, other.Notebook) && Equals(Cells, other.Cells); + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((NotebookSelector)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ( ( Notebook != null ? Notebook.GetHashCode() : 0 ) * 397 ) ^ ( Cells != null ? Cells.GetHashCode() : 0 ); + } + } + + public static bool operator ==(NotebookSelector? left, NotebookSelector? right) + { + return Equals(left, right); + } + + public static bool operator !=(NotebookSelector? left, NotebookSelector? right) + { + return !Equals(left, right); + } + } + + /// + /// A collection of document filters used to identify valid documents + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class NotebookDocumentSelector : ContainerBase + { + public NotebookDocumentSelector() : this(Enumerable.Empty()) + { + } + + public NotebookDocumentSelector(IEnumerable items) : base(items) + { + } + + public NotebookDocumentSelector(params NotebookDocumentFilter[] items) : base(items) + { + } + + public static implicit operator NotebookDocumentSelector(NotebookDocumentFilter[] items) => new NotebookDocumentSelector(items); + + public static implicit operator NotebookDocumentSelector(Collection items) => new NotebookDocumentSelector(items); + + public static implicit operator NotebookDocumentSelector(List items) => new NotebookDocumentSelector(items); + + public static implicit operator string(NotebookDocumentSelector? documentSelector) => + documentSelector is not null ? string.Join(", ", documentSelector.Select(x => (string)x)) : string.Empty; + + public bool IsMatch(NotebookDocumentAttributes attributes) => this.Any(z => z.IsMatch(attributes)); + + public override string ToString() => this; + + public static NotebookDocumentSelector ForPattern(params string[] wildcards) => + new NotebookDocumentSelector(wildcards.Select(NotebookDocumentFilter.ForPattern)); + + public static NotebookDocumentSelector ForNotebookType(params string[] notebookTypes) => + new NotebookDocumentSelector(notebookTypes.Select(NotebookDocumentFilter.ForNotebookType)); + + public static NotebookDocumentSelector ForScheme(params string[] schemes) => + new NotebookDocumentSelector(schemes.Select(NotebookDocumentFilter.ForScheme)); + + private string DebuggerDisplay => this; + } + + + /// + /// A notebook cell kind. + /// + /// @since 3.17.0 + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum NotebookCellKind + { + /// + /// A markup-cell is formatted source that is used for display. + /// + Markup = 1, + + /// + /// A code-cell is source code. + /// + Code = 2 + } + + public interface INotebookDocumentRegistrationOptions : IRegistrationOptions + { + /// + /// The notebooks to be synced + /// + NotebookSelector NotebookSelector { get; set; } + } + + /// + /// Options specific to a notebook plus its cells + /// to be synced to the server. + /// + /// If a selector provider a notebook document + /// filter but no cell selector all cells of a + /// matching notebook document will be synced. + /// + /// If a selector provides no notebook document + /// filter but only a cell selector all notebook + /// document that contain at least one matching + /// cell will be synced. + /// + /// @since 3.17.0 + /// + [GenerateRegistrationOptions(nameof(ServerCapabilities.NotebookDocumentSync))] + [RegistrationOptionsConverter(typeof(Converter))] + public partial class NotebookDocumentSyncOptions : INotebookDocumentRegistrationOptions + { + /// + /// The notebook to be synced. If a string + /// value is provided it matches against the + /// notebook type. '*' matches every notebook. + /// + public NotebookSelector NotebookSelector { get; set; } + + /// + /// Whether save notification should be forwarded to + /// the server. Will only be honored if mode === `notebook`. + /// + public bool? Save { get; set; } + + private class Converter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public Converter(IHandlersManager handlersManager) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(NotebookDocumentSyncOptions source) + { + return new() + { + NotebookSelector = source.NotebookSelector, + Save = source.Save, + }; + } + } + } + } + + namespace Client.Capabilities + { + /// + /// Notebook specific client capabilities. + /// + /// @since 3.17.0 + /// + public partial class NotebookDocumentSyncClientCapabilities : DynamicCapability + { + /// + /// The client supports sending execution summary data per cell. + /// + public bool? ExecutionSummarySupport { get; set; } + } + } + + namespace Document + { + public interface INotebookDocumentSyncHandler : IDidChangeNotebookDocumentHandler, IDidOpenNotebookDocumentHandler, + IDidCloseNotebookDocumentHandler, IDidSaveNotebookDocumentHandler, INotebookDocumentIdentifier + { + } + + public abstract class NotebookDocumentSyncHandlerBase : INotebookDocumentSyncHandler + { + public abstract NotebookDocumentAttributes GetNotebookDocumentAttributes(DocumentUri uri); + public abstract Task Handle(DidOpenNotebookDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidChangeNotebookDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidSaveNotebookDocumentParams request, CancellationToken cancellationToken); + public abstract Task Handle(DidCloseNotebookDocumentParams request, CancellationToken cancellationToken); + + protected NotebookDocumentSyncOptions RegistrationOptions { get; private set; } + + protected ClientCapabilities ClientCapabilities { get; private set; } + + protected NotebookDocumentSyncClientCapabilities Capability { get; private set; } = default!; + + protected abstract NotebookDocumentSyncOptions CreateRegistrationOptions( + NotebookDocumentSyncClientCapabilities capability, ClientCapabilities clientCapabilities + ); + + private NotebookDocumentSyncOptions AssignRegistrationOptions( + NotebookDocumentSyncClientCapabilities capability, ClientCapabilities clientCapabilities + ) + { + Capability = capability; + if (RegistrationOptions is { }) return RegistrationOptions; + ClientCapabilities = clientCapabilities; + return RegistrationOptions = CreateRegistrationOptions(capability, clientCapabilities); + } + + NotebookDocumentSyncOptions IRegistration.GetRegistrationOptions( + NotebookDocumentSyncClientCapabilities capability, ClientCapabilities clientCapabilities + ) + { + return RegistrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); + } + } + + + public static class NotebookDocumentSyncExtensions + { + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + onOpenHandler, + onCloseHandler, + onChangeHandler, + onSaveHandler, + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + RegistrationOptionsDelegate? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + public static ILanguageServerRegistry OnNotebookDocumentSync( + this ILanguageServerRegistry registry, + Func getNotebookDocumentAttributes, + Action onOpenHandler, + Action onCloseHandler, + Action onChangeHandler, + Action onSaveHandler, + NotebookDocumentSyncOptions? registrationOptions + ) + { + return registry.AddHandlers( + new DelegatingHandler( + getNotebookDocumentAttributes, + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) + ) + ); + } + + private class DelegatingHandler : NotebookDocumentSyncHandlerBase + { + private readonly Func _onOpenHandler; + private readonly Func _onCloseHandler; + private readonly Func _onChangeHandler; + private readonly Func _onSaveHandler; + + private readonly RegistrationOptionsDelegate + _registrationOptionsFactory; + + private readonly Func _getNotebookDocumentAttributes; + + public DelegatingHandler( + Func getNotebookDocumentAttributes, + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _onOpenHandler = onOpenHandler; + _onSaveHandler = onSaveHandler; + _registrationOptionsFactory = registrationOptionsFactory; + _onChangeHandler = onChangeHandler; + _onCloseHandler = onCloseHandler; + _getNotebookDocumentAttributes = getNotebookDocumentAttributes; + } + + public override async Task Handle(DidOpenNotebookDocumentParams request, CancellationToken cancellationToken) + { + await _onOpenHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidChangeNotebookDocumentParams request, CancellationToken cancellationToken) + { + await _onChangeHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidSaveNotebookDocumentParams request, CancellationToken cancellationToken) + { + await _onSaveHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + public override async Task Handle(DidCloseNotebookDocumentParams request, CancellationToken cancellationToken) + { + await _onCloseHandler.Invoke(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected override NotebookDocumentSyncOptions CreateRegistrationOptions( + NotebookDocumentSyncClientCapabilities capability, ClientCapabilities clientCapabilities + ) + { + return _registrationOptionsFactory(capability, clientCapabilities); + } + + public override NotebookDocumentAttributes GetNotebookDocumentAttributes(DocumentUri uri) + { + return _getNotebookDocumentAttributes.Invoke(uri); + } + } + } + } +} diff --git a/src/Protocol/Features/Document/ReferencesFeature.cs b/src/Protocol/Features/Document/ReferencesFeature.cs index 28f19715b..92a0ebb9e 100644 --- a/src/Protocol/Features/Document/ReferencesFeature.cs +++ b/src/Protocol/Features/Document/ReferencesFeature.cs @@ -18,10 +18,13 @@ namespace Models GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) ] [RegistrationOptions(typeof(ReferenceRegistrationOptions)), Capability(typeof(ReferenceCapability))] - public partial record ReferenceParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest + public partial record ReferenceParams : TextDocumentPositionParams, IWorkDoneProgressParams, IPartialItemsRequest { public ReferenceContext Context { get; init; } } + + public partial class LocationContainer {} + public record ReferenceContext { /// diff --git a/src/Protocol/Features/Document/RenameFeature.cs b/src/Protocol/Features/Document/RenameFeature.cs index 48ae01358..80eab42d0 100644 --- a/src/Protocol/Features/Document/RenameFeature.cs +++ b/src/Protocol/Features/Document/RenameFeature.cs @@ -48,7 +48,7 @@ public partial record RenameParams : ITextDocumentIdentifierParams, IRequest; + public partial record PrepareRenameParams : TextDocumentPositionParams, IWorkDoneProgressParams, IRequest; [JsonConverter(typeof(RangeOrPlaceholderRangeConverter))] public record RangeOrPlaceholderRange @@ -177,7 +177,7 @@ public class RenameCapability : DynamicCapability public PrepareSupportDefaultBehavior PrepareSupportDefaultBehavior { get; set; } /// - /// Whether th client honors the change annotations in + /// Whether the client honors the change annotations in /// text edits and resource operations returned via the /// `CodeAction#edit` property by for example presenting /// the workspace edit in the user interface and asking @@ -194,7 +194,7 @@ public enum PrepareSupportDefaultBehavior { /// /// The client's default behavior is to select the identifier - /// according the to language's syntax rule. + /// according to the language's syntax rule. /// Identifier = 1 } diff --git a/src/Protocol/Features/Document/SemanticTokensFeature.cs b/src/Protocol/Features/Document/SemanticTokensFeature.cs index 7185fdfca..cd9d56358 100644 --- a/src/Protocol/Features/Document/SemanticTokensFeature.cs +++ b/src/Protocol/Features/Document/SemanticTokensFeature.cs @@ -177,6 +177,8 @@ internal SemanticTokensPartialResult(SemanticTokens? result) { Data = result?.Data ?? ImmutableArray.Empty; } + + public static SemanticTokensPartialResult From(SemanticTokens? result) => new SemanticTokensPartialResult(result); } @@ -418,6 +420,8 @@ public static implicit operator SemanticTokensFullOrDelta(SemanticTokensFullOrDe { return new SemanticTokensFullOrDelta(semanticTokensDeltaPartialResult); } + + public static SemanticTokensFullOrDeltaPartialResult From(SemanticTokensFullOrDelta? result) => new SemanticTokensFullOrDeltaPartialResult(result); } /// @@ -604,6 +608,11 @@ public readonly partial struct SemanticTokenType public static SemanticTokenType Modifier { get; } = new SemanticTokenType("modifier"); public static SemanticTokenType Event { get; } = new SemanticTokenType("event"); public static SemanticTokenType EnumMember { get; } = new SemanticTokenType("enumMember"); + + /// + /// @since 3.17.0 + /// + public static SemanticTokenType Decorator { get; } = new SemanticTokenType("decorator"); } [RegistrationName(TextDocumentNames.SemanticTokensRegistration)] @@ -708,6 +717,32 @@ public partial class SemanticTokensCapability : DynamicCapability /// [Optional] public bool MultilineTokenSupport { get; set; } + + /// + /// Whether the client allows the server to actively cancel a + /// semantic token request, e.g. supports returning + /// ErrorCodes.ServerCancelled. If a server does the client + /// needs to retrigger the request. + /// + /// @since 3.17.0 + /// + [Optional] + public bool ServerCancelSupport { get; set; } + + /// + /// Whether the client uses semantic tokens to augment existing + /// syntax tokens. If set to `true` client side created syntax + /// tokens and semantic tokens are both used for colorization. If + /// set to `false` the client only uses the returned semantic tokens + /// for colorization. + /// + /// If the value is `undefined` then the client behavior is not + /// specified. + /// + /// @since 3.17.0 + /// + [Optional] + public bool AugmentsSyntaxTokens { get; set; } } public partial class SemanticTokensCapabilityRequests @@ -931,7 +966,7 @@ protected internal override SemanticTokensRegistrationOptions CreateRegistration { return mediator.ProgressManager.MonitorUntil( @params, - (partial, result) => new SemanticTokens + (result, partial) => new SemanticTokens { Data = partial.Data, ResultId = result?.ResultId @@ -946,9 +981,9 @@ protected internal override SemanticTokensRegistrationOptions CreateRegistration ) { return mediator.ProgressManager.MonitorUntil( - @params, (partial, result) => + @params, (result, partial) => { - if (partial.IsDelta) + if (partial?.IsDelta == true) { return new SemanticTokensFullOrDelta( new SemanticTokensDelta @@ -959,7 +994,7 @@ protected internal override SemanticTokensRegistrationOptions CreateRegistration ); } - if (partial.IsFull) + if (partial?.IsFull == true) { return new SemanticTokensFullOrDelta( new SemanticTokens @@ -971,7 +1006,7 @@ protected internal override SemanticTokensRegistrationOptions CreateRegistration } return new SemanticTokensFullOrDelta(new SemanticTokens()); - }, cancellationToken + }, SemanticTokensFullOrDeltaPartialResult.From, cancellationToken ); } @@ -982,12 +1017,12 @@ protected internal override SemanticTokensRegistrationOptions CreateRegistration { return mediator.ProgressManager.MonitorUntil( @params, - (partial, result) => new SemanticTokens + (result, partial) => new SemanticTokens { Data = partial.Data, ResultId = result?.ResultId }, - tokens => new SemanticTokensPartialResult(tokens)!, + SemanticTokensPartialResult.From, cancellationToken ); } diff --git a/src/Protocol/Features/Document/TextDocumentSyncFeature.cs b/src/Protocol/Features/Document/TextDocumentSyncFeature.cs index 615df16a0..bc2d14057 100644 --- a/src/Protocol/Features/Document/TextDocumentSyncFeature.cs +++ b/src/Protocol/Features/Document/TextDocumentSyncFeature.cs @@ -1,8 +1,12 @@ using System; +using System.Collections.ObjectModel; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using MediatR; +using Minimatch; +using Newtonsoft.Json; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Generation; using OmniSharp.Extensions.LanguageServer.Protocol.Client; @@ -25,7 +29,7 @@ namespace Models [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumentChangeRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial record DidChangeTextDocumentParams : IRequest { /// @@ -55,8 +59,8 @@ public partial class TextDocumentChangeRegistrationOptions : ITextDocumentRegist } /// - /// 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. + /// An event describing a change to a text document. If only a text is provided + /// it is considered to be the full content of the document. /// public record TextDocumentContentChangeEvent { @@ -90,6 +94,9 @@ public record TextDocumentEdit /// /// The edits to be applied. + /// + /// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the + /// client capability `workspace.workspaceEdit.changeAnnotationSupport` /// /// /// This can contain both and @@ -103,7 +110,7 @@ public record TextDocumentEdit [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumentOpenRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial class DidOpenTextDocumentParams : IRequest { /// @@ -123,7 +130,7 @@ public partial class TextDocumentOpenRegistrationOptions : ITextDocumentRegistra [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumentCloseRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial class DidCloseTextDocumentParams : ITextDocumentIdentifierParams, IRequest { /// @@ -143,7 +150,7 @@ public partial class TextDocumentCloseRegistrationOptions : ITextDocumentRegistr [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumentSaveRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial class DidSaveTextDocumentParams : ITextDocumentIdentifierParams, IRequest { /// @@ -169,6 +176,229 @@ public partial class TextDocumentSaveRegistrationOptions : ITextDocumentRegistra public bool IncludeText { get; set; } } + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class TextDocumentFilter : IEquatable + { + public static TextDocumentFilter ForPattern(string wildcard) => new TextDocumentFilter { Pattern = wildcard }; + + public static TextDocumentFilter ForLanguage(string language) => new TextDocumentFilter { Language = language }; + + public static TextDocumentFilter ForScheme(string scheme) => new TextDocumentFilter { Scheme = scheme }; + + /// + /// A language id, like `typescript`. + /// + [Optional] + public string? Language { get; init; } + + /// + /// does the document filter contains a language + /// + [JsonIgnore] + public bool HasLanguage => Language != null; + + /// + /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + /// + [Optional] + public string? Scheme { get; init; } + + /// + /// does the document filter contains a scheme + /// + [JsonIgnore] + public bool HasScheme => Scheme != null; + + /// + /// A glob pattern, like `*.{ts,js}`. + /// + /// Glob patterns can have the following syntax: + /// - `*` to match one or more characters in a path segment + /// - `?` to match on one character in a path segment + /// - `**` to match any number of path segments, including none + /// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` + /// matches all TypeScript and JavaScript files) + /// - `[]` to declare a range of characters to match in a path segment + /// (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + /// - `[!...]` to negate a range of characters to match in a path segment + /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but + /// not `example.0`) + /// + [Optional] + public string? Pattern + { + get => _pattern; + init + { + _pattern = value; + _minimatcher = new Minimatcher(value!, new Options { MatchBase = true }); + } + } + + /// + /// does the document filter contains a paattern + /// + [JsonIgnore] + public bool HasPattern => Pattern != null; + + private string? _pattern; + private Minimatcher? _minimatcher; + + public static explicit operator string(TextDocumentFilter textDocumentFilter) + { + var items = new List(); + if (textDocumentFilter.HasLanguage) + { + items.Add(textDocumentFilter.Language!); + } + + if (textDocumentFilter.HasScheme) + { + items.Add(textDocumentFilter.Scheme!); + } + + if (textDocumentFilter.HasPattern) + { + items.Add(textDocumentFilter.Pattern!); + } + + return $"[{string.Join(", ", items)}]"; + } + + public bool IsMatch(TextDocumentAttributes attributes) + { + if (HasLanguage && HasPattern && HasScheme) + { + return Language == attributes.LanguageId && Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasLanguage && HasPattern) + { + return Language == attributes.LanguageId && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasLanguage && HasScheme) + { + return Language == attributes.LanguageId && Scheme == attributes.Scheme; + } + + if (HasPattern && HasScheme) + { + return Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + if (HasLanguage) + { + return Language == attributes.LanguageId; + } + + if (HasScheme) + { + return Scheme == attributes.Scheme; + } + + if (HasPattern) + { + return _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; + } + + return false; + } + + public bool Equals(TextDocumentFilter? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return _pattern == other._pattern && Language == other.Language && Scheme == other.Scheme; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((TextDocumentFilter)obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = _pattern != null ? _pattern.GetHashCode() : 0; + hashCode = ( hashCode * 397 ) ^ ( Language != null ? Language.GetHashCode() : 0 ); + hashCode = ( hashCode * 397 ) ^ ( Scheme != null ? Scheme.GetHashCode() : 0 ); + return hashCode; + } + } + + public static bool operator ==(TextDocumentFilter left, TextDocumentFilter right) => Equals(left, right); + + public static bool operator !=(TextDocumentFilter left, TextDocumentFilter right) => !Equals(left, right); + + private string DebuggerDisplay => (string)this; + + /// + public override string ToString() => DebuggerDisplay; + } + + /// + /// A collection of document filters used to identify valid documents + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public class TextDocumentSelector : ContainerBase + { + public TextDocumentSelector() : this(Enumerable.Empty()) + { + } + + public TextDocumentSelector(IEnumerable items) : base(items) + { + } + + public TextDocumentSelector(params TextDocumentFilter[] items) : base(items) + { + } + + public static implicit operator TextDocumentSelector(TextDocumentFilter[] items) => new TextDocumentSelector(items); + + public static implicit operator TextDocumentSelector(Collection items) => new TextDocumentSelector(items); + + public static implicit operator TextDocumentSelector(List items) => new TextDocumentSelector(items); + + public static implicit operator string(TextDocumentSelector? documentSelector) => + documentSelector is not null ? string.Join(", ", documentSelector.Select(x => (string)x)) : string.Empty; + + public bool IsMatch(TextDocumentAttributes attributes) => this.Any(z => z.IsMatch(attributes)); + + public override string ToString() => this; + + public static TextDocumentSelector ForPattern(params string[] wildcards) => new TextDocumentSelector(wildcards.Select(TextDocumentFilter.ForPattern)); + + public static TextDocumentSelector ForLanguage(params string[] languages) => new TextDocumentSelector(languages.Select(TextDocumentFilter.ForLanguage)); + + public static TextDocumentSelector ForScheme(params string[] schemes) => new TextDocumentSelector(schemes.Select(TextDocumentFilter.ForScheme)); + + private string DebuggerDisplay => this; + } + + public interface ITextDocumentSyncOptions + { + [Optional] bool OpenClose { get; set; } + [Optional] TextDocumentSyncKind Change { get; set; } + [Optional] bool WillSave { get; set; } + [Optional] bool WillSaveWaitUntil { get; set; } + [Optional] BooleanOr Save { get; set; } + } + + public interface ITextDocumentRegistrationOptions : IRegistrationOptions + { + /// + /// 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. + /// + TextDocumentSelector? DocumentSelector { get; set; } + } + [GenerateRegistrationOptions(nameof(ServerCapabilities.TextDocumentSync))] [RegistrationOptionsConverter(typeof(Converter))] public partial class TextDocumentSyncRegistrationOptions : ITextDocumentRegistrationOptions @@ -284,7 +514,7 @@ public static implicit operator TextDocumentCloseRegistrationOptions(TextDocumen [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumenWillSaveRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial class WillSaveTextDocumentParams : IRequest { /// @@ -312,7 +542,7 @@ public partial class TextDocumenWillSaveRegistrationOptions : ITextDocumentRegis [GenerateHandlerMethods] [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(TextDocumentWillSaveWaitUntilRegistrationOptions))] - [Capability(typeof(SynchronizationCapability))] + [Capability(typeof(TextSynchronizationCapability))] public partial class WillSaveWaitUntilTextDocumentParams : IRequest { /// @@ -335,7 +565,7 @@ public partial class TextDocumentWillSaveWaitUntilRegistrationOptions : ITextDoc namespace Client.Capabilities { [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Synchronization))] - public class SynchronizationCapability : DynamicCapability + public class TextSynchronizationCapability : DynamicCapability { /// @@ -379,13 +609,15 @@ public abstract class TextDocumentSyncHandlerBase : ITextDocumentSyncHandler protected ClientCapabilities ClientCapabilities { get; private set; } - protected SynchronizationCapability Capability { get; private set; } = default!; + protected TextSynchronizationCapability Capability { get; private set; } = default!; protected abstract TextDocumentSyncRegistrationOptions CreateRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ); - private TextDocumentSyncRegistrationOptions AssignRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) + private TextDocumentSyncRegistrationOptions AssignRegistrationOptions( + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities + ) { Capability = capability; if (RegistrationOptions is { }) return RegistrationOptions; @@ -393,29 +625,29 @@ private TextDocumentSyncRegistrationOptions AssignRegistrationOptions(Synchroniz return RegistrationOptions = CreateRegistrationOptions(capability, clientCapabilities); } - TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions( + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ) { return RegistrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); } - TextDocumentOpenRegistrationOptions IRegistration.GetRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextDocumentOpenRegistrationOptions IRegistration.GetRegistrationOptions( + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ) { return RegistrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); } - TextDocumentCloseRegistrationOptions IRegistration.GetRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextDocumentCloseRegistrationOptions IRegistration.GetRegistrationOptions( + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ) { return RegistrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); } - TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions( + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ) { return RegistrationOptions ?? AssignRegistrationOptions(capability, clientCapabilities); @@ -428,11 +660,11 @@ public static class TextDocumentSyncExtensions public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, Func getTextDocumentAttributes, - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate? registrationOptions ) { return registry.AddHandlers( @@ -442,7 +674,7 @@ public static ILanguageServerRegistry OnTextDocumentSync( onCloseHandler, onChangeHandler, onSaveHandler, - RegistrationAdapter.Adapt(registrationOptions) + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -450,21 +682,21 @@ public static ILanguageServerRegistry OnTextDocumentSync( public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, Func getTextDocumentAttributes, - Func onOpenHandler, - Func onCloseHandler, - Func onChangeHandler, - Func onSaveHandler, + 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) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -472,21 +704,21 @@ public static ILanguageServerRegistry OnTextDocumentSync( public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + 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) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -494,21 +726,21 @@ public static ILanguageServerRegistry OnTextDocumentSync( public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, + 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) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -517,21 +749,21 @@ public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, TextDocumentSyncKind kind, Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + 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) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -540,21 +772,21 @@ public static ILanguageServerRegistry OnTextDocumentSync( this ILanguageServerRegistry registry, TextDocumentSyncKind kind, Func getTextDocumentAttributes, - Action onOpenHandler, - Action onCloseHandler, - Action onChangeHandler, - Action onSaveHandler, + 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) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -567,17 +799,17 @@ public static ILanguageServerRegistry OnTextDocumentSync( Func onCloseHandler, Func onChangeHandler, Func onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + RegistrationOptionsDelegate? registrationOptions ) { return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -596,11 +828,11 @@ public static ILanguageServerRegistry OnTextDocumentSync( return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -613,17 +845,17 @@ public static ILanguageServerRegistry OnTextDocumentSync( Action onCloseHandler, Action onChangeHandler, Action onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + RegistrationOptionsDelegate? registrationOptions ) { return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -642,11 +874,11 @@ public static ILanguageServerRegistry OnTextDocumentSync( return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -659,17 +891,17 @@ public static ILanguageServerRegistry OnTextDocumentSync( Func onCloseHandler, Func onChangeHandler, Func onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + RegistrationOptionsDelegate? registrationOptions ) { return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -688,11 +920,11 @@ public static ILanguageServerRegistry OnTextDocumentSync( return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -705,17 +937,17 @@ public static ILanguageServerRegistry OnTextDocumentSync( Action onCloseHandler, Action onChangeHandler, Action onSaveHandler, - RegistrationOptionsDelegate? registrationOptions + RegistrationOptionsDelegate? registrationOptions ) { return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + HandlerAdapter.Adapt(onOpenHandler), + HandlerAdapter.Adapt(onCloseHandler), + HandlerAdapter.Adapt(onChangeHandler), + HandlerAdapter.Adapt(onSaveHandler), + RegistrationAdapter.Adapt(registrationOptions) ) ); } @@ -734,31 +966,31 @@ public static ILanguageServerRegistry OnTextDocumentSync( return registry.AddHandlers( new DelegatingHandler( getTextDocumentAttributes, - HandlerAdapter.Adapt(onOpenHandler), - HandlerAdapter.Adapt(onCloseHandler), - HandlerAdapter.Adapt(onChangeHandler), - HandlerAdapter.Adapt(onSaveHandler), - RegistrationAdapter.Adapt(registrationOptions) + 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 _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 + Func onOpenHandler, + Func onCloseHandler, + Func onChangeHandler, + Func onSaveHandler, + RegistrationOptionsDelegate registrationOptionsFactory ) { _onOpenHandler = onOpenHandler; @@ -794,7 +1026,7 @@ public override async Task Handle(DidCloseTextDocumentParams request, Canc } protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions( - SynchronizationCapability capability, ClientCapabilities clientCapabilities + TextSynchronizationCapability capability, ClientCapabilities clientCapabilities ) { return _registrationOptionsFactory(capability, clientCapabilities); diff --git a/src/Protocol/Features/Document/TypeDefinitionFeature.cs b/src/Protocol/Features/Document/TypeDefinitionFeature.cs index 504742323..134a2edce 100644 --- a/src/Protocol/Features/Document/TypeDefinitionFeature.cs +++ b/src/Protocol/Features/Document/TypeDefinitionFeature.cs @@ -18,7 +18,7 @@ namespace Models [RegistrationOptions(typeof(TypeDefinitionRegistrationOptions))] [Capability(typeof(TypeDefinitionCapability))] public partial record TypeDefinitionParams : TextDocumentPositionParams, IWorkDoneProgressParams, - IPartialItemsRequest; + IPartialItemsRequest; [GenerateRegistrationOptions(nameof(ServerCapabilities.TypeDefinitionProvider))] [RegistrationName(TextDocumentNames.TypeDefinition)] diff --git a/src/Protocol/Features/Document/TypeHierarchyFeature.cs b/src/Protocol/Features/Document/TypeHierarchyFeature.cs new file mode 100644 index 000000000..97a5eb640 --- /dev/null +++ b/src/Protocol/Features/Document/TypeHierarchyFeature.cs @@ -0,0 +1,997 @@ +using System; +using System.Collections.Generic; +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.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 + { + /// + /// The parameter of a `textDocument/prepareTypeHierarchy` request. + /// + /// @since 3.17.0 + /// + [Parallel] + [Method(TextDocumentNames.PrepareTypeHierarchy, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(TypeHierarchyRegistrationOptions))] + [Capability(typeof(TypeHierarchyCapability))] + public partial record TypeHierarchyPrepareParams : TextDocumentPositionParams, IWorkDoneProgressParams, + IPartialItemsRequest?, TypeHierarchyItem>; + + /// + /// Represents programming constructs like functions or constructors in the context + /// of call hierarchy. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateTypedData] + public partial record TypeHierarchyItem : ICanBeResolved + { + /// + /// The name of this item. + /// + public string Name { get; init; } = null!; + + /// + /// The kind of this item. + /// + public SymbolKind Kind { get; init; } + + /// + /// Tags for this item. + /// + [Optional] + public Container? Tags { get; init; } + + /// + /// More detail for this item, e.g. the signature of a function. + /// + [Optional] + public string? Detail { get; init; } + + /// + /// The resource identifier of this item. + /// + public DocumentUri Uri { get; init; } = null!; + + /// + /// The range enclosing this symbol not including leading/trailing whitespace + /// but everything else, e.g. comments and code. + /// + public Range Range { get; init; } = 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`](#TypeHierarchyItem.range). + /// + public Range SelectionRange { get; init; } = null!; + + /// + /// A data entry field that is preserved between a call hierarchy prepare and + /// supertypes or subtypes requests. It could also be used to identify the + /// type hierarchy in the server, helping improve the performance on + /// resolving supertypes and subtypes. + /// + [Optional] + public JToken? Data { get; init; } + + private string DebuggerDisplay => + $"[{Kind.ToString()}] " + + $"{Name} " + + $"@ {Uri} " + + $"{Range}"; + + /// + public override string ToString() + { + return DebuggerDisplay; + } + } + + public abstract record TypeHierarchyBaseParams : ICanBeResolved + { + public TypeHierarchyItem Item { get; init; } = null!; + + JToken? ICanBeResolved.Data + { + get => Item.GetRawData(); + init => Item.SetRawData(value); + } + } + + public abstract record TypeHierarchyBaseParams : ICanBeResolved + where T : class?, IHandlerIdentity? + { + public TypeHierarchyItem Item { get; init; } = null!; + + JToken? ICanBeResolved.Data + { + get => Item.GetRawData(); + init => Item.SetRawData(value); + } + } + + /// + /// The parameter of a `TypeHierarchy/supertypes` request. + /// + /// @since 3.17.0 + /// + [Parallel] + [Method(TextDocumentNames.TypeHierarchySupertypes, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "TypeHierarchySupertypes")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [Capability(typeof(TypeHierarchyCapability))] + public partial record TypeHierarchySupertypesParams : TypeHierarchyBaseParams, IWorkDoneProgressParams, + IPartialItemsRequest?, TypeHierarchyItem>, + IDoesNotParticipateInRegistration; + + /// + /// The parameter of a `TypeHierarchy/supertypes` request. + /// + /// @since 3.17.0 + /// + [Method(TextDocumentNames.TypeHierarchySupertypes, Direction.ClientToServer)] + public partial record TypeHierarchySupertypesParams : TypeHierarchyBaseParams, IWorkDoneProgressParams, + IPartialItemsRequest?, TypeHierarchyItem>, + IDoesNotParticipateInRegistration + where T : class?, IHandlerIdentity?; + + /// + /// The parameter of a `TypeHierarchy/subtypes` request. + /// + /// @since 3.17.0 + /// + [Parallel] + [Method(TextDocumentNames.TypeHierarchySubtypes, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "TypeHierarchySubtypes")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [Capability(typeof(TypeHierarchyCapability))] + public partial record TypeHierarchySubtypesParams : TypeHierarchyBaseParams, IWorkDoneProgressParams, + IPartialItemsRequest?, TypeHierarchyItem>, + IDoesNotParticipateInRegistration + + { + public static TypeHierarchySubtypesParams Create(TypeHierarchySubtypesParams item) + where T : class?, IHandlerIdentity? + { + return new TypeHierarchySubtypesParams + { + Item = item.Item, + PartialResultToken = item.PartialResultToken, + WorkDoneToken = item.PartialResultToken + }; + } + } + + /// + /// The parameter of a `TypeHierarchy/subtypes` request. + /// + /// @since 3.17.0 + /// + [Method(TextDocumentNames.TypeHierarchySubtypes, Direction.ClientToServer)] + public partial record TypeHierarchySubtypesParams : TypeHierarchyBaseParams, IWorkDoneProgressParams, + IPartialItemsRequest?, TypeHierarchyItem>, + IDoesNotParticipateInRegistration + where T : class?, IHandlerIdentity? + { + public static TypeHierarchySubtypesParams Create(TypeHierarchySubtypesParams item) + { + return new TypeHierarchySubtypesParams + { + Item = item.Item, + PartialResultToken = item.PartialResultToken, + WorkDoneToken = item.PartialResultToken + }; + } + + public static implicit operator TypeHierarchySubtypesParams(TypeHierarchySubtypesParams item) + { + return Create(item); + } + + public static implicit operator TypeHierarchySubtypesParams(TypeHierarchySubtypesParams item) + { + return TypeHierarchySubtypesParams.Create(item); + } + } + + /// + /// Type hierarchy options used during static or dynamic registration. + /// + /// @since 3.17.0 + /// + [GenerateRegistrationOptions(nameof(ServerCapabilities.TypeHierarchyProvider))] + [RegistrationName(TextDocumentNames.PrepareTypeHierarchy)] + public partial class TypeHierarchyRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions, IStaticRegistrationOptions + { + } + } + + namespace Client.Capabilities + { + /// + /// Capabilities specific to the `textDocument/typeHierarchy`. + /// + /// @since 3.17.0 + /// + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.TypeHierarchy))] + public partial class TypeHierarchyCapability : DynamicCapability + { + } + } + + namespace Document + { + public abstract class TypeHierarchyHandlerBase : AbstractHandlers.Base, + ITypeHierarchyPrepareHandler, + ITypeHierarchySupertypesHandler, + ITypeHierarchySubtypesHandler + { + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + protected TypeHierarchyHandlerBase(Guid id) + { + _id = id; + } + + protected TypeHierarchyHandlerBase() : this(Guid.NewGuid()) + { + } + + public abstract Task?> Handle(TypeHierarchyPrepareParams request, CancellationToken cancellationToken); + public abstract Task?> Handle(TypeHierarchySupertypesParams request, CancellationToken cancellationToken); + public abstract Task?> Handle(TypeHierarchySubtypesParams request, CancellationToken cancellationToken); + } + + public abstract class PartialTypeHierarchyHandlerBase : AbstractHandlers.PartialResults?, + TypeHierarchyItem, + TypeHierarchyRegistrationOptions, TypeHierarchyCapability>, + ITypeHierarchyPrepareHandler, ITypeHierarchySupertypesHandler, ITypeHierarchySubtypesHandler + { + private readonly ITypeHierarchySupertypesHandler _supertypes; + private readonly ITypeHierarchySubtypesHandler _subtypes; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + protected PartialTypeHierarchyHandlerBase(Guid id, IProgressManager progressManager) : base(progressManager, Container.From) + { + _id = id; + _supertypes = new PartialSupertypes(id, progressManager, this); + _subtypes = new PartialSubtypes(id, progressManager, this); + } + + protected PartialTypeHierarchyHandlerBase(IProgressManager progressManager) : this(Guid.NewGuid(), progressManager) + { + } + + public Task?> Handle(TypeHierarchySupertypesParams request, CancellationToken cancellationToken) + { + return _supertypes.Handle(request, cancellationToken); + } + + public Task?> Handle(TypeHierarchySubtypesParams request, CancellationToken cancellationToken) + { + return _subtypes.Handle(request, cancellationToken); + } + + protected abstract void Handle( + TypeHierarchySupertypesParams request, IObserver> results, CancellationToken cancellationToken + ); + + protected abstract void Handle( + TypeHierarchySubtypesParams request, IObserver> results, CancellationToken cancellationToken + ); + + private class PartialSupertypes : AbstractHandlers.PartialResults< + TypeHierarchySupertypesParams, + Container?, + TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >, ITypeHierarchySupertypesHandler + { + private readonly PartialTypeHierarchyHandlerBase _self; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialSupertypes(Guid id, IProgressManager progressManager, PartialTypeHierarchyHandlerBase self) : + base(progressManager, Container.From) + { + _id = id; + _self = self; + } + + protected override void Handle( + TypeHierarchySupertypesParams request, + IObserver> results, + CancellationToken cancellationToken + ) + { + _self.Handle(request, results, cancellationToken); + } + + protected internal override TypeHierarchyRegistrationOptions CreateRegistrationOptions( + TypeHierarchyCapability capability, ClientCapabilities clientCapabilities + ) + { + return ( (IRegistration)_self ).GetRegistrationOptions( + capability, clientCapabilities + ); + } + } + + private class PartialSubtypes : AbstractHandlers.PartialResults?, + TypeHierarchyItem, TypeHierarchyRegistrationOptions + , TypeHierarchyCapability>, ITypeHierarchySubtypesHandler + { + private readonly PartialTypeHierarchyHandlerBase _self; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialSubtypes(Guid id, IProgressManager progressManager, PartialTypeHierarchyHandlerBase self) : + base(progressManager, Container.From) + + { + _id = id; + _self = self; + } + + protected override void Handle( + TypeHierarchySubtypesParams request, IObserver> results, CancellationToken cancellationToken + ) + { + _self.Handle(request, results, cancellationToken); + } + + protected internal override TypeHierarchyRegistrationOptions CreateRegistrationOptions( + TypeHierarchyCapability capability, ClientCapabilities clientCapabilities + ) + { + return ( (IRegistration)_self ).GetRegistrationOptions( + capability, clientCapabilities + ); + } + } + } + + public abstract class TypeHierarchyHandlerBase : TypeHierarchyHandlerBase where T : class?, IHandlerIdentity? + { + protected TypeHierarchyHandlerBase(Guid id) : base(id) + { + } + + protected TypeHierarchyHandlerBase() : this(Guid.NewGuid()) + { + } + + public sealed override async Task?> Handle(TypeHierarchyPrepareParams request, CancellationToken cancellationToken) + { + var response = await HandlePrepare(request, cancellationToken).ConfigureAwait(false); + return Container.From(response?.Select(TypeHierarchyItem.From)!); + } + + public sealed override Task?> Handle( + TypeHierarchySupertypesParams request, CancellationToken cancellationToken + ) + { + return HandleSupertypes( + new TypeHierarchySupertypesParams + { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + cancellationToken + ); + } + + public sealed override Task?> Handle( + TypeHierarchySubtypesParams request, CancellationToken cancellationToken + ) + { + return HandleSubtypes( + new TypeHierarchySubtypesParams + { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + cancellationToken + ); + } + + protected abstract Task>?> HandlePrepare(TypeHierarchyPrepareParams request, CancellationToken cancellationToken); + + protected abstract Task?> HandleSupertypes( + TypeHierarchySupertypesParams request, CancellationToken cancellationToken + ); + + protected abstract Task?> HandleSubtypes( + TypeHierarchySubtypesParams request, CancellationToken cancellationToken + ); + } + + public abstract class PartialTypeHierarchyHandlerBase : PartialTypeHierarchyHandlerBase where T : class?, IHandlerIdentity? + { + protected PartialTypeHierarchyHandlerBase(IProgressManager progressManager) : base(progressManager) + { + } + + protected sealed override void Handle( + TypeHierarchyPrepareParams request, IObserver> results, CancellationToken cancellationToken + ) + { + Handle( + request, + Observer.Create>>( + x => results.OnNext(x.Select(z => (TypeHierarchyItem)z)), + results.OnError, + results.OnCompleted + ), cancellationToken + ); + } + + protected abstract void Handle( + TypeHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken + ); + + protected sealed override void Handle( + TypeHierarchySupertypesParams request, IObserver> results, CancellationToken cancellationToken + ) + { + Handle( + new TypeHierarchySupertypesParams + { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + results, + cancellationToken + ); + } + + protected abstract void Handle( + TypeHierarchySupertypesParams request, IObserver> results, CancellationToken cancellationToken + ); + + protected sealed override void Handle( + TypeHierarchySubtypesParams request, IObserver> results, CancellationToken cancellationToken + ) + { + Handle( + new TypeHierarchySubtypesParams + { + Item = request.Item, + PartialResultToken = request.PartialResultToken, + WorkDoneToken = request.WorkDoneToken + }, + results, + cancellationToken + ); + } + + protected abstract void Handle( + TypeHierarchySubtypesParams request, IObserver> results, CancellationToken cancellationToken + ); + } + + public static partial class TypeHierarchyExtensions + { + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func?>> handler, + Func?>> supertypesHandler, + Func?>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry + .AddHandler( + TextDocumentNames.PrepareTypeHierarchy, + new LanguageProtocolDelegatingHandlers.Request< + TypeHierarchyPrepareParams, + Container?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySupertypes, + new LanguageProtocolDelegatingHandlers.Request< + TypeHierarchySupertypesParams, + Container?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(supertypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySubtypes, + new LanguageProtocolDelegatingHandlers.Request< + TypeHierarchySubtypesParams, + Container?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + ; + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, TypeHierarchyCapability, CancellationToken, Task?>> + supertypesHandler, + Func, TypeHierarchyCapability, CancellationToken, Task?>> + subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + new DelegatingTypeHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(supertypesHandler), + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func?>> handler, + Func?>> supertypesHandler, + Func?>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry + .AddHandler( + TextDocumentNames.PrepareTypeHierarchy, + new LanguageProtocolDelegatingHandlers.Request< + TypeHierarchyPrepareParams, + Container?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySupertypes, + new LanguageProtocolDelegatingHandlers.Request< + TypeHierarchySupertypesParams, + Container?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(supertypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySubtypes, + new LanguageProtocolDelegatingHandlers.Request?, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ) + ; + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, TypeHierarchyCapability, Task?>> supertypesHandler, + Func, TypeHierarchyCapability, Task?>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + new DelegatingTypeHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(supertypesHandler), + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, CancellationToken, Task?>> supertypesHandler, + Func, CancellationToken, Task?>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + new DelegatingTypeHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(supertypesHandler), + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Func>?>> handler, + Func, Task?>> supertypesHandler, + Func, Task?>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + new DelegatingTypeHierarchyHandler( + HandlerAdapter.Adapt(handler), + HandlerAdapter.Adapt(supertypesHandler), + HandlerAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>, TypeHierarchyCapability, CancellationToken> handler, + Action>, TypeHierarchyCapability, CancellationToken> + supertypesHandler, + Action>, TypeHierarchyCapability, CancellationToken> + subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return registry.AddHandler( + TextDocumentNames.PrepareTypeHierarchy, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchyPrepareParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySupertypes, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchySupertypesParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(supertypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySubtypes, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchySubtypesParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + ; + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>>, TypeHierarchyCapability, CancellationToken> handler, + Action, IObserver>, TypeHierarchyCapability, CancellationToken> + supertypesHandler, + Action, IObserver>, TypeHierarchyCapability, CancellationToken> + subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + _ => + new DelegatingPartialTypeHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(supertypesHandler), + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>, TypeHierarchyCapability> handler, + Action>, TypeHierarchyCapability> supertypesHandler, + Action>, TypeHierarchyCapability> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) + { + var id = Guid.NewGuid(); + return + registry.AddHandler( + TextDocumentNames.PrepareTypeHierarchy, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchyPrepareParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(handler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySupertypes, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchySupertypesParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(supertypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + .AddHandler( + TextDocumentNames.TypeHierarchySubtypes, + _ => new LanguageProtocolDelegatingHandlers.PartialResults< + TypeHierarchySubtypesParams, + Container?, TypeHierarchyItem, + TypeHierarchyRegistrationOptions, + TypeHierarchyCapability + >( + id, + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory), + _.GetRequiredService(), + Container.From + ) + ) + ; + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>>, TypeHierarchyCapability> handler, + Action, IObserver>, TypeHierarchyCapability> supertypesHandler, + Action, IObserver>, TypeHierarchyCapability> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + _ => new DelegatingPartialTypeHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(supertypesHandler), + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>>, CancellationToken> handler, + Action, IObserver>, CancellationToken> supertypesHandler, + Action, IObserver>, CancellationToken> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + _ => new DelegatingPartialTypeHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(supertypesHandler), + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + public static ILanguageServerRegistry OnTypeHierarchy( + this ILanguageServerRegistry registry, + Action>>> handler, + Action, IObserver>> supertypesHandler, + Action, IObserver>> subtypesHandler, + RegistrationOptionsDelegate? registrationOptionsFactory + ) where T : class?, IHandlerIdentity? + { + return registry.AddHandler( + _ => new DelegatingPartialTypeHierarchyHandler( + _.GetRequiredService(), + PartialAdapter.Adapt(handler), + PartialAdapter.Adapt(supertypesHandler), + PartialAdapter.Adapt(subtypesHandler), + RegistrationAdapter.Adapt(registrationOptionsFactory) + ) + ); + } + + private class DelegatingTypeHierarchyHandler : TypeHierarchyHandlerBase where T : class?, IHandlerIdentity? + { + private readonly Func>?>> + _handlePrepare; + + private readonly Func, TypeHierarchyCapability, CancellationToken, + Task?>> + _handleSupertypes; + + private readonly Func, TypeHierarchyCapability, CancellationToken, + Task?>> + _handleSubtypes; + + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + + public DelegatingTypeHierarchyHandler( + Func>?>> handlePrepare, + Func, TypeHierarchyCapability, CancellationToken, Task?>> + handleSupertypes, + Func, TypeHierarchyCapability, CancellationToken, Task?>> + handleSubtypes, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _handlePrepare = handlePrepare; + _handleSupertypes = handleSupertypes; + _handleSubtypes = handleSubtypes; + _registrationOptionsFactory = registrationOptionsFactory; + } + + protected override Task>?> HandlePrepare(TypeHierarchyPrepareParams request, CancellationToken cancellationToken) + { + return _handlePrepare(request, Capability, cancellationToken); + } + + protected override Task?> HandleSupertypes( + TypeHierarchySupertypesParams request, CancellationToken cancellationToken + ) + { + return _handleSupertypes(request, Capability, cancellationToken); + } + + protected override Task?> HandleSubtypes( + TypeHierarchySubtypesParams request, CancellationToken cancellationToken + ) + { + return _handleSubtypes(request, Capability, cancellationToken); + } + + protected internal override TypeHierarchyRegistrationOptions CreateRegistrationOptions( + TypeHierarchyCapability capability, ClientCapabilities clientCapabilities + ) + { + return _registrationOptionsFactory(capability, clientCapabilities); + } + } + + private class DelegatingPartialTypeHierarchyHandler : PartialTypeHierarchyHandlerBase where T : class?, IHandlerIdentity? + { + private readonly Action>>, TypeHierarchyCapability, CancellationToken> + _handleParams; + + private readonly Action, IObserver>, TypeHierarchyCapability, + CancellationToken> + _handleSupertypes; + + private readonly Action, IObserver>, TypeHierarchyCapability, + CancellationToken> + _handleSubtypes; + + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + + public DelegatingPartialTypeHierarchyHandler( + IProgressManager progressManager, + Action>>, TypeHierarchyCapability, CancellationToken> handleParams, + Action, IObserver>, TypeHierarchyCapability, CancellationToken> + handleSupertypes, + Action, IObserver>, TypeHierarchyCapability, CancellationToken> + handleSubtypes, + RegistrationOptionsDelegate registrationOptionsFactory + ) : base(progressManager) + { + _handleParams = handleParams; + _handleSupertypes = handleSupertypes; + _handleSubtypes = handleSubtypes; + _registrationOptionsFactory = registrationOptionsFactory; + } + + protected override void Handle( + TypeHierarchyPrepareParams request, IObserver>> results, CancellationToken cancellationToken + ) + { + _handleParams(request, results, Capability, cancellationToken); + } + + protected override void Handle( + TypeHierarchySupertypesParams request, IObserver> results, CancellationToken cancellationToken + ) + { + _handleSupertypes(request, results, Capability, cancellationToken); + } + + protected override void Handle( + TypeHierarchySubtypesParams request, IObserver> results, CancellationToken cancellationToken + ) + { + _handleSubtypes(request, results, Capability, cancellationToken); + } + + protected internal override TypeHierarchyRegistrationOptions CreateRegistrationOptions( + TypeHierarchyCapability capability, ClientCapabilities clientCapabilities + ) + { + return _registrationOptionsFactory(capability, clientCapabilities); + } + } + } + } +} diff --git a/src/Protocol/Features/FileOperationsFeature.cs b/src/Protocol/Features/FileOperationsFeature.cs index b9d1b6829..158e0a40e 100644 --- a/src/Protocol/Features/FileOperationsFeature.cs +++ b/src/Protocol/Features/FileOperationsFeature.cs @@ -329,7 +329,7 @@ public record FileOperationFilter namespace Server.Capabilities { - public class FileOperationsWorkspaceServerCapabilities : DynamicCapability + public class FileOperationsWorkspaceServerCapabilities { /// /// The client has support for sending didCreateFiles notifications. diff --git a/src/Protocol/Features/ProgressFeature.cs b/src/Protocol/Features/ProgressFeature.cs index 9e971f13a..ee48a6187 100644 --- a/src/Protocol/Features/ProgressFeature.cs +++ b/src/Protocol/Features/ProgressFeature.cs @@ -130,12 +130,13 @@ public static IRequestProgressObservable RequestProgress @params, Func factory, + Func reverseFactory, CancellationToken cancellationToken = default - ) + ) where TResponse : TItem { @params.SetPartialResultToken(new ProgressToken(Guid.NewGuid().ToString())); - return requestRouter.ProgressManager.MonitorUntil(@params, factory, cancellationToken); + return requestRouter.ProgressManager.MonitorUntil(@params, factory, reverseFactory, cancellationToken); } public static IRequestProgressObservable, TResponse> RequestProgress( diff --git a/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs b/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs index 7a3ed66f9..8d93114d1 100644 --- a/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs +++ b/src/Protocol/Features/Window/ShowDocumentRequestFeature.cs @@ -12,7 +12,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol namespace Models { /// - /// Params to show a document. + /// Params to show a resource. /// /// @since 3.16.0 /// @@ -31,7 +31,7 @@ public record ShowDocumentParams : IRequest /// /// Indicates to show the resource in an external program. - /// To show for example `https://code.visualstudio.com/` + /// To show, for example, `https://code.visualstudio.com/` /// in the default WEB browser set `external` to `true`. /// [Optional] diff --git a/src/Protocol/Features/Window/WorkDoneProgressFeature.cs b/src/Protocol/Features/Window/WorkDoneProgressFeature.cs index f99bb1bd6..79aed087e 100644 --- a/src/Protocol/Features/Window/WorkDoneProgressFeature.cs +++ b/src/Protocol/Features/Window/WorkDoneProgressFeature.cs @@ -57,8 +57,11 @@ public abstract record WorkDoneProgress public WorkDoneProgressKind Kind { get; } /// - /// Optional, a final message indicating to for example indicate the outcome - /// of the operation. + /// Optional, more detailed associated progress message. Contains + /// complementary information to the `title`. + /// + /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". + /// If unset, the previous progress message(if any) is still valid. /// [Optional] public string? Message { get; init; } @@ -91,8 +94,8 @@ public WorkDoneProgressBegin() : base(WorkDoneProgressKind.Begin) /// /// 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. + /// long running operation. Clients that don't support cancellation are + /// allowed to ignore the setting. /// [Optional] public bool Cancellable { get; init; } @@ -103,7 +106,7 @@ public WorkDoneProgressBegin() : base(WorkDoneProgressKind.Begin) /// 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. + /// that are not following this rule. The value range is [0, 100] /// /// /// in the LSP spec @@ -137,11 +140,11 @@ 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. + /// 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. + /// 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; } @@ -152,7 +155,7 @@ public WorkDoneProgressReport() : base(WorkDoneProgressKind.Report) /// 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. + /// that are not following this rule. The value range is [0, 100] /// /// /// in the LSP spec diff --git a/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs b/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs index 8cd9eef48..fe48f3cef 100644 --- a/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs +++ b/src/Protocol/Features/Workspace/DidChangeWatchedFilesFeature.cs @@ -39,6 +39,12 @@ namespace Client.Capabilities [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.DidChangeWatchedFiles))] public partial class DidChangeWatchedFilesCapability : DynamicCapability { + /// + /// Whether the client has support for relative patterns + /// or not. + /// + [Optional] + public bool? RelativePatternSupport { get; init; } } } } diff --git a/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs b/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs index 1c34a435d..7626390d5 100644 --- a/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs +++ b/src/Protocol/Features/Workspace/WorkspaceSymbolsFeature.cs @@ -1,11 +1,15 @@ using System.Diagnostics; +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; 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 @@ -17,9 +21,26 @@ namespace Models /// [Parallel] [Method(WorkspaceNames.WorkspaceSymbol, Direction.ClientToServer)] - [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace", Name = "WorkspaceSymbols"), GenerateHandlerMethods, GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace", Name = "SymbolInformation"), GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] [RegistrationOptions(typeof(WorkspaceSymbolRegistrationOptions)), Capability(typeof(WorkspaceSymbolCapability))] - public partial record WorkspaceSymbolParams : IPartialItemsRequest?, SymbolInformation>, IWorkDoneProgressParams + public partial record SymbolInformationParams : IPartialItemsRequest?, SymbolInformation>, IWorkDoneProgressParams + { + /// + /// A non-empty query string + /// + public string Query { get; init; } + } + + /// + /// 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 record WorkspaceSymbolParams : IPartialItemsRequest?, WorkspaceSymbol>, IWorkDoneProgressParams { /// /// A non-empty query string @@ -71,14 +92,103 @@ public partial record SymbolInformation public override string ToString() => DebuggerDisplay; } + /// + /// A special workspace symbol that supports locations without a range + /// + /// @since 3.17.0 - proposed state + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [Method(WorkspaceNames.WorkspaceSymbolResolve, Direction.ClientToServer)] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Workspace", Name = "WorkspaceSymbolResolve")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(IWorkspaceLanguageClient), typeof(ILanguageClient))] + [Capability(typeof(WorkspaceSymbolCapability))] + public partial record WorkspaceSymbol : IRequest + { + /// + /// The name of this symbol. + /// + public string Name { get; set; } + + /// + /// The kind of this symbol. + /// + public SymbolKind Kind { get; set; } + + /// + /// Tags for this completion item. + /// + [Optional] + public Container? Tags { get; set; } + + /// + /// The name of the symbol containing this symbol. This information is for + /// user interface purposes (e.g. to render a qualifier in the user interface + /// if necessary). It can't be used to re-infer a hierarchy for the document + /// symbols. + /// + [Optional] + public string? ContainerName { get; set; } + + /// + /// The location of this symbol. Whether a server is allowed to + /// return a location without a range depends on the client + /// capability `workspace.symbol.resolveSupport`. + /// + /// See also `SymbolInformation.location`. + /// + public LocationOrFileLocation Location { get; set; } + + /// + /// A data entry field that is preserved on a workspace symbol between a + /// workspace symbol request and a workspace symbol resolve request. + /// + public JToken? Data { get; set; } + + private string DebuggerDisplay => $"[{Kind}@{Location}] {Name}"; + + /// + public override string ToString() => DebuggerDisplay; + } + [GenerateRegistrationOptions(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + [RegistrationOptionsConverter(typeof(WorkspaceSymbolRegistrationOptionsConverter))] [RegistrationName(WorkspaceNames.WorkspaceSymbol)] - public partial class WorkspaceSymbolRegistrationOptions : IWorkDoneProgressOptions { } + public partial class WorkspaceSymbolRegistrationOptions : IWorkDoneProgressOptions + { + /// + /// The server provides support to resolve additional + /// information for a workspace symbol. + /// + [Optional] + public bool ResolveProvider { get; set; } + + private class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public WorkspaceSymbolRegistrationOptionsConverter(IHandlersManager handlersManager) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) + { + return new() + { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IWorkspaceSymbolResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } + } } + namespace Client.Capabilities { [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Symbol))] - public partial class WorkspaceSymbolCapability : DynamicCapability// + public partial class WorkspaceSymbolCapability : DynamicCapability // { /// /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. @@ -87,7 +197,7 @@ public partial class WorkspaceSymbolCapability : DynamicCapability// public SymbolKindCapabilityOptions? SymbolKind { get; set; } /// - /// The client supports tags on `SymbolInformation`.Tags are supported on + /// The client supports tags on `SymbolInformation` and `WorkspaceSymbol`. Tags are supported on /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. /// Clients supporting tags have to handle unknown tags gracefully. /// @@ -95,6 +205,67 @@ public partial class WorkspaceSymbolCapability : DynamicCapability// /// [Optional] public Supports TagSupport { get; set; } + + + /// + /// The client support partial workspace symbols. The client will send the + /// request `workspaceSymbol/resolve` to the server to resolve additional + /// properties. + /// + /// @since 3.17.0 - proposedState + /// + [Optional] + public ResolveSupportCapabilityOptions? ResolveSupport { 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 + /// + public class TagSupportCapabilityOptions + { + /// + /// The tags supported by the client. + /// + public Container ValueSet { get; set; } = null!; + } + + /// + /// Specific capabilities for the `SymbolKind`. + /// + public class SymbolKindCapabilityOptions + { + /// + /// The symbol 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 symbol kinds from `File` to `Array` as defined in + /// the initial version of the protocol. + /// + [Optional] + public Container? ValueSet { get; set; } + } + + /// + /// The client support partial workspace symbols. The client will send the + /// request `workspaceSymbol/resolve` to the server to resolve additional + /// properties. + /// + /// @since 3.17.0 - proposedState + /// + public partial class ResolveSupportCapabilityOptions + { + /// + /// The properties that a client can resolve lazily. Usually + /// `location.range` + /// + public Container Properties { get; set; } = new(); } } } diff --git a/src/Protocol/Generation/GenerateContainerAttribute.cs b/src/Protocol/Generation/GenerateContainerAttribute.cs index 582e7a175..96d9636c4 100644 --- a/src/Protocol/Generation/GenerateContainerAttribute.cs +++ b/src/Protocol/Generation/GenerateContainerAttribute.cs @@ -18,5 +18,7 @@ public GenerateContainerAttribute(string? className = null) { } + + public bool GenerateImplicitConversion { get; set; } } } diff --git a/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs b/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs index d24f59ae6..4bbced7e0 100644 --- a/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs +++ b/src/Protocol/Generation/GenerateRegistrationOptionsAttribute.cs @@ -13,13 +13,20 @@ public class GenerateRegistrationOptionsAttribute : Attribute { public bool SupportsWorkDoneProgress { get; init; } public bool SupportsStaticRegistrationOptions { get; init; } - public bool SupportsDocumentSelector { get; init; } + public bool SupportsTextDocumentSelector { get; init; } + public bool SupportsNotebookDocumentSelector { get; init; } public Type? Converter { get; init; } public bool SupportsTextDocument { - get => SupportsDocumentSelector; - init => SupportsDocumentSelector = value; + get => SupportsTextDocumentSelector; + init => SupportsTextDocumentSelector = value; + } + + public bool SupportsNotebookDocument + { + get => SupportsNotebookDocumentSelector; + init => SupportsNotebookDocumentSelector = value; } public GenerateRegistrationOptionsAttribute(string? key = null, params string?[] keys) diff --git a/src/Protocol/ILanguageProtocolRpcOptions.cs b/src/Protocol/ILanguageProtocolRpcOptions.cs index 209e258c8..c02f21326 100644 --- a/src/Protocol/ILanguageProtocolRpcOptions.cs +++ b/src/Protocol/ILanguageProtocolRpcOptions.cs @@ -8,5 +8,7 @@ public interface ILanguageProtocolRpcOptions : IJsonRpcHandlerRegistry, IJ { T AddTextDocumentIdentifier(params ITextDocumentIdentifier[] handlers); T AddTextDocumentIdentifier() where TTextDocumentIdentifier : ITextDocumentIdentifier; + T AddNotebookDocumentIdentifier(params INotebookDocumentIdentifier[] handlers); + T AddNotebookDocumentIdentifier() where TNotebookDocumentIdentifier : INotebookDocumentIdentifier; } } diff --git a/src/Protocol/IRegistrationManager.cs b/src/Protocol/IRegistrationManager.cs index 000802dfc..2e721b31a 100644 --- a/src/Protocol/IRegistrationManager.cs +++ b/src/Protocol/IRegistrationManager.cs @@ -10,7 +10,7 @@ public interface IRegistrationManager IObservable> Registrations { get; } IEnumerable CurrentRegistrations { get; } IEnumerable GetRegistrationsForMethod(string method); - IEnumerable GetRegistrationsMatchingSelector(DocumentSelector documentSelector); + IEnumerable GetRegistrationsMatchingSelector(TextDocumentSelector textDocumentSelector); void RegisterCapabilities(ServerCapabilities serverCapabilities); } } diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.CanBeResolved.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.CanBeResolved.cs new file mode 100644 index 000000000..c73acd41e --- /dev/null +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.CanBeResolved.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class LanguageProtocolDelegatingHandlers + { + public sealed class CanBeResolved : + AbstractHandlers.Base, + ICanBeResolvedHandler, + ICanBeIdentifiedHandler + where TItem : ICanBeResolved, IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func> _resolveHandler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public CanBeResolved( + Guid id, Func> resolveHandler, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _resolveHandler = resolveHandler; + _registrationOptionsFactory = registrationOptionsFactory; + _id = id; + } + + Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, Capability, cancellationToken); + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class CanBeResolved : + AbstractHandlers.Base, + ICanBeResolvedHandler, + ICanBeIdentifiedHandler + where TItem : ICanBeResolved, IRequest + where TRegistrationOptions : class, new() + { + private readonly Func> _resolveHandler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public CanBeResolved(Guid id, Func> resolveHandler, RegistrationOptionsDelegate registrationOptionsFactory) + { + _id = id; + _resolveHandler = resolveHandler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, cancellationToken); + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); + } + } +} diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.Notification.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.Notification.cs new file mode 100644 index 000000000..ca1b7a124 --- /dev/null +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.Notification.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class LanguageProtocolDelegatingHandlers + { + public sealed class Notification : + AbstractHandlers.Base, + IJsonRpcNotificationHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public Notification( + Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + public Notification( + Func handler, RegistrationOptionsDelegate registrationOptionsFactory + ) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class Notification : + AbstractHandlers.Base, + IJsonRpcNotificationHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + private readonly Func _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public Notification(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + public Notification(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); + } + + public sealed class NotificationCapability : + AbstractHandlers.BaseCapability, + IJsonRpcNotificationHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TCapability : ICapability + { + private readonly Func _handler; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public NotificationCapability(Guid id, Func handler) + { + _id = id; + _handler = handler; + } + + public NotificationCapability(Func handler) : + this(Guid.Empty, handler) + { + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } + } +} diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.Partial.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.Partial.cs new file mode 100644 index 000000000..7df35bc0b --- /dev/null +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.Partial.cs @@ -0,0 +1,503 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol +{ + public static partial class LanguageProtocolDelegatingHandlers + { + public sealed class PartialResult : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemRequest + where TItem : class? + where TResponse : class? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func _factory; + private readonly Action, TCapability, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResult( + Guid id, Action, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + } + + 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 + ) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject(); + var task = subject + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class PartialResult : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemRequest + where TItem : class? + where TResponse : class? + where TRegistrationOptions : class, new() + { + private readonly Action, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResult( + Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func factory + ) : + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResult( + Guid id, Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + } + + 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 default; + } + + using var subject = new Subject(); + var task = subject + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, cancellationToken); + return await task; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); + } + + public sealed class PartialResultCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemRequest + where TItem : class? + where TResponse : class? + where TCapability : ICapability + { + private readonly Action, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultCapability( + Action, CancellationToken> handler, IProgressManager progressManager, Func factory + ) : + this(Guid.Empty, handler, progressManager, factory) + { + } + + public PartialResultCapability( + Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + _handler(request, Capability, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject(); + var task = subject + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, Capability, subject, cancellationToken); + return await task; + } + } + + public sealed class PartialResult : + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemRequest + where TItem : class? + where TResponse : class? + { + private readonly Action, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResult(Action, CancellationToken> handler, IProgressManager progressManager, Func factory) : + this(Guid.Empty, handler, progressManager, factory) + { + } + + public PartialResult(Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + 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 default; + } + + using var subject = new Subject(); + var task = subject + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, cancellationToken); + return await task; + } + } + + public sealed class PartialResults : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsRequest + where TItem : class? + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Action>, TCapability, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResults( + Action>, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func, TResponse?> factory + ) : + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResults( + Guid id, Action>, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, Func, TResponse?> factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class PartialResults : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsRequest + where TItem : class? + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + { + private readonly Action>, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResults( + Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func, TResponse?> factory + ) : + this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResults( + Guid id, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func, TResponse?> factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + } + + 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 default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, cancellationToken); + return await task; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); + } + + public sealed class PartialResultsCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsRequest + where TItem : class? + where TResponse : IEnumerable? + where TCapability : ICapability + { + private readonly Action>, TCapability, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultsCapability( + Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse?> factory + ) : + this(Guid.Empty, handler, progressManager, factory) + { + } + + public PartialResultsCapability( + Guid id, Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse?> factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + } + + public sealed class PartialResults : + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsRequest + where TItem : class? + where TResponse : IEnumerable? + { + private readonly Action>, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse?> _factory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResults( + Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory + ) : + this(Guid.Empty, handler, progressManager, factory) + { + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + public PartialResults( + Guid id, Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + 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 default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate( + new List(), (acc, items) => { + acc.AddRange(items); + return acc; + } + ) + .Select(_factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, cancellationToken); + return await task; + } + } + } +} diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.PartialWithInitialValue.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.PartialWithInitialValue.cs new file mode 100644 index 000000000..50573ab29 --- /dev/null +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.PartialWithInitialValue.cs @@ -0,0 +1,542 @@ +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol; + +public static partial class LanguageProtocolDelegatingHandlers +{ + public sealed class PartialResultWithInitialValue : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemWithInitialValueRequest + where TItem : class? + where TResponse : TItem? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func _factory; + private readonly Func> _initialValue; + private readonly Action, TCapability, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultWithInitialValue( + Guid id, + Func> initialValue, + Action, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + public PartialResultWithInitialValue( + Func> initialValue, + Action, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func factory + ) : + this(Guid.Empty, initialValue, handler, registrationOptionsFactory, progressManager, factory) + { + } + + async Task IRequestHandler.Handle( + TParams request, + CancellationToken cancellationToken + ) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + observer.OnNext(await _initialValue(request, Capability, cancellationToken)); + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await _initialValue(request, Capability, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class PartialResultWithInitialValue : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemWithInitialValueRequest + where TItem : class? + where TResponse : TItem? + where TRegistrationOptions : class, new() + { + private readonly Action, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultWithInitialValue( + Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func factory, + Func> initialValue + ) : + this(Guid.Empty, initialValue, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResultWithInitialValue( + Guid id, + Func> initialValue, + Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + observer.OnNext(await _initialValue(request, cancellationToken)); + _handler(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await _initialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, cancellationToken); + return await task; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(clientCapabilities); + } + + public sealed class PartialResultWithInitialValueCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemWithInitialValueRequest + where TItem : class? + where TResponse : TItem? + where TCapability : ICapability + { + private readonly Action, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultWithInitialValueCapability( + Func> initialValue, + Action, CancellationToken> handler, + IProgressManager progressManager, + Func factory + ) : + this(Guid.Empty, initialValue, handler, progressManager, factory) + { + } + + public PartialResultWithInitialValueCapability( + Guid id, + Func> initialValue, + Action, CancellationToken> handler, + IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + observer.OnNext(await _initialValue(request, Capability, cancellationToken)); + _handler(request, Capability, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await _initialValue(request, Capability, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, Capability, subject, cancellationToken); + return await task; + } + } + + public sealed class PartialResultWithInitialValue : + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemWithInitialValueRequest + where TItem : class? + where TResponse : TItem? + { + private readonly Action, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultWithInitialValue( + Func> initialValue, + Action, CancellationToken> handler, + IProgressManager progressManager, + Func factory + ) : + this(Guid.Empty, initialValue, handler, progressManager, factory) + { + } + + public PartialResultWithInitialValue( + Guid id, + Func> initialValue, + Action, CancellationToken> handler, + IProgressManager progressManager, + Func factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver.Noop) + { + observer.OnNext(await _initialValue(request, cancellationToken)); + _handler(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new AsyncSubject(); + var task = subject + .Aggregate(await _initialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + // in the event nothing is emitted... + subject.OnNext(default!); + _handler(request, subject, cancellationToken); + return await task; + } + } + + public sealed class PartialResultsWithInitialValue : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsWithInitialValueRequest + where TItem : class? + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Action>, TCapability, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultsWithInitialValue( + Func> initialValue, + Action>, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, + Func, TResponse> factory + ) : + this(Guid.Empty, initialValue, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResultsWithInitialValue( + Guid id, + Func> initialValue, + Action>, TCapability, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, Func, TResponse> factory + + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + observer.OnNext(await _initialValue(request, Capability, cancellationToken)); + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate(await _initialValue(request, Capability, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class PartialResultsWithInitialValue : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsWithInitialValueRequest + where TItem : class? + where TResponse : IEnumerable? + where TRegistrationOptions : class, new() + { + private readonly Action>, CancellationToken> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultsWithInitialValue( + Func> initialValue, + Action>, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func, TResponse> factory + + ) : + this(Guid.Empty, initialValue, handler, registrationOptionsFactory, progressManager, factory) + { + } + + public PartialResultsWithInitialValue( + Guid id, + Func> initialValue, + Action>, CancellationToken> handler, + RegistrationOptionsDelegate registrationOptionsFactory, + IProgressManager progressManager, + Func, TResponse> factory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + observer.OnNext(await _initialValue(request, cancellationToken)); + _handler(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate(await _initialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, cancellationToken); + return await task; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(clientCapabilities); + } + + public sealed class PartialResultsWithInitialValueCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsWithInitialValueRequest + where TItem : class? + where TResponse : IEnumerable? + where TCapability : ICapability + { + private readonly Action>, TCapability, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultsWithInitialValueCapability( + Func> initialValue, + Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse> factory + ) : + this(Guid.Empty, initialValue, handler, progressManager, factory) + { + } + + public PartialResultsWithInitialValueCapability( + Guid id, + Func> initialValue, + Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse> factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + observer.OnNext(await _initialValue(request, Capability, cancellationToken)); + _handler(request, observer, Capability, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate(await _initialValue(request, Capability, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, Capability, cancellationToken); + return await task; + } + } + + public sealed class PartialResultsWithInitialValue : + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IPartialItemsWithInitialValueRequest + where TItem : class? + where TResponse : IEnumerable? + { + private readonly Action>, CancellationToken> _handler; + private readonly IProgressManager _progressManager; + private readonly Func, TResponse> _factory; + private readonly Func> _initialValue; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public PartialResultsWithInitialValue( + Func> initialValue, + Action>, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse> factory + + ) : + this(Guid.Empty, initialValue, handler, progressManager, factory) + { + _handler = handler; + _progressManager = progressManager; + _factory = factory; + } + + public PartialResultsWithInitialValue( + Guid id, + Func> initialValue, + Action>, CancellationToken> handler, IProgressManager progressManager, + Func, TResponse> factory + ) + { + _id = id; + _handler = handler; + _progressManager = progressManager; + _factory = factory; + _initialValue = initialValue; + } + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + var observer = _progressManager.For(request, cancellationToken); + if (observer != ProgressObserver>.Noop) + { + observer.OnNext(await _initialValue(request, cancellationToken)); + _handler(request, observer, cancellationToken); + await observer; + return default; + } + + using var subject = new Subject>(); + var task = subject + .Aggregate(await _initialValue(request, cancellationToken), _factory) + .ToTask(cancellationToken, _progressManager.Scheduler) + .ConfigureAwait(false); + _handler(request, subject, cancellationToken); + return await task; + } + } +} diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.Request.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.Request.cs new file mode 100644 index 000000000..b269ffe4f --- /dev/null +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.Request.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol; + +public static partial class LanguageProtocolDelegatingHandlers +{ + public sealed class Request : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public Request( + Guid id, Func> handler, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + public Request( + Func> handler, + RegistrationOptionsDelegate registrationOptionsFactory + ) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => + _handler(request, Capability, cancellationToken); + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class Request : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + where TCapability : ICapability + { + private readonly Func _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public Request( + Guid id, Func handler, + RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + public Request( + Func handler, + RegistrationOptionsDelegate registrationOptionsFactory + ) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + + async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(capability, clientCapabilities); + } + + public sealed class RequestRegistration : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + private readonly Func> _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public RequestRegistration( + Func> handler, RegistrationOptionsDelegate registrationOptionsFactory + ) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + public RequestRegistration( + Guid id, Func> handler, RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => + _handler(request, cancellationToken); + + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(clientCapabilities); + } + + public sealed class RequestRegistration : + AbstractHandlers.Base, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TRegistrationOptions : class, new() + { + private readonly Func _handler; + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public RequestRegistration( + Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory + ) + { + _id = id; + _handler = handler; + _registrationOptionsFactory = registrationOptionsFactory; + } + + public RequestRegistration( + Func handler, RegistrationOptionsDelegate registrationOptionsFactory + ) : + this(Guid.Empty, handler, registrationOptionsFactory) + { + } + + async Task IRequestHandler. + Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + + protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => + _registrationOptionsFactory(clientCapabilities); + } + + public sealed class RequestCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TCapability : ICapability + { + private readonly Func> _handler; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public RequestCapability(Func> handler) : + this(Guid.Empty, handler) + { + } + + public RequestCapability(Guid id, Func> handler) + { + _id = id; + _handler = handler; + } + + Task IRequestHandler. + Handle(TParams request, CancellationToken cancellationToken) => + _handler(request, Capability, cancellationToken); + } + + public sealed class RequestCapability : + AbstractHandlers.BaseCapability, + IJsonRpcRequestHandler, + ICanBeIdentifiedHandler + where TParams : IRequest + where TCapability : ICapability + { + private readonly Func _handler; + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + + public RequestCapability(Func handler) : + this(Guid.Empty, handler) + { + } + + public RequestCapability(Guid id, Func handler) + { + _id = id; + _handler = handler; + } + + async Task IRequestHandler. + Handle(TParams request, CancellationToken cancellationToken) + { + await _handler(request, Capability, cancellationToken).ConfigureAwait(false); + return Unit.Value; + } + } +} diff --git a/src/Protocol/LanguageProtocolDelegatingHandlers.cs b/src/Protocol/LanguageProtocolDelegatingHandlers.cs index 1b6386b75..899531ca3 100644 --- a/src/Protocol/LanguageProtocolDelegatingHandlers.cs +++ b/src/Protocol/LanguageProtocolDelegatingHandlers.cs @@ -14,844 +14,8 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol { - public static class LanguageProtocolDelegatingHandlers + public static partial class LanguageProtocolDelegatingHandlers { - public sealed class Request : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Func> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public Request( - Guid id, Func> handler, - RegistrationOptionsDelegate registrationOptionsFactory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - public Request( - Func> handler, RegistrationOptionsDelegate registrationOptionsFactory - ) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => - _handler(request, Capability, cancellationToken); - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class CanBeResolved : - AbstractHandlers.Base, - ICanBeResolvedHandler, - ICanBeIdentifiedHandler - where TItem : ICanBeResolved, IRequest - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Func> _resolveHandler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public CanBeResolved( - Guid id, Func> resolveHandler, - RegistrationOptionsDelegate registrationOptionsFactory - ) - { - _resolveHandler = resolveHandler; - _registrationOptionsFactory = registrationOptionsFactory; - _id = id; - } - - Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, Capability, cancellationToken); - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class CanBeResolved : - AbstractHandlers.Base, - ICanBeResolvedHandler, - ICanBeIdentifiedHandler - where TItem : ICanBeResolved, IRequest - where TRegistrationOptions : class, new() - { - private readonly Func> _resolveHandler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public CanBeResolved(Guid id, Func> resolveHandler, RegistrationOptionsDelegate registrationOptionsFactory) - { - _id = id; - _resolveHandler = resolveHandler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - Task IRequestHandler.Handle(TItem request, CancellationToken cancellationToken) => _resolveHandler(request, cancellationToken); - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class Request : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Func _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public Request( - Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - public Request(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class RequestRegistration : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - { - private readonly Func> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public RequestRegistration(Func> handler, RegistrationOptionsDelegate registrationOptionsFactory) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - public RequestRegistration( - Guid id, Func> handler, RegistrationOptionsDelegate registrationOptionsFactory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) => _handler(request, cancellationToken); - - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class RequestRegistration : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - { - private readonly Func _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public RequestRegistration(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - public RequestRegistration(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - async Task IRequestHandler. - Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class RequestCapability : - AbstractHandlers.BaseCapability, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TCapability : ICapability - { - private readonly Func> _handler; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public RequestCapability(Func> handler) : - this(Guid.Empty, handler) - { - } - - public RequestCapability(Guid id, Func> handler) - { - _id = id; - _handler = handler; - } - - Task IRequestHandler. - Handle(TParams request, CancellationToken cancellationToken) => - _handler(request, Capability, cancellationToken); - } - - public sealed class RequestCapability : - AbstractHandlers.BaseCapability, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TCapability : ICapability - { - private readonly Func _handler; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public RequestCapability(Func handler) : - this(Guid.Empty, handler) - { - } - - public RequestCapability(Guid id, Func handler) - { - _id = id; - _handler = handler; - } - - async Task IRequestHandler. - Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - - public sealed class PartialResult : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemRequest - where TItem : class? - where TResponse : class? - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Func _factory; - private readonly Action, TCapability, CancellationToken> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly IProgressManager _progressManager; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResult( - Guid id, Action, TCapability, CancellationToken> handler, - RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, - Func factory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - _progressManager = progressManager; - _factory = factory; - } - - 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 - ) - { - var observer = _progressManager.For(request, cancellationToken); - if (observer != ProgressObserver.Noop) - { - _handler(request, observer, Capability, cancellationToken); - await observer; - return _factory(default); - } - - var subject = new AsyncSubject(); - var task = subject - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - // in the event nothing is emitted... - subject.OnNext(default!); - _handler(request, subject, Capability, cancellationToken); - return await task; - } - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class PartialResult : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemRequest - where TItem : class? - where TResponse : class? - where TRegistrationOptions : class, new() - { - private readonly Action, CancellationToken> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly IProgressManager _progressManager; - private readonly Func _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResult( - Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, - IProgressManager progressManager, - Func factory - ) : - this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) - { - } - - public PartialResult( - Guid id, Action, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, - IProgressManager progressManager, - Func factory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - _progressManager = progressManager; - _factory = factory; - } - - 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 _factory(default); - } - - var subject = new AsyncSubject(); - var task = subject - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - // in the event nothing is emitted... - subject.OnNext(default!); - _handler(request, subject, cancellationToken); - return await task; - } - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class PartialResultCapability : - AbstractHandlers.BaseCapability, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemRequest - where TItem : class? - where TResponse : class? - where TCapability : ICapability - { - private readonly Action, CancellationToken> _handler; - private readonly IProgressManager _progressManager; - private readonly Func _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResultCapability( - Action, CancellationToken> handler, IProgressManager progressManager, Func factory - ) : - this(Guid.Empty, handler, progressManager, factory) - { - } - - public PartialResultCapability( - Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory - ) - { - _id = id; - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - var observer = _progressManager.For(request, cancellationToken); - if (observer != ProgressObserver.Noop) - { - _handler(request, Capability, observer, cancellationToken); - await observer; - return _factory(default); - } - - var subject = new AsyncSubject(); - var task = subject - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - // in the event nothing is emitted... - subject.OnNext(default!); - _handler(request, Capability, subject, cancellationToken); - return await task; - } - } - - public sealed class PartialResult : - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemRequest - where TItem : class? - where TResponse : class? - { - private readonly Action, CancellationToken> _handler; - private readonly IProgressManager _progressManager; - private readonly Func _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResult(Action, CancellationToken> handler, IProgressManager progressManager, Func factory) : - this(Guid.Empty, handler, progressManager, factory) - { - } - - public PartialResult(Guid id, Action, CancellationToken> handler, IProgressManager progressManager, Func factory) - { - _id = id; - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - 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 _factory(default); - } - - var subject = new AsyncSubject(); - var task = subject - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - // in the event nothing is emitted... - subject.OnNext(default!); - _handler(request, subject, cancellationToken); - return await task; - } - } - - public sealed class PartialResults : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemsRequest - where TItem : class? - where TResponse : IEnumerable? - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Action>, TCapability, CancellationToken> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly IProgressManager _progressManager; - private readonly Func, TResponse?> _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResults( - Action>, TCapability, CancellationToken> handler, - RegistrationOptionsDelegate registrationOptionsFactory, IProgressManager progressManager, - Func, TResponse?> factory - ) : - this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>, TCapability, CancellationToken> handler, - RegistrationOptionsDelegate registrationOptionsFactory, - IProgressManager progressManager, Func, TResponse?> factory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - _progressManager = progressManager; - _factory = factory; - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - var observer = _progressManager.For(request, cancellationToken); - if (observer != ProgressObserver>.Noop) - { - _handler(request, observer, Capability, cancellationToken); - await observer; - return _factory(Enumerable.Empty()); - } - - var subject = new Subject>(); - var task = subject - .Aggregate( - new List(), (acc, items) => { - acc.AddRange(items); - return acc; - } - ) - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - _handler(request, subject, Capability, cancellationToken); - return await task; - } - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class PartialResults : - AbstractHandlers.Base, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemsRequest - where TItem : class? - where TResponse : IEnumerable? - where TRegistrationOptions : class, new() - { - private readonly Action>, CancellationToken> _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly IProgressManager _progressManager; - private readonly Func, TResponse?> _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResults( - Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, - IProgressManager progressManager, - Func, TResponse?> factory - ) : - this(Guid.Empty, handler, registrationOptionsFactory, progressManager, factory) - { - } - - public PartialResults( - Guid id, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptionsFactory, - IProgressManager progressManager, - Func, TResponse?> factory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - _progressManager = progressManager; - _factory = factory; - } - - 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 _factory(Enumerable.Empty()); - } - - var subject = new Subject>(); - var task = subject - .Aggregate( - new List(), (acc, items) => { - acc.AddRange(items); - return acc; - } - ) - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - _handler(request, subject, cancellationToken); - return await task; - } - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class PartialResultsCapability : - AbstractHandlers.BaseCapability, - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemsRequest - where TItem : class? - where TResponse : IEnumerable? - where TCapability : ICapability - { - private readonly Action>, TCapability, CancellationToken> _handler; - private readonly IProgressManager _progressManager; - private readonly Func, TResponse?> _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResultsCapability( - Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, - Func, TResponse?> factory - ) : - this(Guid.Empty, handler, progressManager, factory) - { - } - - public PartialResultsCapability( - Guid id, Action>, TCapability, CancellationToken> handler, IProgressManager progressManager, - Func, TResponse?> factory - ) - { - _id = id; - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - var observer = _progressManager.For(request, cancellationToken); - if (observer != ProgressObserver>.Noop) - { - _handler(request, observer, Capability, cancellationToken); - await observer; - return _factory(Enumerable.Empty()); - } - - var subject = new Subject>(); - var task = subject - .Aggregate( - new List(), (acc, items) => { - acc.AddRange(items); - return acc; - } - ) - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - _handler(request, subject, Capability, cancellationToken); - return await task; - } - } - - public sealed class PartialResults : - IJsonRpcRequestHandler, - ICanBeIdentifiedHandler - where TParams : IPartialItemsRequest - where TItem : class? - where TResponse : IEnumerable? - { - private readonly Action>, CancellationToken> _handler; - private readonly IProgressManager _progressManager; - private readonly Func, TResponse?> _factory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public PartialResults( - Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory - ) : - this(Guid.Empty, handler, progressManager, factory) - { - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - public PartialResults( - Guid id, Action>, CancellationToken> handler, IProgressManager progressManager, Func, TResponse?> factory - ) - { - _id = id; - _handler = handler; - _progressManager = progressManager; - _factory = factory; - } - - 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 _factory(Enumerable.Empty()); - } - - var subject = new Subject>(); - var task = subject - .Aggregate( - new List(), (acc, items) => { - acc.AddRange(items); - return acc; - } - ) - .Select(_factory) - .ToTask(cancellationToken, _progressManager.Scheduler) - .ConfigureAwait(false); - _handler(request, subject, cancellationToken); - return await task; - } - } - - public sealed class Notification : - AbstractHandlers.Base, - IJsonRpcNotificationHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - where TCapability : ICapability - { - private readonly Func _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public Notification( - Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory - ) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - public Notification( - Func handler, RegistrationOptionsDelegate registrationOptionsFactory - ) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected internal override TRegistrationOptions CreateRegistrationOptions(TCapability capability, ClientCapabilities clientCapabilities) => - _registrationOptionsFactory(capability, clientCapabilities); - } - - public sealed class Notification : - AbstractHandlers.Base, - IJsonRpcNotificationHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TRegistrationOptions : class, new() - { - private readonly Func _handler; - private readonly RegistrationOptionsDelegate _registrationOptionsFactory; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public Notification(Guid id, Func handler, RegistrationOptionsDelegate registrationOptionsFactory) - { - _id = id; - _handler = handler; - _registrationOptionsFactory = registrationOptionsFactory; - } - - public Notification(Func handler, RegistrationOptionsDelegate registrationOptionsFactory) : - this(Guid.Empty, handler, registrationOptionsFactory) - { - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - - protected override TRegistrationOptions CreateRegistrationOptions(ClientCapabilities clientCapabilities) => _registrationOptionsFactory(clientCapabilities); - } - - public sealed class NotificationCapability : - AbstractHandlers.BaseCapability, - IJsonRpcNotificationHandler, - ICanBeIdentifiedHandler - where TParams : IRequest - where TCapability : ICapability - { - private readonly Func _handler; - private readonly Guid _id; - Guid ICanBeIdentifiedHandler.Id => _id; - - public NotificationCapability(Guid id, Func handler) - { - _id = id; - _handler = handler; - } - - public NotificationCapability(Func handler) : - this(Guid.Empty, handler) - { - } - - async Task IRequestHandler.Handle(TParams request, CancellationToken cancellationToken) - { - await _handler(request, Capability, cancellationToken).ConfigureAwait(false); - return Unit.Value; - } - } - public sealed class TypedPartialObserver : IObserver> { private readonly IObserver> _results; diff --git a/src/Protocol/LanguageProtocolRpcOptionsBase.cs b/src/Protocol/LanguageProtocolRpcOptionsBase.cs index 6f5339b15..8fbd76e04 100644 --- a/src/Protocol/LanguageProtocolRpcOptionsBase.cs +++ b/src/Protocol/LanguageProtocolRpcOptionsBase.cs @@ -32,6 +32,22 @@ public T AddTextDocumentIdentifier() where TI : ITextDocumentIdentifier return (T)(object)this; } + public T AddNotebookDocumentIdentifier(params INotebookDocumentIdentifier[] handlers) + { + foreach (var item in handlers) + { + Services.AddSingleton(typeof(INotebookDocumentIdentifier), item); + } + + return (T)(object)this; + } + + public T AddNotebookDocumentIdentifier() where TI : INotebookDocumentIdentifier + { + Services.AddSingleton(typeof(INotebookDocumentIdentifier), typeof(TI)); + return (T)(object)this; + } + public LspSerializer Serializer { get; set; } = new LspSerializer(ClientVersion.Lsp3); public ConfigurationBuilder ConfigurationBuilder { get; set; } = new ConfigurationBuilder(); internal bool AddDefaultLoggingProvider { get; set; } diff --git a/src/Protocol/Models/CreateFile.cs b/src/Protocol/Models/CreateFile.cs index 4ddfce1cc..76990d791 100644 --- a/src/Protocol/Models/CreateFile.cs +++ b/src/Protocol/Models/CreateFile.cs @@ -18,13 +18,13 @@ public record CreateFile : IFile public DocumentUri Uri { get; init; } = null!; /// - /// Additional Options + /// Additional options /// [Optional] public CreateFileOptions? Options { get; init; } /// - /// An optional annotation describing the operation. + /// An optional annotation identifier describing the operation. /// /// @since 3.16.0 /// diff --git a/src/Protocol/Models/DeleteFile.cs b/src/Protocol/Models/DeleteFile.cs index 5a9438caf..c1ebc4caf 100644 --- a/src/Protocol/Models/DeleteFile.cs +++ b/src/Protocol/Models/DeleteFile.cs @@ -18,13 +18,13 @@ public record DeleteFile : IFile public DocumentUri Uri { get; init; } = null!; /// - /// Delete Options. + /// Delete options. /// [Optional] public DeleteFileOptions? Options { get; init; } /// - /// An optional annotation describing the operation. + /// An optional annotation identifier describing the operation. /// /// @since 3.16.0 /// diff --git a/src/Protocol/Models/Diagnostic.cs b/src/Protocol/Models/Diagnostic.cs index b8bac7195..b61a463ff 100644 --- a/src/Protocol/Models/Diagnostic.cs +++ b/src/Protocol/Models/Diagnostic.cs @@ -26,7 +26,7 @@ public partial record Diagnostic : ICanHaveData public DiagnosticSeverity? Severity { get; init; } /// - /// The diagnostic's code. Can be omitted. + /// The diagnostic's code, which might appear in the user interface. /// [Optional] public DiagnosticCode? Code { get; init; } @@ -67,8 +67,11 @@ public partial record Diagnostic : ICanHaveData public Container? RelatedInformation { get; init; } /// - /// A data entry field that is preserved on a code lens item between - /// a code lens and a code lens resolve request. + /// A data entry field that is preserved between a + /// `textDocument/publishDiagnostics` notification and + /// `textDocument/codeAction` request. + /// + /// @since 3.16.0 /// [Optional] public JToken? Data { get; init; } diff --git a/src/Protocol/Models/DocumentFilter.cs b/src/Protocol/Models/DocumentFilter.cs deleted file mode 100644 index e9f6628d4..000000000 --- a/src/Protocol/Models/DocumentFilter.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Minimatch; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -// ReSharper disable NonReadonlyMemberInGetHashCode - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class DocumentFilter : IEquatable - { - public static DocumentFilter ForPattern(string wildcard) => new DocumentFilter { Pattern = wildcard }; - - public static DocumentFilter ForLanguage(string language) => new DocumentFilter { Language = language }; - - public static DocumentFilter ForScheme(string scheme) => new DocumentFilter { Scheme = scheme }; - - /// - /// A language id, like `typescript`. - /// - [Optional] - public string? Language { get; set; } - - /// - /// does the document filter contains a language - /// - [JsonIgnore] - public bool HasLanguage => Language != null; - - /// - /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`. - /// - [Optional] - public string? Scheme { get; set; } - - /// - /// does the document filter contains a scheme - /// - [JsonIgnore] - public bool HasScheme => Scheme != null; - - /// - /// A glob pattern, like `*.{ts,js}`. - /// - [Optional] - public string? Pattern - { - get => _pattern; - set { - _pattern = value; - _minimatcher = new Minimatcher(value!, new Options { MatchBase = true }); - } - } - - /// - /// does the document filter contains a paattern - /// - [JsonIgnore] - public bool HasPattern => Pattern != null; - - private string? _pattern; - private Minimatcher? _minimatcher; - - public static explicit operator string(DocumentFilter documentFilter) - { - var items = new List(); - if (documentFilter.HasLanguage) - { - items.Add(documentFilter.Language!); - } - - if (documentFilter.HasScheme) - { - items.Add(documentFilter.Scheme!); - } - - if (documentFilter.HasPattern) - { - items.Add(documentFilter.Pattern!); - } - - return $"[{string.Join(", ", items)}]"; - } - - public bool IsMatch(TextDocumentAttributes attributes) - { - if (HasLanguage && HasPattern && HasScheme) - { - return Language == attributes.LanguageId && Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; - } - - if (HasLanguage && HasPattern) - { - return Language == attributes.LanguageId && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; - } - - if (HasLanguage && HasScheme) - { - return Language == attributes.LanguageId && Scheme == attributes.Scheme; - } - - if (HasPattern && HasScheme) - { - return Scheme == attributes.Scheme && _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; - } - - if (HasLanguage) - { - return Language == attributes.LanguageId; - } - - if (HasScheme) - { - return Scheme == attributes.Scheme; - } - - if (HasPattern) - { - return _minimatcher?.IsMatch(attributes.Uri.ToString()) == true; - } - - return false; - } - - public bool Equals(DocumentFilter? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return _pattern == other._pattern && Language == other.Language && Scheme == other.Scheme; - } - - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((DocumentFilter) obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = _pattern != null ? _pattern.GetHashCode() : 0; - hashCode = ( hashCode * 397 ) ^ ( Language != null ? Language.GetHashCode() : 0 ); - hashCode = ( hashCode * 397 ) ^ ( Scheme != null ? Scheme.GetHashCode() : 0 ); - return hashCode; - } - } - - public static bool operator ==(DocumentFilter left, DocumentFilter right) => Equals(left, right); - - public static bool operator !=(DocumentFilter left, DocumentFilter right) => !Equals(left, right); - - private string DebuggerDisplay => (string) this; - - /// - public override string ToString() => DebuggerDisplay; - } -} diff --git a/src/Protocol/Models/DocumentSelector.cs b/src/Protocol/Models/DocumentSelector.cs deleted file mode 100644 index 761c54739..000000000 --- a/src/Protocol/Models/DocumentSelector.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Linq; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - /// - /// A collection of document filters used to identify valid documents - /// - [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public class DocumentSelector : ContainerBase - { - public DocumentSelector() : this(Enumerable.Empty()) - { - } - - public DocumentSelector(IEnumerable items) : base(items) - { - } - - public DocumentSelector(params DocumentFilter[] items) : base(items) - { - } - - public static implicit operator DocumentSelector(DocumentFilter[] items) => new DocumentSelector(items); - - public static implicit operator DocumentSelector(Collection items) => new DocumentSelector(items); - - public static implicit operator DocumentSelector(List items) => new DocumentSelector(items); - - public static implicit operator string(DocumentSelector? documentSelector) => - documentSelector is not null ? string.Join(", ", documentSelector.Select(x => (string) x)) : string.Empty; - - public bool IsMatch(TextDocumentAttributes attributes) => this.Any(z => z.IsMatch(attributes)); - - public override string ToString() => this; - - public static DocumentSelector ForPattern(params string[] wildcards) => new DocumentSelector(wildcards.Select(DocumentFilter.ForPattern)); - - public static DocumentSelector ForLanguage(params string[] languages) => new DocumentSelector(languages.Select(DocumentFilter.ForLanguage)); - - public static DocumentSelector ForScheme(params string[] schemes) => new DocumentSelector(schemes.Select(DocumentFilter.ForScheme)); - - private string DebuggerDisplay => this; - } -} diff --git a/src/Protocol/Models/EditRange.cs b/src/Protocol/Models/EditRange.cs new file mode 100644 index 000000000..bff1dbc99 --- /dev/null +++ b/src/Protocol/Models/EditRange.cs @@ -0,0 +1,7 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +public partial record EditRange +{ + public Range Insert { get; init; } + public Range Replace { get; init; } +} \ No newline at end of file diff --git a/src/Protocol/Models/FailureHandlingKind.cs b/src/Protocol/Models/FailureHandlingKind.cs index b9157d2fb..dfcf36fde 100644 --- a/src/Protocol/Models/FailureHandlingKind.cs +++ b/src/Protocol/Models/FailureHandlingKind.cs @@ -8,8 +8,9 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models public enum FailureHandlingKind { /// - /// Applying the workspace change is simply aborted if one of the changes provided - /// fails. All operations executed before the failing operation stay executed. + /// Applying the workspace change is simply aborted if one of the changes + /// provided fails. All operations executed before the failing operation + /// stay executed. /// [EnumMember(Value = "abort")] Abort, @@ -20,9 +21,9 @@ public enum FailureHandlingKind [EnumMember(Value = "transactional")] Transactional, /// - /// If the workspace edit contains only textual file changes they are executed transactional. - /// If resource changes (create, rename or delete file) are part of the change the failure - /// handling strategy is abort. + /// If the workspace edit contains only textual file changes they are + /// executed transactional. If resource changes (create, rename or delete + /// file) are part of the change the failure handling strategy is abort. /// [EnumMember(Value = "textOnlyTransactional")] TextOnlyTransactional, diff --git a/src/Protocol/Models/FileLocation.cs b/src/Protocol/Models/FileLocation.cs new file mode 100644 index 000000000..e62aa39b5 --- /dev/null +++ b/src/Protocol/Models/FileLocation.cs @@ -0,0 +1,22 @@ +using System.Diagnostics; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] +[GenerateContainer] +public record FileLocation +{ + /// + /// The uri of the document + /// + public DocumentUri Uri { get; init; } = null!; + + private string DebuggerDisplay => $"{{{Uri}}}"; + + /// + public override string ToString() + { + return DebuggerDisplay; + } +} \ No newline at end of file diff --git a/src/Protocol/Models/FileSystemWatcher.cs b/src/Protocol/Models/FileSystemWatcher.cs index 96ca17de4..3c13bae03 100644 --- a/src/Protocol/Models/FileSystemWatcher.cs +++ b/src/Protocol/Models/FileSystemWatcher.cs @@ -6,17 +6,12 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models public record FileSystemWatcher { /// - /// The glob pattern to watch. + /// The glob pattern to watch. See + /// for more detail. /// - /// Glob patterns can have the following syntax: - /// - `*` to match one or more characters in a path segment - /// - `?` to match on one character in a path segment - /// - `**` to match any number of path segments, including none - /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) - /// - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) - /// - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + /// @since 3.17.0 support for relative patterns. /// - public string GlobPattern { get; init; } = null!; + public GlobPattern GlobPattern { get; init; } /// /// The kind of events of interest. If omitted it defaults diff --git a/src/Protocol/Models/GlobPattern.cs b/src/Protocol/Models/GlobPattern.cs new file mode 100644 index 000000000..ff5672885 --- /dev/null +++ b/src/Protocol/Models/GlobPattern.cs @@ -0,0 +1,61 @@ +using System.Diagnostics; +using Newtonsoft.Json; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + /// + /// The glob pattern. Either a string pattern or a relative pattern. + /// + /// @since 3.17.0 + /// + [JsonConverter(typeof(GlobPatternConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public record GlobPattern + { + public GlobPattern(string value) => Pattern = value; + + public GlobPattern(RelativePattern value) => RelativePattern = value; + + /// + /// The glob pattern to watch relative to the base path. Glob patterns can have + /// the following syntax: + /// - `*` to match one or more characters in a path segment + /// - `?` to match on one character in a path segment + /// - `**` to match any number of path segments, including none + /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript + /// and JavaScript files) + /// - `[]` to declare a range of characters to match in a path segment + /// (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + /// - `[!...]` to negate a range of characters to match in a path segment + /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, + /// but not `example.0`) + /// + /// @since 3.17.0 + /// + public string? Pattern { get; } + public bool HasPattern => RelativePattern is null; + + /// + /// A relative pattern is a helper to construct glob patterns that are matched + /// relatively to a base URI. The common value for a `baseUri` is a workspace + /// folder root, but it can be another absolute URI as well. + /// + /// @since 3.17.0 + /// + public RelativePattern? RelativePattern { get; } + public bool HasRelativePattern => RelativePattern is { }; + + public static implicit operator GlobPattern?(string? value) => + value is null ? null : new GlobPattern(value); + + public static implicit operator GlobPattern?(RelativePattern value) => + value is null ? null : new GlobPattern(value); + + private string DebuggerDisplay => + $"{( HasPattern ? Pattern : HasRelativePattern ? RelativePattern : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + } +} diff --git a/src/Protocol/Models/INotebookDocumentIdentifierParams.cs b/src/Protocol/Models/INotebookDocumentIdentifierParams.cs new file mode 100644 index 000000000..3d54eb520 --- /dev/null +++ b/src/Protocol/Models/INotebookDocumentIdentifierParams.cs @@ -0,0 +1,9 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +public interface INotebookDocumentIdentifierParams +{ + /// + /// The notebook document that got closed. + /// + public NotebookDocumentIdentifier NotebookDocument {get; set;} +} diff --git a/src/Protocol/Models/IPartialItem.cs b/src/Protocol/Models/IPartialItem.cs index ff494139f..14f8cf847 100644 --- a/src/Protocol/Models/IPartialItem.cs +++ b/src/Protocol/Models/IPartialItem.cs @@ -3,8 +3,14 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { public interface IPartialItem : IPartialResultParams { } + public interface IPartialItemWithInitialValue : IPartialResultParams { } public interface IPartialItemRequest : IRequest, IPartialItem { } + + public interface IPartialItemWithInitialValueRequest : IRequest, IPartialItemWithInitialValue + where TResponse : T + { + } } diff --git a/src/Protocol/Models/IPartialItems.cs b/src/Protocol/Models/IPartialItems.cs index 2a1f036f0..cf1ff18d9 100644 --- a/src/Protocol/Models/IPartialItems.cs +++ b/src/Protocol/Models/IPartialItems.cs @@ -4,9 +4,15 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { public interface IPartialItems : IPartialResultParams { } + public interface IPartialItemsWithInitialValue : IPartialResultParams { } public interface IPartialItemsRequest : IRequest, IPartialItems where TResponse : IEnumerable? { } + + public interface IPartialItemsWithInitialValueRequest : IRequest, IPartialItemsWithInitialValue + where TResponse : IEnumerable? + { + } } diff --git a/src/Protocol/Models/IPartialResultParams.cs b/src/Protocol/Models/IPartialResultParams.cs index 3dedcf965..0e741f6a4 100644 --- a/src/Protocol/Models/IPartialResultParams.cs +++ b/src/Protocol/Models/IPartialResultParams.cs @@ -5,8 +5,8 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models public interface IPartialResultParams { /// - /// An optional token that a server can use to report partial results (e.g. streaming) to - /// the client. + /// An optional token that a server can use to report partial results (e.g. + /// streaming) to the client. /// [Optional] ProgressToken? PartialResultToken { get; init; } diff --git a/src/Protocol/Models/ITextDocumentRegistrationOptions.cs b/src/Protocol/Models/ITextDocumentRegistrationOptions.cs deleted file mode 100644 index 574fe8c34..000000000 --- a/src/Protocol/Models/ITextDocumentRegistrationOptions.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public interface ITextDocumentRegistrationOptions : IRegistrationOptions - { - DocumentSelector? DocumentSelector { get; set; } - } -} diff --git a/src/Protocol/Models/ITextDocumentSyncOptions.cs b/src/Protocol/Models/ITextDocumentSyncOptions.cs deleted file mode 100644 index 66e8cbfbe..000000000 --- a/src/Protocol/Models/ITextDocumentSyncOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Models -{ - public interface ITextDocumentSyncOptions - { - [Optional] bool OpenClose { get; set; } - [Optional] TextDocumentSyncKind Change { get; set; } - [Optional] bool WillSave { get; set; } - [Optional] bool WillSaveWaitUntil { get; set; } - [Optional] BooleanOr Save { get; set; } - } -} diff --git a/src/Protocol/Models/Location.cs b/src/Protocol/Models/Location.cs index 29814a3dd..2d1179028 100644 --- a/src/Protocol/Models/Location.cs +++ b/src/Protocol/Models/Location.cs @@ -13,7 +13,7 @@ public record Location public DocumentUri Uri { get; init; } = null!; /// - /// The range in side the document given by the uri + /// The range inside the document given by the uri /// public Range Range { get; init; } = null!; diff --git a/src/Protocol/Models/LocationLink.cs b/src/Protocol/Models/LocationLink.cs index 506b4a7da..7eb558588 100644 --- a/src/Protocol/Models/LocationLink.cs +++ b/src/Protocol/Models/LocationLink.cs @@ -7,8 +7,8 @@ public record LocationLink /// /// Span of the origin of this link. /// - /// Used as the underlined span for mouse interaction. Defaults to the word range at - /// the mouse position. + /// Used as the underlined span for mouse interaction. Defaults to the word + /// range at the mouse position. /// [Optional] public Range? OriginSelectionRange { get; init; } @@ -19,15 +19,17 @@ public record LocationLink public DocumentUri TargetUri { get; init; } = null!; /// - /// The full target range of this link. If the target for example is a symbol then target range is the - /// range enclosing this symbol not including leading/trailing whitespace but everything else - /// like comments. This information is typically used to highlight the range in the editor. + /// The full target range of this link. If the target for example is a symbol + /// then target range is the range enclosing this symbol not including + /// leading/trailing whitespace but everything else like comments. This + /// information is typically used to highlight the range in the editor. /// public Range TargetRange { get; init; } = null!; /// - /// The range that should be selected and revealed when this link is being followed, e.g the name of a function. - /// Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + /// The range that should be selected and revealed when this link is being + /// followed, e.g the name of a function. Must be contained by the the + /// `targetRange`. See also `DocumentSymbol#range` /// public Range TargetSelectionRange { get; init; } = null!; } diff --git a/src/Protocol/Models/LocationOrFileLocation.cs b/src/Protocol/Models/LocationOrFileLocation.cs new file mode 100644 index 000000000..790bd7787 --- /dev/null +++ b/src/Protocol/Models/LocationOrFileLocation.cs @@ -0,0 +1,30 @@ +using Newtonsoft.Json; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[JsonConverter(typeof(LocationOrFileLocationConverter))] +public record LocationOrFileLocation +{ + public LocationOrFileLocation(Location location) + { + Location = location; + FileLocation = null; + } + + public LocationOrFileLocation(FileLocation locationLink) + { + Location = null; + FileLocation = locationLink; + } + + public bool IsLocation => Location is not null; + public Location? Location { get; } + + public bool IsFileLocation => FileLocation != null; + public FileLocation? FileLocation { get; } + + public static implicit operator LocationOrFileLocation(Location location) => new LocationOrFileLocation(location); + + public static implicit operator LocationOrFileLocation(FileLocation locationLink) => new LocationOrFileLocation(locationLink); +} \ No newline at end of file diff --git a/src/Protocol/Models/NotebookDocumentIdentifier.cs b/src/Protocol/Models/NotebookDocumentIdentifier.cs new file mode 100644 index 000000000..045455abb --- /dev/null +++ b/src/Protocol/Models/NotebookDocumentIdentifier.cs @@ -0,0 +1,40 @@ +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] +public record NotebookDocumentIdentifier +{ + public NotebookDocumentIdentifier() + { + } + + public NotebookDocumentIdentifier(DocumentUri uri) + { + Uri = uri; + } + + /// + /// The text document's URI. + /// + public DocumentUri Uri { get; init; } = null!; + + public static implicit operator NotebookDocumentIdentifier(DocumentUri uri) + { + return new NotebookDocumentIdentifier { Uri = uri }; + } + + public static implicit operator NotebookDocumentIdentifier(string uri) + { + return new NotebookDocumentIdentifier { Uri = uri }; + } + + // ReSharper disable once ConstantConditionalAccessQualifier + private string DebuggerDisplay => Uri?.ToString() ?? string.Empty; + + /// + public override string ToString() + { + return DebuggerDisplay; + } +} diff --git a/src/Protocol/Models/OptionalVersionedNotebookDocumentIdentifier.cs b/src/Protocol/Models/OptionalVersionedNotebookDocumentIdentifier.cs new file mode 100644 index 000000000..116ca48f0 --- /dev/null +++ b/src/Protocol/Models/OptionalVersionedNotebookDocumentIdentifier.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] +public record OptionalVersionedNotebookDocumentIdentifier : NotebookDocumentIdentifier +{ + /// + /// The version number of this document. + /// + public int? Version { get; init; } + + private string DebuggerDisplay => $"{Uri}@({Version})"; + + /// + public override string ToString() => DebuggerDisplay; +} diff --git a/src/Protocol/Models/OptionalVersionedTextDocumentIdentifier.cs b/src/Protocol/Models/OptionalVersionedTextDocumentIdentifier.cs index 9f41c54f3..8f3e1e49c 100644 --- a/src/Protocol/Models/OptionalVersionedTextDocumentIdentifier.cs +++ b/src/Protocol/Models/OptionalVersionedTextDocumentIdentifier.cs @@ -6,7 +6,15 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models public record OptionalVersionedTextDocumentIdentifier : TextDocumentIdentifier { /// - /// The version number of this document. + /// The version number of this document. If an optional versioned text document + /// identifier is sent from the server to the client and the file is not + /// open in the editor(the server has not received an open notification + /// before) the server can send `null` to indicate that the version is + /// known and the content on disk is the master(as specified with document + /// content ownership). + /// + /// The version number of a document will increase after each change, + /// including undo/redo.The number doesn't need to be consecutive. /// public int? Version { get; init; } diff --git a/src/Protocol/Models/Position.cs b/src/Protocol/Models/Position.cs index 0a15facc0..696039019 100644 --- a/src/Protocol/Models/Position.cs +++ b/src/Protocol/Models/Position.cs @@ -24,7 +24,11 @@ public Position(int line, int character) public int Line { get; set; } /// - /// Character offset on a line in a document (zero-based). + /// Character offset on a line in a document (zero-based). The meaning of this + /// offset is determined by the negotiated `PositionEncodingKind`. + /// + /// If the character value is greater than the line length it defaults back + /// to the line length. /// /// /// in the LSP spec diff --git a/src/Protocol/Models/PositionEncodingKind.cs b/src/Protocol/Models/PositionEncodingKind.cs new file mode 100644 index 000000000..2718ed784 --- /dev/null +++ b/src/Protocol/Models/PositionEncodingKind.cs @@ -0,0 +1,35 @@ +using OmniSharp.Extensions.JsonRpc.Generation; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +/// +/// A type indicating how positions are encoded, +/// specifically what column offsets mean. +/// +/// @since 3.17.0 +/// +[StringEnum] +public readonly partial struct PositionEncodingKind +{ + /// + /// Character offsets count UTF-8 code units (e.g bytes). + /// + public static PositionEncodingKind UTF8 = new("utf-8"); + + /// + /// Character offsets count UTF-16 code units. + /// + /// This is the default and must always be supported + /// by servers + /// + public static PositionEncodingKind UTF16 = new("utf-16"); + + /// + /// Character offsets count UTF-32 code units. + /// + /// Implementation note: these are the same as Unicode code points, + /// so this `PositionEncodingKind` may also be used for an + /// encoding-agnostic representation of character offsets. + /// + public static PositionEncodingKind UTF32 = new("utf-32"); +} diff --git a/src/Protocol/Models/RangeOrEditRange.cs b/src/Protocol/Models/RangeOrEditRange.cs new file mode 100644 index 000000000..3f8dbcb5c --- /dev/null +++ b/src/Protocol/Models/RangeOrEditRange.cs @@ -0,0 +1,57 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[JsonConverter(typeof(Converter))] +public partial record RangeOrEditRange +{ + public RangeOrEditRange(Range range) + { + Range = range; + EditRange = null; + } + + public RangeOrEditRange(EditRange editRange) + { + Range = null; + EditRange = editRange; + } + + public bool IsRange => Range is not null; + public Range? Range { get; set; } + + public bool IsEditRange => EditRange != null; + public EditRange? EditRange { get; } + + public static implicit operator RangeOrEditRange(Range range) => new RangeOrEditRange(range); + + public static implicit operator RangeOrEditRange(EditRange editRange) => new RangeOrEditRange(editRange); + + + public class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, RangeOrEditRange value, JsonSerializer serializer) + { + if (value.IsRange) + serializer.Serialize(writer, value.Range); + if (value.IsEditRange) + serializer.Serialize(writer, value.EditRange); + } + + public override RangeOrEditRange ReadJson( + JsonReader reader, Type objectType, RangeOrEditRange existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + var obj = JObject.Load(reader); + if (obj.ContainsKey("insert")) + { + return new RangeOrEditRange(obj.ToObject()); + } + + return new RangeOrEditRange(obj.ToObject()); + } + + public override bool CanRead => true; + } +} diff --git a/src/Protocol/Models/RelativePattern.cs b/src/Protocol/Models/RelativePattern.cs new file mode 100644 index 000000000..66b8e6686 --- /dev/null +++ b/src/Protocol/Models/RelativePattern.cs @@ -0,0 +1,36 @@ +using System.Diagnostics; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + /// + /// A relative pattern is a helper to construct glob patterns that are matched + /// relatively to a base URI. The common value for a `baseUri` is a workspace + /// folder root, but it can be another absolute URI as well. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [GenerateContainer] + public record RelativePattern + { + /// + /// A workspace folder or a base URI to which this pattern will be matched + /// against relatively. + /// + public WorkspaceFolderOrUri BaseUri { get; init; } = null!; + + /// + /// The actual glob pattern; + /// + public string Pattern { get; init; } = null!; + + private string DebuggerDisplay => $"{{{BaseUri} {Pattern}}}"; + + /// + public override string ToString() + { + return DebuggerDisplay; + } + } +} diff --git a/src/Protocol/Models/RenameFile.cs b/src/Protocol/Models/RenameFile.cs index 4964dd22a..187149468 100644 --- a/src/Protocol/Models/RenameFile.cs +++ b/src/Protocol/Models/RenameFile.cs @@ -23,13 +23,13 @@ public record RenameFile : IFile public DocumentUri NewUri { get; init; } = null!; /// - /// Rename Options. + /// Rename options. /// [Optional] public RenameFileOptions? Options { get; init; } /// - /// An optional annotation describing the operation. + /// An optional annotation identifier describing the operation. /// /// @since 3.16.0 /// diff --git a/src/Protocol/Models/StringOrMarkupContent.cs b/src/Protocol/Models/StringOrMarkupContent.cs index 9b9ce5de7..0e0421faa 100644 --- a/src/Protocol/Models/StringOrMarkupContent.cs +++ b/src/Protocol/Models/StringOrMarkupContent.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; @@ -17,8 +18,10 @@ public record StringOrMarkupContent public MarkupContent? MarkupContent { get; } public bool HasMarkupContent => String == null; + [return: NotNullIfNotNull("value")] public static implicit operator StringOrMarkupContent?(string? value) => value is null ? null : new StringOrMarkupContent(value); + [return: NotNullIfNotNull("markupContent")] public static implicit operator StringOrMarkupContent?(MarkupContent? markupContent) => markupContent is null ? null : new StringOrMarkupContent(markupContent); private string DebuggerDisplay => $"{( HasString ? String : HasMarkupContent ? MarkupContent!.ToString() : string.Empty )}"; diff --git a/src/Protocol/Models/TextDocumentItem.cs b/src/Protocol/Models/TextDocumentItem.cs index 0a51cedf3..3878e1011 100644 --- a/src/Protocol/Models/TextDocumentItem.cs +++ b/src/Protocol/Models/TextDocumentItem.cs @@ -11,7 +11,7 @@ public record TextDocumentItem : TextDocumentIdentifier public string LanguageId { get; init; } = null!; /// - /// The version number of this document (it will strictly increase after each + /// The version number of this document (it will increase after each /// change, including undo/redo). /// public int? Version { get; init; } diff --git a/src/Protocol/Models/TextEdit.cs b/src/Protocol/Models/TextEdit.cs index 4b6ac9fff..e736b5cd0 100644 --- a/src/Protocol/Models/TextEdit.cs +++ b/src/Protocol/Models/TextEdit.cs @@ -180,7 +180,8 @@ public record ChangeAnnotation public record ChangeAnnotationIdentifier { /// - /// An optional annotation identifer describing the operation. + /// An identifier referring to a change annotation managed by a workspace + /// edit. /// /// @since 3.16.0 /// @@ -207,7 +208,7 @@ public static implicit operator ChangeAnnotationIdentifier(string identifier) public record AnnotatedTextEdit : TextEdit { /// - /// The actual annotation + /// The actual annotation identifier. /// public ChangeAnnotationIdentifier AnnotationId { get; init; } = null!; diff --git a/src/Protocol/Models/VersionedNotebookDocumentIdentifier.cs b/src/Protocol/Models/VersionedNotebookDocumentIdentifier.cs new file mode 100644 index 000000000..b5fa46ffc --- /dev/null +++ b/src/Protocol/Models/VersionedNotebookDocumentIdentifier.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models; + +/// +/// A versioned notebook document identifier. +/// +/// @since 3.17.0 +/// +[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] +public partial record VersionedNotebookDocumentIdentifier { + /// + /// The version number of this notebook document. + /// + public int Version {get; set;} + /// + /// The notebook document's uri. + /// + public DocumentUri Uri {get; set;} + + private string DebuggerDisplay => $"{Uri}@({Version})"; + + /// + public override string ToString() => DebuggerDisplay; +} diff --git a/src/Protocol/Models/VersionedTextDocumentIdentifier.cs b/src/Protocol/Models/VersionedTextDocumentIdentifier.cs index c3d0ef719..599070d5a 100644 --- a/src/Protocol/Models/VersionedTextDocumentIdentifier.cs +++ b/src/Protocol/Models/VersionedTextDocumentIdentifier.cs @@ -3,10 +3,13 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models { [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] - public record VersionedTextDocumentIdentifier : TextDocumentIdentifier + public partial record VersionedTextDocumentIdentifier : TextDocumentIdentifier { /// /// The version number of this document. + /// + /// The version number of a document will increase after each change, + /// including undo/redo.The number doesn't need to be consecutive. /// public int Version { get; init; } diff --git a/src/Protocol/Models/WorkspaceEdit.cs b/src/Protocol/Models/WorkspaceEdit.cs index 182f524ef..a65cc41ec 100644 --- a/src/Protocol/Models/WorkspaceEdit.cs +++ b/src/Protocol/Models/WorkspaceEdit.cs @@ -12,16 +12,19 @@ public record WorkspaceEdit public IDictionary>? Changes { get; init; } /// - /// An array of `TextDocumentEdit`s to express changes to n different text documents - /// where each text document edit addresses a specific version of a text document. - /// where each text document edit addresses a specific version of a text document. Or it can contain - /// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations. + /// Depending on the client capability + /// `workspace.workspaceEdit.resourceOperations` document changes are either + /// an array of `TextDocumentEdit`s to express changes to n different text + /// documents where each text document edit addresses a specific version of + /// a text document. Or it can contain above `TextDocumentEdit`s mixed with + /// create, rename and delete file / folder operations. /// /// Whether a client supports versioned document edits is expressed via /// `WorkspaceCapability.workspaceEdit.documentChanges`. /// - /// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then - /// only plain `TextEdit`s using the `changes` property are supported. + /// If a client neither supports `documentChanges` nor + /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s + /// using the `changes` property are supported. /// [Optional] public Container? DocumentChanges { get; init; } diff --git a/src/Protocol/Models/WorkspaceFolderOrUri.cs b/src/Protocol/Models/WorkspaceFolderOrUri.cs new file mode 100644 index 000000000..4895c8458 --- /dev/null +++ b/src/Protocol/Models/WorkspaceFolderOrUri.cs @@ -0,0 +1,32 @@ +using System.Diagnostics; +using Newtonsoft.Json; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + [JsonConverter(typeof(WorkspaceFolderOrUriConverter))] + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + public record WorkspaceFolderOrUri + { + public WorkspaceFolderOrUri(WorkspaceFolder value) => WorkspaceFolder = value; + + public WorkspaceFolderOrUri(DocumentUri value) => Uri = value; + + public WorkspaceFolder? WorkspaceFolder { get; } + public bool HasWorkspaceFolder => WorkspaceFolder is { }; + public DocumentUri? Uri { get; } + public bool HasUri => Uri is { }; + + public static implicit operator WorkspaceFolderOrUri?(WorkspaceFolder value) => + value is null ? null : new WorkspaceFolderOrUri(value); + + public static implicit operator WorkspaceFolderOrUri?(DocumentUri value) => + value is null ? null : new WorkspaceFolderOrUri(value); + + private string DebuggerDisplay => + $"{( HasWorkspaceFolder ? WorkspaceFolder : HasUri ? Uri : string.Empty )}"; + + /// + public override string ToString() => DebuggerDisplay; + } +} diff --git a/src/Protocol/NotebookDocumentNames.cs b/src/Protocol/NotebookDocumentNames.cs new file mode 100644 index 000000000..e90844615 --- /dev/null +++ b/src/Protocol/NotebookDocumentNames.cs @@ -0,0 +1,9 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol; + +public static class NotebookDocumentNames +{ + public const string DidChange = "notebookDocument/didChange"; + public const string DidClose = "notebookDocument/didClose"; + public const string DidOpen = "notebookDocument/didOpen"; + public const string DidSave = "notebookDocument/didSave"; +} diff --git a/src/Protocol/Progress/IProgressManager.cs b/src/Protocol/Progress/IProgressManager.cs index f46219cc3..14d3f5059 100644 --- a/src/Protocol/Progress/IProgressManager.cs +++ b/src/Protocol/Progress/IProgressManager.cs @@ -15,47 +15,61 @@ public interface IProgressManager : IProgressHandler IRequestProgressObservable MonitorUntil( IPartialItemRequest request, Func factory, - Func reverseFactory, CancellationToken cancellationToken - ); + ) where TResult : TItem; IRequestProgressObservable MonitorUntil( IPartialItemRequest request, - Func factory, - Func reverseFactory, + Func factory, CancellationToken cancellationToken - ); + ) where TResult : TItem; - [Obsolete("Method may not work correctly when subscribing to the result, use overload with the reverse factory parameter")] IRequestProgressObservable MonitorUntil( IPartialItemRequest request, Func factory, + Func reverseFactory, CancellationToken cancellationToken ); - [Obsolete("Method may not work correctly when subscribing to the result, use overload with the reverse factory parameter")] IRequestProgressObservable MonitorUntil( IPartialItemRequest request, - Func factory, + Func factory, + Func reverseFactory, CancellationToken cancellationToken ); + IRequestProgressObservable MonitorUntil( + IPartialItemWithInitialValueRequest request, + Func factory, + CancellationToken cancellationToken + ) where TResult : TItem; + IRequestProgressObservable, TResponse> MonitorUntil( IPartialItemsRequest request, Func, TResponse> factory, CancellationToken cancellationToken - ) where TResponse : IEnumerable?; + ) where TResponse : IEnumerable; IRequestProgressObservable MonitorUntil( IPartialItemsRequest, TItem> request, CancellationToken cancellationToken ); + + IRequestProgressObservable, TResponse> MonitorUntil( + IPartialItemsWithInitialValueRequest request, + Func, TResponse> factory, + CancellationToken cancellationToken + ) where TResponse : IEnumerable; IProgressObserver For(ProgressToken token, CancellationToken cancellationToken); IProgressObserver For(IPartialItemRequest request, CancellationToken cancellationToken); + IProgressObserverWithInitialValue For(IPartialItemWithInitialValueRequest request, CancellationToken cancellationToken) + where TInitial : TItem; IProgressObserver> For(IPartialItemsRequest request, CancellationToken cancellationToken) - where TResponse : IEnumerable?; + where TResponse : IEnumerable; + IProgressObserverWithInitialValue> For(IPartialItemsWithInitialValueRequest request, CancellationToken cancellationToken) + where TInitial : IEnumerable; IScheduler Scheduler { get; } } } diff --git a/src/Protocol/Progress/IProgressObserver.cs b/src/Protocol/Progress/IProgressObserver.cs index 24616e9d4..cc492961b 100644 --- a/src/Protocol/Progress/IProgressObserver.cs +++ b/src/Protocol/Progress/IProgressObserver.cs @@ -5,6 +5,11 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { + public interface IProgressObserverWithInitialValue : IProgressObserver, IObserver + { + void OnNext(TInitial initial); + TaskAwaiter GetAwaiter(); + } public interface IProgressObserver : IProgressObserver, IObserver { TaskAwaiter GetAwaiter(); diff --git a/src/Protocol/Progress/PartialItemRequestProgressObservable.cs b/src/Protocol/Progress/PartialItemRequestProgressObservable.cs index 5e921134d..d67c79f2d 100644 --- a/src/Protocol/Progress/PartialItemRequestProgressObservable.cs +++ b/src/Protocol/Progress/PartialItemRequestProgressObservable.cs @@ -25,7 +25,7 @@ public PartialItemRequestProgressObservable( ISerializer serializer, ProgressToken token, IObservable requestResult, - Func factory, + Func factory, Func reverseFactory, CancellationToken cancellationToken, Action onCompleteAction @@ -37,20 +37,17 @@ Action onCompleteAction _task = Observable.Create( observer => new CompositeDisposable { - _dataSubject - .ForkJoin( - requestResult - .Do( - _ => - { - if (_receivedPartialData) return; - _dataSubject.OnNext(reverseFactory(_)); - }, - _dataSubject.OnError, - _dataSubject.OnCompleted - ), - factory + requestResult + .Do( + result => + { + if (_receivedPartialData) return; + _dataSubject.OnNext(reverseFactory(result)); + }, + _dataSubject.OnError, + _dataSubject.OnCompleted ) + .ForkJoin(_dataSubject, factory) .Subscribe(observer), Disposable.Create(onCompleteAction) } @@ -89,7 +86,7 @@ public void OnNext(JToken value) { if (_dataSubject.IsDisposed) return; _receivedPartialData = true; - _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)); + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); } public void Dispose() diff --git a/src/Protocol/Progress/PartialItemWithInitialValueRequestProgressObservable.cs b/src/Protocol/Progress/PartialItemWithInitialValueRequestProgressObservable.cs new file mode 100644 index 000000000..f66770327 --- /dev/null +++ b/src/Protocol/Progress/PartialItemWithInitialValueRequestProgressObservable.cs @@ -0,0 +1,119 @@ +using System.Reactive.Concurrency; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Runtime.CompilerServices; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +internal class PartialItemWithInitialValueRequestProgressObservable : IRequestProgressObservable, IObserver + where TResult : TItem +{ + private readonly ISerializer _serializer; + private readonly ReplaySubject _dataSubject; + private readonly CompositeDisposable _disposable; + private readonly Task _task; + private bool _receivedInitialValue; + private bool _receivedPartialData; + + public PartialItemWithInitialValueRequestProgressObservable( + ISerializer serializer, + ProgressToken token, + IObservable requestResult, + Func factory, + CancellationToken cancellationToken, + Action onCompleteAction + ) + { + _serializer = serializer; + _dataSubject = new ReplaySubject(1, Scheduler.Immediate); + _disposable = new CompositeDisposable { _dataSubject }; + _task = Observable.Create( + observer => new CompositeDisposable + { + requestResult + .Do( + result => + { + if (_receivedPartialData) return; + _dataSubject.OnNext(result); + }, + _dataSubject.OnError, + _dataSubject.OnCompleted + ) + .ForkJoin(_dataSubject, factory) + .Subscribe(observer), + Disposable.Create(onCompleteAction) + } + ) + .ToTask(cancellationToken); + + ProgressToken = token; + } + + public ProgressToken ProgressToken { get; } + public Type ParamsType { get; } = typeof(TItem); + + void IObserver.OnCompleted() + { + OnCompleted(); + } + + void IObserver.OnError(Exception error) + { + OnError(error); + } + + private void OnCompleted() + { + if (_dataSubject.IsDisposed) return; + _dataSubject.OnCompleted(); + } + + private void OnError(Exception error) + { + if (_dataSubject.IsDisposed) return; + _dataSubject.OnError(error); + } + + public void OnNext(JToken value) + { + if (_dataSubject.IsDisposed) return; + _receivedPartialData = true; + if (!_receivedInitialValue) + { + _receivedInitialValue = true; + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); + } + else + { + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); + } + } + + public void Dispose() + { + if (_disposable.IsDisposed) return; + _disposable.Dispose(); + } + + public IDisposable Subscribe(IObserver observer) + { + return _dataSubject.Subscribe(observer); + } + +#pragma warning disable VSTHRD003 + public Task AsTask() + { + return _task; + } +#pragma warning restore VSTHRD003 + public TaskAwaiter GetAwaiter() + { + return _task.GetAwaiter(); + } +} diff --git a/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs b/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs index 3ca17fe7d..113a70020 100644 --- a/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs +++ b/src/Protocol/Progress/PartialItemsRequestProgressObservable.cs @@ -16,12 +16,12 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { - internal class PartialItemsRequestProgressObservable : IRequestProgressObservable, TResult>, IObserver, + internal class PartialItemsRequestProgressObservable : IRequestProgressObservable?, TResult>, IObserver, IDisposable where TResult : IEnumerable? { private readonly ISerializer _serializer; - private readonly ReplaySubject> _dataSubject; + private readonly ReplaySubject?> _dataSubject; private readonly CompositeDisposable _disposable; private readonly Task _task; private bool _receivedPartialData; @@ -36,7 +36,7 @@ Action onCompleteAction ) { _serializer = serializer; - _dataSubject = new ReplaySubject>(int.MaxValue, Scheduler.Immediate); + _dataSubject = new ReplaySubject?>(int.MaxValue, Scheduler.Immediate); _disposable = new CompositeDisposable { _dataSubject }; _task = Observable.Create( observer => new CompositeDisposable @@ -46,6 +46,7 @@ Action onCompleteAction new List(), (acc, data) => { + if (data is null) return acc; acc.AddRange(data); return acc; } @@ -54,11 +55,15 @@ Action onCompleteAction .ForkJoin( requestResult .Do( - result => _dataSubject.OnNext(result ?? Enumerable.Empty()), + result => + { + if (_receivedPartialData) return; + _dataSubject.OnNext(result); + }, _dataSubject.OnError, _dataSubject.OnCompleted ), - (items, result) => items?.Count() > result?.Count() ? items : result + (items, result) => _receivedPartialData ? items : result ) .Subscribe(observer), Disposable.Create(onCompleteAction) @@ -98,7 +103,7 @@ public void OnNext(JToken value) { if (_dataSubject.IsDisposed) return; _receivedPartialData = true; - _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)); + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); } public void Dispose() @@ -108,7 +113,7 @@ public void Dispose() } // public IDisposable Subscribe(IObserver> observer) => _disposable.IsDisposed ? Disposable.Empty : _dataSubject.Subscribe(observer); - public IDisposable Subscribe(IObserver> observer) + public IDisposable Subscribe(IObserver?> observer) { return _dataSubject.Subscribe(observer); } @@ -125,14 +130,14 @@ public TaskAwaiter GetAwaiter() } } - internal class PartialItemsRequestProgressObservable : PartialItemsRequestProgressObservable?>, + internal class PartialItemsRequestProgressObservable : PartialItemsRequestProgressObservable>, IRequestProgressObservable { public PartialItemsRequestProgressObservable( ISerializer serializer, ProgressToken token, - IObservable?> requestResult, - Func, Container?> factory, + IObservable> requestResult, + Func, Container> factory, CancellationToken cancellationToken, Action onCompleteAction, ILogger logger diff --git a/src/Protocol/Progress/PartialItemsWithInitialValueRequestProgressObservable.cs b/src/Protocol/Progress/PartialItemsWithInitialValueRequestProgressObservable.cs new file mode 100644 index 000000000..28cebcb99 --- /dev/null +++ b/src/Protocol/Progress/PartialItemsWithInitialValueRequestProgressObservable.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Reactive.Threading.Tasks; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress +{ + internal class PartialItemsWithInitialValueRequestProgressObservable : IRequestProgressObservable, TResult>, + IObserver, + IDisposable + where TResult : IEnumerable + { + private readonly ISerializer _serializer; + private readonly ReplaySubject?> _dataSubject; + private readonly CompositeDisposable _disposable; + private readonly Task _task; + private bool _receivedInitialValue; + private bool _receivedPartialData; + + public PartialItemsWithInitialValueRequestProgressObservable( + ISerializer serializer, + ProgressToken token, + IObservable requestResult, + Func?, TResult> factory, + CancellationToken cancellationToken, + Action onCompleteAction + ) + { + _serializer = serializer; + _dataSubject = new ReplaySubject?>(int.MaxValue, Scheduler.Immediate); + _disposable = new CompositeDisposable { _dataSubject }; + _task = Observable.Create( + observer => new CompositeDisposable + { + _dataSubject + .Aggregate(default(TResult), (acc, items) => acc is null && items is TResult r ? r : factory(acc, items)) + .ForkJoin( + requestResult + .Do( + result => + { + if (_receivedPartialData) return; + _dataSubject.OnNext(result); + }, + _dataSubject.OnError, + _dataSubject.OnCompleted + ), + (items, result) => _receivedPartialData ? items : result + ) + .Subscribe(observer!), + Disposable.Create(onCompleteAction) + } + ) + .ToTask(cancellationToken); + + ProgressToken = token; + } + + public ProgressToken ProgressToken { get; } + public Type ParamsType { get; } = typeof(TItem); + + void IObserver.OnCompleted() + { + OnCompleted(); + } + + void IObserver.OnError(Exception error) + { + OnError(error); + } + + private void OnCompleted() + { + if (_dataSubject.IsDisposed) return; + _dataSubject.OnCompleted(); + } + + private void OnError(Exception error) + { + if (_dataSubject.IsDisposed) return; + _dataSubject.OnError(error); + } + + public void OnNext(JToken value) + { + if (_dataSubject.IsDisposed) return; + _receivedPartialData = true; + if (!_receivedInitialValue) + { + _receivedInitialValue = true; + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); + } + else + { + _dataSubject.OnNext(value.ToObject(_serializer.JsonSerializer)!); + } + } + + public void Dispose() + { + if (_disposable.IsDisposed) return; + _disposable.Dispose(); + } + +// public IDisposable Subscribe(IObserver> observer) => _disposable.IsDisposed ? Disposable.Empty : _dataSubject.Subscribe(observer); + public IDisposable Subscribe(IObserver> observer) + { + return _dataSubject.Subscribe(observer!); + } + +#pragma warning disable VSTHRD003 + public Task AsTask() + { + return _task; + } +#pragma warning restore VSTHRD003 + public TaskAwaiter GetAwaiter() + { + return _task.GetAwaiter(); + } + } +} diff --git a/src/Protocol/Progress/ProgressManager.cs b/src/Protocol/Progress/ProgressManager.cs index c57fb182a..290e06476 100644 --- a/src/Protocol/Progress/ProgressManager.cs +++ b/src/Protocol/Progress/ProgressManager.cs @@ -48,7 +48,7 @@ Task IRequestHandler.Handle(ProgressParams request, return Unit.Task; } - public IProgressObservable Monitor(ProgressToken token) => Monitor(token, x => x.ToObject(_serializer.JsonSerializer)); + public IProgressObservable Monitor(ProgressToken token) => Monitor(token, x => x.ToObject(_serializer.JsonSerializer)!); public IProgressObservable Monitor(ProgressToken token, Func factory) { @@ -65,12 +65,12 @@ public IProgressObservable Monitor(ProgressToken token, Func fa public IRequestProgressObservable MonitorUntil( IPartialItemRequest request, Func factory, + Func reverseFactory, CancellationToken cancellationToken ) { request.SetPartialResultToken(); - if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) - && o is IRequestProgressObservable observable) + if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) && o is IRequestProgressObservable observable) { return observable; } @@ -79,8 +79,8 @@ CancellationToken cancellationToken _serializer, request.PartialResultToken!, MakeRequest(request), - (x, _) => factory(x), - _ => default!, + (_, x) => factory(x), + reverseFactory, cancellationToken, () => _activeObservables.TryRemove(request.PartialResultToken!, out _) ); @@ -90,7 +90,8 @@ CancellationToken cancellationToken public IRequestProgressObservable MonitorUntil( IPartialItemRequest request, - Func factory, + Func factory, + Func reverseFactory, CancellationToken cancellationToken ) { @@ -102,23 +103,22 @@ CancellationToken cancellationToken observable = new PartialItemRequestProgressObservable( _serializer, - request.PartialResultToken, + request.PartialResultToken!, MakeRequest(request), factory, - _ => default!, + reverseFactory, cancellationToken, - () => _activeObservables.TryRemove(request.PartialResultToken, out _) + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) ); - _activeObservables.TryAdd(request.PartialResultToken, observable); + _activeObservables.TryAdd(request.PartialResultToken!, observable); return observable; } public IRequestProgressObservable MonitorUntil( IPartialItemRequest request, Func factory, - Func reverseFactory, CancellationToken cancellationToken - ) + ) where TResult : TItem { request.SetPartialResultToken(); if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) @@ -131,8 +131,8 @@ CancellationToken cancellationToken _serializer, request.PartialResultToken!, MakeRequest(request), - (x, _) => factory(x), - reverseFactory, + (_, x) => factory(x), + x => x, cancellationToken, () => _activeObservables.TryRemove(request.PartialResultToken!, out _) ); @@ -142,10 +142,9 @@ CancellationToken cancellationToken public IRequestProgressObservable MonitorUntil( IPartialItemRequest request, - Func factory, - Func reverseFactory, + Func factory, CancellationToken cancellationToken - ) + ) where TResult : TItem { request.SetPartialResultToken(); if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) && o is IRequestProgressObservable observable) @@ -155,14 +154,39 @@ CancellationToken cancellationToken observable = new PartialItemRequestProgressObservable( _serializer, - request.PartialResultToken, + request.PartialResultToken!, MakeRequest(request), factory, - reverseFactory, + x => x, cancellationToken, - () => _activeObservables.TryRemove(request.PartialResultToken, out _) + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) ); - _activeObservables.TryAdd(request.PartialResultToken, observable); + _activeObservables.TryAdd(request.PartialResultToken!, observable); + return observable; + } + + public IRequestProgressObservable MonitorUntil( + IPartialItemWithInitialValueRequest request, + Func factory, + CancellationToken cancellationToken + ) + where TResult : TItem + { + request.SetPartialResultToken(); + if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) && o is IRequestProgressObservable observable) + { + return observable; + } + + observable = new PartialItemWithInitialValueRequestProgressObservable( + _serializer, + request.PartialResultToken!, + MakeRequest(request), + factory, + cancellationToken, + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) + ); + _activeObservables.TryAdd(request.PartialResultToken!, observable); return observable; } @@ -172,20 +196,21 @@ CancellationToken cancellationToken ) { request.SetPartialResultToken(); - if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) && o is IRequestProgressObservable, IEnumerable> observable) + if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) + && o is IRequestProgressObservable, IEnumerable> observable) { return observable; } observable = new PartialItemsRequestProgressObservable>( _serializer, - request.PartialResultToken, + request.PartialResultToken!, MakeRequest(request), x => x, cancellationToken, - () => _activeObservables.TryRemove(request.PartialResultToken, out _) - ); - _activeObservables.TryAdd(request.PartialResultToken, observable); + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) + )!; + _activeObservables.TryAdd(request.PartialResultToken!, observable); return observable; } @@ -193,22 +218,23 @@ public IRequestProgressObservable, TResponse> MonitorUntil request, Func, TResponse> factory, CancellationToken cancellationToken ) - where TResponse : IEnumerable? + where TResponse : IEnumerable { request.SetPartialResultToken(); - if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) && o is IRequestProgressObservable, TResponse> observable) + if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) + && o is IRequestProgressObservable, TResponse> observable) { return observable; } observable = new PartialItemsRequestProgressObservable( _serializer, - request.PartialResultToken, + request.PartialResultToken!, MakeRequest(request), factory, cancellationToken, - () => _activeObservables.TryRemove(request.PartialResultToken, out _) - ); - _activeObservables.TryAdd(request.PartialResultToken, observable); + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) + )!; + _activeObservables.TryAdd(request.PartialResultToken!, observable); return observable; } @@ -222,14 +248,39 @@ public IRequestProgressObservable MonitorUntil(IPartialItemsReques observable = new PartialItemsRequestProgressObservable( _serializer, - request.PartialResultToken, + request.PartialResultToken!, MakeRequest(request), x => new Container(x), cancellationToken, - () => _activeObservables.TryRemove(request.PartialResultToken, out _), + () => _activeObservables.TryRemove(request.PartialResultToken!, out _), _logger.Value ); - _activeObservables.TryAdd(request.PartialResultToken, observable); + _activeObservables.TryAdd(request.PartialResultToken!, observable); + return observable; + } + + + public IRequestProgressObservable, TResponse> MonitorUntil( + IPartialItemsWithInitialValueRequest request, + Func, TResponse> factory, CancellationToken cancellationToken + ) + where TResponse : IEnumerable + { + request.SetPartialResultToken(); + if (_activeObservables.TryGetValue(request.PartialResultToken!, out var o) + && o is IRequestProgressObservable, TResponse> observable) + { + return observable; + } + + observable = new PartialItemsWithInitialValueRequestProgressObservable( + _serializer, + request.PartialResultToken!, + MakeRequest(request), + factory, cancellationToken, + () => _activeObservables.TryRemove(request.PartialResultToken!, out _) + ); + _activeObservables.TryAdd(request.PartialResultToken!, observable); return observable; } @@ -260,8 +311,25 @@ public IProgressObserver For(IPartialItemRequest For( + IPartialItemWithInitialValueRequest request, CancellationToken cancellationToken + ) where TResponse : TItem + { + if (request.PartialResultToken == null) return ProgressObserver.Noop; + if (_activeObservers.TryGetValue(request.PartialResultToken, out var o) && o is IProgressObserverWithInitialValue observer) + { + return observer; + } + + observer = new ProgressObserver( + request.PartialResultToken, _router, _serializer, cancellationToken, () => _activeObservers.TryRemove(request.PartialResultToken, out _) + ); + _activeObservers.TryAdd(request.PartialResultToken, observer); + return observer; + } + public IProgressObserver> For(IPartialItemsRequest request, CancellationToken cancellationToken) - where TResponse : IEnumerable? + where TResponse : IEnumerable { if (request.PartialResultToken == null) return ProgressObserver>.Noop; if (_activeObservers.TryGetValue(request.PartialResultToken, out var o) && o is IProgressObserver> observer) @@ -276,11 +344,31 @@ public IProgressObserver> For(IPartialItems return observer; } + public IProgressObserverWithInitialValue> For( + IPartialItemsWithInitialValueRequest request, CancellationToken cancellationToken + ) + where TInitial : IEnumerable + { + if (request.PartialResultToken == null) return ProgressObserver>.Noop; + if (_activeObservers.TryGetValue(request.PartialResultToken, out var o) + && o is IProgressObserverWithInitialValue> observer) + { + return observer; + } + + observer = new ProgressObserver>( + request.PartialResultToken, _router, _serializer, cancellationToken, () => _activeObservers.TryRemove(request.PartialResultToken, out _) + ); + _activeObservers.TryAdd(request.PartialResultToken, observer); + return observer; + } + private IObservable MakeRequest(IRequest request) => // Has problems with wanting custom exceptions around cancellation. // Observable.FromAsync(ct => _router.SendRequest(request, ct)) Observable.Create( - async (observer, ct) => { + async (observer, ct) => + { try { observer.OnNext(await _router.SendRequest(request, ct).ConfigureAwait(false)); diff --git a/src/Protocol/Progress/ProgressObserver.cs b/src/Protocol/Progress/ProgressObserver.cs index 95d6e069e..5c01ff449 100644 --- a/src/Protocol/Progress/ProgressObserver.cs +++ b/src/Protocol/Progress/ProgressObserver.cs @@ -9,13 +9,40 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Progress { + internal class ProgressObserver : ProgressObserver, IProgressObserverWithInitialValue + { + private bool _isInitialized; + + public static ProgressObserver Noop { get; } = + new ProgressObserver(new ProgressToken(nameof(Noop)), null, null, CancellationToken.None, () => { }); + + public ProgressObserver( + ProgressToken token, IResponseRouter? responseRouter, ISerializer? serializer, CancellationToken cancellationToken, Action disposal + ) : base(token, responseRouter, serializer, cancellationToken, disposal) + { + } + + public void OnNext(TInitial initial) + { + if (_isInitialized || isComplete || responseRouter == null) return; + responseRouter.SendNotification( + new ProgressParams + { + Token = ProgressToken, + Value = JToken.FromObject(initial, serializer?.JsonSerializer) + } + ); + _isInitialized = true; + } + } + internal class ProgressObserver : IProgressObserver { - private readonly IResponseRouter? _responseRouter; - private readonly ISerializer? _serializer; + protected readonly IResponseRouter? responseRouter; + protected readonly ISerializer? serializer; private readonly Action _disposal; private readonly TaskCompletionSource _completionSource; - private bool _isComplete; + protected bool isComplete; public static ProgressObserver Noop { get; } = new ProgressObserver(new ProgressToken(nameof(Noop)), null, null, CancellationToken.None, () => { }); @@ -28,8 +55,8 @@ public ProgressObserver( Action disposal ) { - _responseRouter = responseRouter; - _serializer = serializer; + this.responseRouter = responseRouter; + this.serializer = serializer; _disposal = disposal; ProgressToken = token; CancellationToken = cancellationToken; @@ -43,25 +70,26 @@ Action disposal public void OnCompleted() { - if (_isComplete) return; + if (isComplete) return; _completionSource.TrySetResult(Unit.Default); - _isComplete = true; + isComplete = true; } void IObserver.OnError(Exception error) { - if (_isComplete) return; + if (isComplete) return; _completionSource.TrySetException(error); - _isComplete = true; + isComplete = true; } public void OnNext(T value) { - if (_isComplete || _responseRouter == null) return; - _responseRouter.SendNotification( - new ProgressParams { + if (isComplete || responseRouter == null) return; + responseRouter.SendNotification( + new ProgressParams + { Token = ProgressToken, - Value = JToken.FromObject(value, _serializer?.JsonSerializer) + Value = JToken.FromObject(value, serializer?.JsonSerializer) } ); } diff --git a/src/Protocol/Protocol.csproj b/src/Protocol/Protocol.csproj index 28fb52bfa..df8c95b85 100644 --- a/src/Protocol/Protocol.csproj +++ b/src/Protocol/Protocol.csproj @@ -15,34 +15,23 @@ - + - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol.Proposals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageServer.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageServer.Shared, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f - <_Parameter1 - >OmniSharp.Extensions.LanguageClient, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageClient, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f diff --git a/src/Protocol/Serialization/Converters/CompletionListConverter.cs b/src/Protocol/Serialization/Converters/CompletionListConverter.cs index 701d9f473..352d98acc 100644 --- a/src/Protocol/Serialization/Converters/CompletionListConverter.cs +++ b/src/Protocol/Serialization/Converters/CompletionListConverter.cs @@ -7,44 +7,4 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters { - internal class CompletionListConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, CompletionList value, JsonSerializer serializer) - { - if (!value.IsIncomplete) - { - serializer.Serialize(writer, value.Items.ToArray()); - return; - } - - writer.WriteStartObject(); - writer.WritePropertyName("isIncomplete"); - writer.WriteValue(value.IsIncomplete); - - writer.WritePropertyName("items"); - writer.WriteStartArray(); - foreach (var item in value.Items) - { - serializer.Serialize(writer, item); - } - - writer.WriteEndArray(); - writer.WriteEndObject(); - } - - public override CompletionList ReadJson(JsonReader reader, Type objectType, CompletionList existingValue, bool hasExistingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.StartArray) - { - var array = JArray.Load(reader).ToObject>(serializer); - return new CompletionList(array); - } - - var result = JObject.Load(reader); - var items = result["items"].ToObject>(serializer); - return new CompletionList(items, result["isIncomplete"].Value()); - } - - public override bool CanRead => true; - } } diff --git a/src/Protocol/Serialization/Converters/GlobPatternConverter.cs b/src/Protocol/Serialization/Converters/GlobPatternConverter.cs new file mode 100644 index 000000000..8b05f1b5b --- /dev/null +++ b/src/Protocol/Serialization/Converters/GlobPatternConverter.cs @@ -0,0 +1,40 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters +{ + internal class GlobPatternConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, GlobPattern value, JsonSerializer serializer) + { + if (value.HasPattern) + { + writer.WriteValue(value.Pattern); + } + else + { + serializer.Serialize(writer, value.RelativePattern); + } + } + + public override GlobPattern ReadJson( + JsonReader reader, Type objectType, GlobPattern existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.String) + { + return new GlobPattern(( reader.Value as string )!); + } + + if (reader.TokenType == JsonToken.StartObject) + { + return new GlobPattern(JObject.Load(reader).ToObject()); + } + + return new GlobPattern(""); + } + + public override bool CanRead => true; + } +} diff --git a/src/Protocol/Serialization/Converters/LocationOrFileLocationConverter.cs b/src/Protocol/Serialization/Converters/LocationOrFileLocationConverter.cs new file mode 100644 index 000000000..01112e26a --- /dev/null +++ b/src/Protocol/Serialization/Converters/LocationOrFileLocationConverter.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; + +public class LocationOrFileLocationConverter : JsonConverter +{ + public override void WriteJson(JsonWriter writer, LocationOrFileLocation value, JsonSerializer serializer) + { + if (value.IsLocation) + serializer.Serialize(writer, value.Location); + if (value.IsFileLocation) + serializer.Serialize(writer, value.FileLocation); + } + + public override LocationOrFileLocation ReadJson(JsonReader reader, Type objectType, LocationOrFileLocation existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var obj = JObject.Load(reader); + if (obj.ContainsKey("range")) + { + return new LocationOrFileLocation(obj.ToObject()); + } + + return new LocationOrFileLocation(obj.ToObject()); + } + + public override bool CanRead => true; +} diff --git a/src/Protocol/Serialization/Converters/NumberEnumConverter.cs b/src/Protocol/Serialization/Converters/NumberEnumConverter.cs index f318cad3b..7563be77d 100644 --- a/src/Protocol/Serialization/Converters/NumberEnumConverter.cs +++ b/src/Protocol/Serialization/Converters/NumberEnumConverter.cs @@ -9,9 +9,13 @@ internal class NumberEnumConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => new JValue(value).WriteTo(writer); - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => Enum.Parse( - Nullable.GetUnderlyingType(objectType) ?? objectType, reader.Value.ToString() - ); + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + return Enum.Parse( + Nullable.GetUnderlyingType(objectType) ?? objectType, reader.Value.ToString() + ); + } public override bool CanRead => true; diff --git a/src/Protocol/Serialization/Converters/WorkspaceFolderOrUriConverter.cs b/src/Protocol/Serialization/Converters/WorkspaceFolderOrUriConverter.cs new file mode 100644 index 000000000..9e9ab992c --- /dev/null +++ b/src/Protocol/Serialization/Converters/WorkspaceFolderOrUriConverter.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters +{ + internal class WorkspaceFolderOrUriConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, WorkspaceFolderOrUri value, JsonSerializer serializer) + { + if (value.HasWorkspaceFolder) + { + serializer.Serialize(writer, value.WorkspaceFolder); + } + else + { + serializer.Serialize(writer, value.Uri); + } + } + + public override WorkspaceFolderOrUri ReadJson( + JsonReader reader, Type objectType, WorkspaceFolderOrUri existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.String) + { + return new WorkspaceFolderOrUri(( reader.Value as string )!); + } + + if (reader.TokenType == JsonToken.StartObject) + { + var obj = JObject.Load(reader); + if (obj.ContainsKey("name")) + { + return new WorkspaceFolderOrUri(obj.ToObject()); + } + + return new WorkspaceFolderOrUri(obj.ToObject()); + } + + return new WorkspaceFolderOrUri(""); + } + + public override bool CanRead => true; + } +} diff --git a/src/Protocol/Serialization/Serializer.cs b/src/Protocol/Serialization/Serializer.cs index 96c55b41a..441e2ae63 100644 --- a/src/Protocol/Serialization/Serializer.cs +++ b/src/Protocol/Serialization/Serializer.cs @@ -105,7 +105,7 @@ protected override JsonSerializerSettings CreateSerializerSettings() protected override void AddOrReplaceConverters(ICollection converters) { ReplaceConverter(converters, new SupportsConverter()); - ReplaceConverter(converters, new CompletionListConverter()); + ReplaceConverter(converters, new CompletionList.Converter()); ReplaceConverter(converters, new DiagnosticCodeConverter()); ReplaceConverter(converters, new NullableDiagnosticCodeConverter()); ReplaceConverter(converters, new LocationOrLocationLinksConverter()); @@ -123,6 +123,7 @@ protected override void AddOrReplaceConverters(ICollection conver ReplaceConverter(converters, new SemanticTokensFullOrDeltaPartialResultConverter()); ReplaceConverter(converters, new SymbolInformationOrDocumentSymbolConverter()); ReplaceConverter(converters, new LocationOrLocationLinkConverter()); + ReplaceConverter(converters, new StringOrInlayHintLabelParts.Converter()); ReplaceConverter(converters, new WorkspaceEditDocumentChangeConverter()); ReplaceConverter(converters, new ParameterInformationLabelConverter()); ReplaceConverter(converters, new ValueTupleContractResolver()); diff --git a/src/Protocol/Server/Capabilities/IServerCapabilities.cs b/src/Protocol/Server/Capabilities/IServerCapabilities.cs index b441b237c..d410f321c 100644 --- a/src/Protocol/Server/Capabilities/IServerCapabilities.cs +++ b/src/Protocol/Server/Capabilities/IServerCapabilities.cs @@ -13,12 +13,32 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities /// public interface IServerCapabilities : ICapabilitiesBase { + /// + /// The position encoding the server picked from the encodings offered + /// by the client via the client capability `general.positionEncodings`. + /// + /// If the client didn't provide any position encodings the only valid + /// value that a server can return is 'utf-16'. + /// + /// If omitted it defaults to 'utf-16'. + /// + /// @since 3.17.0 + /// + PositionEncodingKind? PositionEncoding { get; set; } + /// /// Defines how text documents are synced. Is either a detailed structure defining each notification or /// for backwards compatibility the TextDocumentSyncKind number. /// TextDocumentSync? TextDocumentSync { get; set; } +// /// +// /// Defines how notebook documents are synced. +// /// +// /// @since 3.17.0 +// /// +// NotebookDocumentSyncOptions.StaticOptions NotebookDocumentSync { get; set; } + /// /// The server provides hover support. /// @@ -167,5 +187,33 @@ public interface IServerCapabilities : ICapabilitiesBase /// Since 3.14.0 /// BooleanOr? DeclarationProvider { get; set; } + + /// + /// The server provides type hierarchy support. + /// + /// @since 3.17.0 + /// + BooleanOr? TypeHierarchyProvider { get; set; } + + /// + /// The server provides inline values. + /// + /// @since 3.17.0 + /// + BooleanOr? InlineValueProvider { get; set; } + + /// + /// The server provides inlay hints. + /// + /// @since 3.17.0 + /// + BooleanOr? InlayHintProvider { get; set; } + + /// + /// The server has support for pull model diagnostics. + /// + /// @since 3.17.0 + /// + DiagnosticsRegistrationOptions.StaticOptions? DiagnosticProvider { get; set; } } } diff --git a/src/Protocol/Server/Capabilities/ServerCapabilities.cs b/src/Protocol/Server/Capabilities/ServerCapabilities.cs index 578440393..6d2c3e9ce 100644 --- a/src/Protocol/Server/Capabilities/ServerCapabilities.cs +++ b/src/Protocol/Server/Capabilities/ServerCapabilities.cs @@ -14,6 +14,19 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities /// public class ServerCapabilities : CapabilitiesBase, IServerCapabilities { + /// + /// The position encoding the server picked from the encodings offered + /// by the client via the client capability `general.positionEncodings`. + /// + /// If the client didn't provide any position encodings the only valid + /// value that a server can return is 'utf-16'. + /// + /// If omitted it defaults to 'utf-16'. + /// + /// @since 3.17.0 + /// + public PositionEncodingKind? PositionEncoding { get; set; } + /// /// Defines how text documents are synced. Is either a detailed structure defining each notification or /// for backwards compatibility the TextDocumentSyncKind number. @@ -21,6 +34,14 @@ public class ServerCapabilities : CapabilitiesBase, IServerCapabilities [Optional] public TextDocumentSync? TextDocumentSync { get; set; } + /// + /// Defines how notebook documents are synced. + /// + /// @since 3.17.0 + /// + [Optional] + public NotebookDocumentSyncOptions? NotebookDocumentSync { get; set; } + /// /// The server provides hover support. /// @@ -170,6 +191,7 @@ public class ServerCapabilities : CapabilitiesBase, IServerCapabilities /// /// Since 3.10.0 /// + [Optional] public BooleanOr? FoldingRangeProvider { get; set; } /// @@ -177,6 +199,7 @@ public class ServerCapabilities : CapabilitiesBase, IServerCapabilities /// /// Since 3.15.0 /// + [Optional] public BooleanOr? SelectionRangeProvider { get; set; } /// @@ -192,8 +215,41 @@ public class ServerCapabilities : CapabilitiesBase, IServerCapabilities /// /// Since 3.14.0 /// + [Optional] public BooleanOr? DeclarationProvider { get; set; } + /// + /// The server provides type hierarchy support. + /// + /// @since 3.17.0 + /// + [Optional] + public BooleanOr? TypeHierarchyProvider { get; set; } + + /// + /// The server provides inline values. + /// + /// @since 3.17.0 + /// + [Optional] + public BooleanOr? InlineValueProvider { get; set; } + + /// + /// The server provides inlay hints. + /// + /// @since 3.17.0 + /// + [Optional] + public BooleanOr? InlayHintProvider { get; set; } + + /// + /// The server has support for pull model diagnostics. + /// + /// @since 3.17.0 + /// + [Optional] + public DiagnosticsRegistrationOptions.StaticOptions? DiagnosticProvider { get; set; } + /// /// Workspace specific server capabilities /// diff --git a/src/Protocol/Server/ILanguageServerFacade.cs b/src/Protocol/Server/ILanguageServerFacade.cs index 15019d677..21f919ea1 100644 --- a/src/Protocol/Server/ILanguageServerFacade.cs +++ b/src/Protocol/Server/ILanguageServerFacade.cs @@ -5,6 +5,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Server public interface ILanguageServerFacade : ILanguageServerProxy, IJsonRpcHandlerInstance { ITextDocumentLanguageServer TextDocument { get; } + INotebookDocumentLanguageServer NotebookDocument { get; } IClientLanguageServer Client { get; } IGeneralLanguageServer General { get; } IWindowLanguageServer Window { get; } diff --git a/src/Protocol/Server/INotebookDocumentLanguageServer.cs b/src/Protocol/Server/INotebookDocumentLanguageServer.cs new file mode 100644 index 000000000..4b0d37231 --- /dev/null +++ b/src/Protocol/Server/INotebookDocumentLanguageServer.cs @@ -0,0 +1,5 @@ +namespace OmniSharp.Extensions.LanguageServer.Protocol.Server; + +public interface INotebookDocumentLanguageServer : ILanguageServerProxy +{ +} diff --git a/src/Protocol/Server/NotebookDocumentLanguageServer.cs b/src/Protocol/Server/NotebookDocumentLanguageServer.cs new file mode 100644 index 000000000..88c9001dd --- /dev/null +++ b/src/Protocol/Server/NotebookDocumentLanguageServer.cs @@ -0,0 +1,17 @@ + +using DryIoc; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.LanguageServer.Protocol.Progress; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Server +{ + internal class NotebookDocumentLanguageServer : LanguageProtocolProxy, INotebookDocumentLanguageServer + { + public NotebookDocumentLanguageServer( + IResponseRouter requestRouter, IResolverContext resolverContext, IProgressManager progressManager, + ILanguageProtocolSettings languageProtocolSettings + ) : base(requestRouter, resolverContext, progressManager, languageProtocolSettings) + { + } + } +} diff --git a/src/Protocol/Server/TextDocumentLanguageServer.cs b/src/Protocol/Server/TextDocumentLanguageServer.cs index 2c04ce3fd..699d33cd9 100644 --- a/src/Protocol/Server/TextDocumentLanguageServer.cs +++ b/src/Protocol/Server/TextDocumentLanguageServer.cs @@ -1,3 +1,4 @@ + using DryIoc; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Progress; diff --git a/src/Protocol/Shared/LspHandlerTypeDescriptor.cs b/src/Protocol/Shared/LspHandlerTypeDescriptor.cs index 2e5ba1123..f3120d281 100644 --- a/src/Protocol/Shared/LspHandlerTypeDescriptor.cs +++ b/src/Protocol/Shared/LspHandlerTypeDescriptor.cs @@ -15,12 +15,18 @@ public LspHandlerTypeDescriptor(Type handlerType) : base(handlerType) { if (HasParamsType) { - PartialItemsType = ParamsType!.GetInterfaces() - .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItems<>).IsAssignableFrom(z.GetGenericTypeDefinition())) + PartialItemsType = (ParamsType!.GetInterfaces() + .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItems<>).IsAssignableFrom(z.GetGenericTypeDefinition())) + ?? + ParamsType!.GetInterfaces() + .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItemsWithInitialValue<,>).IsAssignableFrom(z.GetGenericTypeDefinition())) + ) ?.GetGenericArguments()[0]; - PartialItemType = ParamsType.GetInterfaces() - .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItem<>).IsAssignableFrom(z.GetGenericTypeDefinition())) + PartialItemType = (ParamsType.GetInterfaces() + .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItem<>).IsAssignableFrom(z.GetGenericTypeDefinition()))?? + ParamsType.GetInterfaces() + .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItemWithInitialValue<,>).IsAssignableFrom(z.GetGenericTypeDefinition()))) ?.GetGenericArguments()[0]; } diff --git a/src/Protocol/TextDocumentNames.cs b/src/Protocol/TextDocumentNames.cs index a447bf7e3..2e99158eb 100644 --- a/src/Protocol/TextDocumentNames.cs +++ b/src/Protocol/TextDocumentNames.cs @@ -44,5 +44,12 @@ public static class TextDocumentNames public const string SemanticTokensRange = "textDocument/semanticTokens/range"; public const string Moniker = "textDocument/moniker"; public const string LinkedEditingRange = "textDocument/linkedEditingRange"; + public const string InlayHint = "textDocument/inlayHint"; + public const string InlayHintResolve = "inlayHint/resolve"; + public const string InlineValue = "textDocument/inlineValue"; + public const string Diagnostics = "textDocument/diagnostic"; + public const string PrepareTypeHierarchy = "textDocument/prepareTypeHierarchy"; + public const string TypeHierarchySupertypes = "typeHierarchy/supertypes"; + public const string TypeHierarchySubtypes = "typeHierarchy/subtypes"; } } diff --git a/src/Protocol/WorkspaceNames.cs b/src/Protocol/WorkspaceNames.cs index 90f5f6b31..598adb7bf 100644 --- a/src/Protocol/WorkspaceNames.cs +++ b/src/Protocol/WorkspaceNames.cs @@ -9,6 +9,7 @@ public static class WorkspaceNames public const string DidChangeWorkspaceFolders = "workspace/didChangeWorkspaceFolders"; public const string ExecuteCommand = "workspace/executeCommand"; public const string WorkspaceSymbol = "workspace/symbol"; + public const string WorkspaceSymbolResolve = "workspaceSymbol/resolve"; public const string WorkspaceFolders = "workspace/workspaceFolders"; public const string SemanticTokensRefresh = "workspace/semanticTokens/refresh"; public const string CodeLensRefresh = "workspace/codeLens/refresh"; @@ -18,6 +19,8 @@ public static class WorkspaceNames public const string DidRenameFiles = "workspace/didRenameFiles"; public const string WillDeleteFiles = "workspace/willDeleteFiles"; public const string DidDeleteFiles = "workspace/didDeleteFiles"; - + public const string InlineValueRefresh = "workspace/inlineValue/refresh"; + public const string DiagnosticRefresh = "workspace/diagnostic/refresh"; + public const string Diagnostics = "workspace/diagnostic"; } } diff --git a/src/Server/DefaultLanguageServerFacade.cs b/src/Server/DefaultLanguageServerFacade.cs index 3331596f3..a55433f06 100644 --- a/src/Server/DefaultLanguageServerFacade.cs +++ b/src/Server/DefaultLanguageServerFacade.cs @@ -16,6 +16,7 @@ namespace OmniSharp.Extensions.LanguageServer.Server internal class DefaultLanguageServerFacade : LanguageProtocolProxy, ILanguageServerFacade, IOnLanguageServerStarted { private readonly Lazy _textDocument; + private readonly Lazy _notebookDocument; private readonly Lazy _client; private readonly Lazy _general; private readonly Lazy _window; @@ -33,6 +34,7 @@ public DefaultLanguageServerFacade( IProgressManager progressManager, ILanguageProtocolSettings languageProtocolSettings, Lazy textDocument, + Lazy notebookDocument, Lazy client, Lazy general, Lazy window, @@ -45,6 +47,7 @@ IInsanceHasStarted instancesHasStarted ) : base(requestRouter, resolverContext, progressManager, languageProtocolSettings) { _textDocument = textDocument; + _notebookDocument = notebookDocument; _client = client; _general = general; _window = window; @@ -58,6 +61,7 @@ IInsanceHasStarted instancesHasStarted } public ITextDocumentLanguageServer TextDocument => _textDocument.Value; + public INotebookDocumentLanguageServer NotebookDocument => _notebookDocument.Value; public IClientLanguageServer Client => _client.Value; public IGeneralLanguageServer General => _general.Value; public IWindowLanguageServer Window => _window.Value; diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index ef81d70d8..987229e84 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -12,6 +12,7 @@ using DryIoc; using MediatR; using Microsoft.Extensions.Options; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol; @@ -180,6 +181,7 @@ internal LanguageServer( IEnumerable startedHandlers, IServerWorkDoneManager serverWorkDoneManager, ITextDocumentLanguageServer textDocumentLanguageServer, + INotebookDocumentLanguageServer notebookDocumentLanguageServer, IClientLanguageServer clientLanguageServer, IGeneralLanguageServer generalLanguageServer, IWindowLanguageServer windowLanguageServer, @@ -214,6 +216,7 @@ IScheduler scheduler // We need to at least create Window here in case any handler does logging in their constructor TextDocument = textDocumentLanguageServer; + NotebookDocument = notebookDocumentLanguageServer; Client = clientLanguageServer; General = generalLanguageServer; Window = windowLanguageServer; @@ -231,19 +234,27 @@ IScheduler scheduler _capabilityTypes = options.Value.UseAssemblyAttributeScanning ? options.Value.Assemblies .SelectMany(z => z.GetCustomAttributes()) - .ToLookup(z => z.CapabilityKey, z => z.CapabilityType) + .ToLookup( + z => char.ToLowerInvariant(z.CapabilityKey[0]) + z.CapabilityKey.Substring(1), z => z.CapabilityType, + StringComparer.OrdinalIgnoreCase + ) : options.Value.Assemblies .SelectMany(z => z.ExportedTypes) .Where(z => z.IsClass && !z.IsAbstract) .Where(z => typeof(ICapability).IsAssignableFrom(z)) .Where(z => z.GetCustomAttributes().Any()) - .ToLookup(z => string.Join(".", z.GetCustomAttribute().Keys)); + .ToLookup( + z => string.Join( + ".", z.GetCustomAttribute().Keys.Select(z => char.ToLowerInvariant(z[0]) + z.Substring(1)) + ), StringComparer.OrdinalIgnoreCase + ); _disposable.Add(_collection.Add(this)); } public ITextDocumentLanguageServer TextDocument { get; } + public INotebookDocumentLanguageServer NotebookDocument { get; } public IClientLanguageServer Client { get; } public IGeneralLanguageServer General { get; } public IWindowLanguageServer Window { get; } @@ -318,7 +329,10 @@ async Task IRequestHandler("{}"); + notebookDocumentCapabilities = + ClientSettings.Capabilities.NotebookDocument ??= _serializer.DeserializeObject("{}"); workspaceCapabilities = ClientSettings.Capabilities.Workspace ??= _serializer.DeserializeObject("{}"); windowCapabilities = ClientSettings.Capabilities.Window ??= _serializer.DeserializeObject("{}"); generalCapabilities = ClientSettings.Capabilities.General ??= _serializer.DeserializeObject("{}"); @@ -448,7 +474,11 @@ out GeneralClientCapabilities generalCapabilities } private InitializeResult ReadServerCapabilities( - ClientCapabilities clientCapabilities, WindowClientCapabilities windowCapabilities, TextDocumentClientCapabilities textDocumentCapabilities + ClientCapabilities clientCapabilities, + WindowClientCapabilities windowCapabilities, + WorkspaceClientCapabilities workspaceCapabilities, + TextDocumentClientCapabilities textDocumentCapabilities, + NotebookDocumentClientCapabilities notebookDocumentCapabilities ) { // little hack to ensure that we get the proposed capabilities if proposals are turned on @@ -457,7 +487,7 @@ private InitializeResult ReadServerCapabilities( var serverCapabilitiesObject = new JObject(); foreach (var converter in _registrationOptionsConverters) { - var keys = ( converter.Key ?? Array.Empty() ).Select(key => char.ToLower(key[0]) + key.Substring(1)).ToArray(); + var keys = ( converter.Key ?? Array.Empty() ).Select(key => char.ToLowerInvariant(key[0]) + key.Substring(1)).ToArray(); var value = serverCapabilitiesObject; foreach (var key in keys.Take(keys.Length - 1)) { diff --git a/src/Server/LanguageServerServiceCollectionExtensions.cs b/src/Server/LanguageServerServiceCollectionExtensions.cs index 1f15b71bf..c45cde01a 100644 --- a/src/Server/LanguageServerServiceCollectionExtensions.cs +++ b/src/Server/LanguageServerServiceCollectionExtensions.cs @@ -43,6 +43,7 @@ internal static IContainer AddLanguageServerInternals(this IContainer container, } container.RegisterMany(serviceTypeCondition: type => type.Name.Contains(nameof(TextDocumentLanguageServer)), reuse: Reuse.Singleton); + container.RegisterMany(serviceTypeCondition: type => type.Name.Contains(nameof(NotebookDocumentLanguageServer)), reuse: Reuse.Singleton); container.RegisterMany(serviceTypeCondition: type => type.Name.Contains(nameof(ClientLanguageServer)), reuse: Reuse.Singleton); container.RegisterMany(serviceTypeCondition: type => type.Name.Contains(nameof(GeneralLanguageServer)), reuse: Reuse.Singleton); container.RegisterMany(serviceTypeCondition: type => type.Name.Contains(nameof(WindowLanguageServer)), reuse: Reuse.Singleton); @@ -105,6 +106,7 @@ internal static IContainer AddLanguageServerInternals(this IContainer container, ); container.RegisterMany(Reuse.Singleton); + container.RegisterMany(Reuse.Singleton); container.RegisterMany(Reuse.Singleton); container.RegisterMany(Reuse.Singleton); container.RegisterMany(new[] { typeof(ResolveCommandPipeline<,>) }); diff --git a/src/Server/Matchers/NotebookDocumentMatcher.cs b/src/Server/Matchers/NotebookDocumentMatcher.cs new file mode 100644 index 000000000..62235e9c3 --- /dev/null +++ b/src/Server/Matchers/NotebookDocumentMatcher.cs @@ -0,0 +1,119 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Logging; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Shared; +using OmniSharp.Extensions.LanguageServer.Shared; + +namespace OmniSharp.Extensions.LanguageServer.Server.Matchers +{ + internal class NotebookDocumentMatcher : IHandlerMatcher + { + private readonly ILogger _logger; + private readonly NotebookDocumentIdentifiers _notebookDocumentIdentifiers; + + public NotebookDocumentMatcher(ILogger logger, NotebookDocumentIdentifiers notebookDocumentIdentifiers) + { + _logger = logger; + _notebookDocumentIdentifiers = notebookDocumentIdentifiers; + } + + public IEnumerable FindHandler(object parameters, IEnumerable descriptors) + { + switch (parameters) + { + case INotebookDocumentIdentifierParams notebookDocumentIdentifierParams: + { + // ReSharper disable once ConstantConditionalAccessQualifier + if (notebookDocumentIdentifierParams.NotebookDocument?.Uri is null) break; + var attributes = GetNotebookDocumentAttributes(notebookDocumentIdentifierParams.NotebookDocument.Uri); + + _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.NotebookType}:{x.Scheme}:{x.Uri}")); + + return GetHandler(descriptors, attributes); + } + case DidOpenNotebookDocumentParams openNotebookDocumentParams: + { + // ReSharper disable once ConstantConditionalAccessQualifier + if (openNotebookDocumentParams.NotebookDocument?.Uri is null) break; + var attributes = new List() + { + new ( + openNotebookDocumentParams.NotebookDocument.Uri, openNotebookDocumentParams.NotebookDocument.NotebookType + ) + }; + attributes.AddRange( + openNotebookDocumentParams.CellTextDocuments + .Select(z => new NotebookDocumentAttributes(z.LanguageId, z.Uri)) + .Distinct() + ); + + _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.NotebookType}:{x.Scheme}:{x.Uri}")); + + return GetHandler(descriptors, attributes); + } + case DidChangeNotebookDocumentParams didChangeDocumentParams: + { + // ReSharper disable once ConstantConditionalAccessQualifier + if (didChangeDocumentParams.NotebookDocument?.Uri is null) break; + // TODO: Do something with document version here? + var attributes = GetNotebookDocumentAttributes(didChangeDocumentParams.NotebookDocument.Uri); + + attributes.AddRange( + didChangeDocumentParams.Change.Cells.Structure?.Array.Cells? + .Select(z => new NotebookDocumentAttributes(z.Document)) + .Distinct() ?? Array.Empty() + ); + attributes.AddRange( + didChangeDocumentParams.Change.Cells.Data? + .Select(z => new NotebookDocumentAttributes(z.Document)) + .Distinct() ?? Array.Empty() + ); + + _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.NotebookType}:{x.Scheme}:{x.Uri}")); + + return GetHandler(descriptors, attributes); + } + } + + return Enumerable.Empty(); + } + + private List GetNotebookDocumentAttributes(DocumentUri uri) => + _notebookDocumentIdentifiers + .Select(x => x.GetNotebookDocumentAttributes(uri)) + .Where(x => x is not null) + .ToList(); + + private IEnumerable GetHandler(IEnumerable descriptors, IEnumerable attributes) => + attributes.SelectMany(z => GetHandler(descriptors, z)).Distinct(); + + private IEnumerable GetHandler(IEnumerable descriptors, NotebookDocumentAttributes attributes) + { + var lspHandlerDescriptors = descriptors as ILspHandlerDescriptor[] ?? descriptors.ToArray(); + var method = lspHandlerDescriptors.FirstOrDefault()?.Method; + _logger.LogTrace("Looking for handler for descriptors {Method}", method); + foreach (var descriptor in lspHandlerDescriptors) + { + _logger.LogTrace("Checking handler {Method}:{Handler}", method, descriptor.ImplementationType.FullName); + var registrationOptions = descriptor.RegistrationOptions as INotebookDocumentRegistrationOptions; + + _logger.LogTrace("Registration options {OptionsName}", registrationOptions?.GetType().FullName); + _logger.LogTrace("Document Selector {NotebookDocumentSelector}", registrationOptions?.NotebookSelector?.ToString() ?? string.Empty); + if (registrationOptions?.NotebookSelector is null || registrationOptions.NotebookSelector.IsMatch(attributes)) + { + _logger.LogTrace( + "Handler Selected: {Handler} {Id} via {NotebookDocumentSelector} (targeting {HandlerInterface})", + descriptor.ImplementationType.FullName, + descriptor.Handler is ICanBeIdentifiedHandler h ? h.Id.ToString() : string.Empty, + registrationOptions?.NotebookSelector?.ToString(), + descriptor.HandlerType.FullName + ); + yield return descriptor; + } + } + } + } +} diff --git a/src/Server/Matchers/TextDocumentMatcher.cs b/src/Server/Matchers/TextDocumentMatcher.cs index 758d716e4..a90aeb9c9 100644 --- a/src/Server/Matchers/TextDocumentMatcher.cs +++ b/src/Server/Matchers/TextDocumentMatcher.cs @@ -80,11 +80,11 @@ private IEnumerable GetHandler(IEnumerable - <_Parameter1 - >OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f + <_Parameter1>OmniSharp.Extensions.LanguageProtocol.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f diff --git a/test/Dap.Tests/FoundationTests.cs b/test/Dap.Tests/FoundationTests.cs index 3f5a70897..f592e298a 100644 --- a/test/Dap.Tests/FoundationTests.cs +++ b/test/Dap.Tests/FoundationTests.cs @@ -140,7 +140,7 @@ public void HandlersShouldMatchParamsMethodAttribute(Type type) lhs.Direction.Should().Be(rhs.Direction, $"{type.FullName} direction does not match {paramsType.FullName}"); } - [Theory(DisplayName = "Handler interfaces should have a abstract class")] + [Theory(DisplayName = "Handler interfaces should have an abstract class")] [ClassData(typeof(TypeHandlerData))] public void HandlersShouldAbstractClass(IHandlerTypeDescriptor descriptor) { @@ -226,17 +226,19 @@ public void HandlersShouldHaveExpectedExtensionMethodsBasedOnDirection( .Distinct() .ToHashSet(); - var expectedEventRegistries = descriptor.Direction switch { - Direction.ClientToServer => new (string type, Func matcher)[] { ( "Server", info => info.ParameterType.Name.EndsWith("ServerRegistry") ) }, - Direction.ServerToClient => new (string type, Func matcher)[] { ( "Client", info => info.ParameterType.Name.EndsWith("ClientRegistry") ) }, + var expectedEventRegistries = descriptor.Direction switch + { + Direction.ClientToServer => new (string type, Func matcher)[] { ("Server", info => info.ParameterType.Name.EndsWith("ServerRegistry")) }, + Direction.ServerToClient => new (string type, Func matcher)[] { ("Client", info => info.ParameterType.Name.EndsWith("ClientRegistry")) }, Direction.Bidirectional => new (string type, Func matcher)[] { ( "Server", info => info.ParameterType.Name.EndsWith("ServerRegistry") ), ( "Client", info => info.ParameterType.Name.EndsWith("ClientRegistry") ) }, _ => throw new NotImplementedException(descriptor.HandlerType.FullName) }; - var expectedRequestHandlers = descriptor.Direction switch { - Direction.ClientToServer => new (string type, Func matcher)[] { ( "Server", info => info.ParameterType.Name.EndsWith("Client") ) }, - Direction.ServerToClient => new (string type, Func matcher)[] { ( "Client", info => info.ParameterType.Name.EndsWith("Server") ) }, + var expectedRequestHandlers = descriptor.Direction switch + { + Direction.ClientToServer => new (string type, Func matcher)[] { ("Server", info => info.ParameterType.Name.EndsWith("Client")) }, + Direction.ServerToClient => new (string type, Func matcher)[] { ("Client", info => info.ParameterType.Name.EndsWith("Server")) }, Direction.Bidirectional => new (string type, Func matcher)[] { ( "Server", info => info.ParameterType.Name.EndsWith("Client") ), ( "Client", info => info.ParameterType.Name.EndsWith("Server") ) }, _ => throw new NotImplementedException(descriptor.HandlerType.FullName) @@ -526,7 +528,7 @@ private static Type GetExtensionClass(IHandlerTypeDescriptor descriptor) { var name = GetExtensionClassName(descriptor); return descriptor.HandlerType.Assembly.GetExportedTypes() - .FirstOrDefault(z => z.IsClass && z.IsAbstract && ( z.Name == name || z.Name == name + "Base" )); + .FirstOrDefault(z => z.IsClass && z.IsAbstract && (z.Name == name || z.Name == name + "Base")); } private static string GetOnMethodName(IHandlerTypeDescriptor descriptor) => "On" + SpecialCasedHandlerName(descriptor); diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index 2e1c2229c..2ac321523 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -16,6 +16,8 @@ + + <_Parameter1>Client.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f diff --git a/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs b/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs index 3565b53ae..03653d58b 100644 --- a/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs +++ b/test/Generation.Tests/AutoImplementParamsGeneratorTests.cs @@ -4,6 +4,7 @@ namespace Generation.Tests { + [UsesVerify] public class AutoImplementParamsGeneratorTests { [Fact] @@ -23,31 +24,7 @@ namespace Test 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 Newtonsoft.Json; -using System.ComponentModel; -using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; - -namespace Test -{ - public partial class DeclarationParams - { - [Optional] - public ProgressToken? WorkDoneToken { get; init; } - - [Optional] - public ProgressToken? PartialResultToken { get; init; } - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } } } diff --git a/test/Generation.Tests/EnumLikeStringGeneratorTests.cs b/test/Generation.Tests/EnumLikeStringGeneratorTests.cs index 320a396fc..1bad0d8cd 100644 --- a/test/Generation.Tests/EnumLikeStringGeneratorTests.cs +++ b/test/Generation.Tests/EnumLikeStringGeneratorTests.cs @@ -4,6 +4,7 @@ namespace Generation.Tests { + [UsesVerify] public class EnumLikeStringGeneratorTests { [Fact] @@ -20,43 +21,7 @@ public readonly partial struct ThreadEventReason } } "; - var expected = @" -#nullable enable -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Newtonsoft.Json; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Serialization.Converters; - -namespace Test -{ - [JsonConverter(typeof(EnumLikeStringConverter))] - [DebuggerDisplay(""{_value}"")] - public readonly partial struct ThreadEventReason : IEquatable, IEquatable, IEnumLikeString - { - private static readonly Lazy> _defaults = new Lazy>(() => - { - return new ThreadEventReason[]{Started, Exited}; - }); - public static IEnumerable Defaults => _defaults.Value; - private readonly string _value; - public ThreadEventReason(string type) => _value = type; - public static implicit operator ThreadEventReason(string kind) => new ThreadEventReason(kind); - public static implicit operator string (ThreadEventReason kind) => kind._value; - public override string ToString() => _value; - public bool Equals(ThreadEventReason other) => _value == other._value; - public bool Equals(string other) => _value == other; - public override bool Equals(object obj) => obj is string s && Equals(s) || obj is ThreadEventReason other && Equals(other); - public override int GetHashCode() => _value.GetHashCode(); - public static bool operator ==(ThreadEventReason left, ThreadEventReason right) => left.Equals(right); - public static bool operator !=(ThreadEventReason left, ThreadEventReason right) => !left.Equals(right); - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } } } diff --git a/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs b/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs index 1ab1e1561..2a4e132f8 100644 --- a/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs +++ b/test/Generation.Tests/GeneratedRegistrationOptionsTests.cs @@ -4,6 +4,7 @@ namespace Generation.Tests { + [UsesVerify] public class GeneratedRegistrationOptionsTests { [Fact] @@ -20,44 +21,7 @@ namespace Test 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 -{ - [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] - [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() - { - } - - public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) - { - return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; - } - } - - [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] - public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions - { - [Optional] - public bool WorkDoneProgress { get; set; } - } - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(await GenerationHelpers.GenerateAll(source)); } [Fact] @@ -76,45 +40,7 @@ public partial class WorkspaceSymbolRegistrationOptions : IWorkDoneProgressOptio } "; - 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 -{ - [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] - [RegistrationOptionsConverterAttribute(typeof(WorkspaceSymbolRegistrationOptionsConverter))] - public partial class WorkspaceSymbolRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions - { - [Optional] - public bool WorkDoneProgress { get; set; } - - class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public WorkspaceSymbolRegistrationOptionsConverter() - { - } - - public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) - { - return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; - } - } - - [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] - public partial class StaticOptions : IWorkDoneProgressOptions - { - [Optional] - public bool WorkDoneProgress { get; set; } - } - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(await GenerationHelpers.GenerateAll(source)); } [Fact] @@ -142,7 +68,7 @@ public async Task Supports_Generating_Strongly_Typed_Registration_Options() #nullable enable namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeActionProvider), SupportsDocumentSelector = true, SupportsWorkDoneProgress = true] + [GenerateRegistrationOptions(nameof(ServerCapabilities.CodeActionProvider), SupportsTextDocumentSelector = true, SupportsWorkDoneProgress = true] public partial class CodeActionRegistrationOptions { /// @@ -165,76 +91,7 @@ public partial class CodeActionRegistrationOptions } } #nullable restore"; - - var expected = @" -using System; -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; -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; - -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ - [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] - [RegistrationOptionsConverterAttribute(typeof(CodeActionRegistrationOptionsConverter))] - public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions - { - public DocumentSelector? DocumentSelector { get; set; } - - [Optional] - public bool WorkDoneProgress { get; set; } - - class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public CodeActionRegistrationOptionsConverter() - { - } - - public override StaticOptions Convert(CodeActionRegistrationOptions source) - { - return new StaticOptions{CodeActionKinds = source.CodeActionKinds, ResolveProvider = source.ResolveProvider, WorkDoneProgress = source.WorkDoneProgress}; - } - } - - [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] - public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.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 { 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; } - - [Optional] - public bool WorkDoneProgress { get; set; } - } - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(await GenerationHelpers.GenerateAll(source)); } [Fact] @@ -304,62 +161,7 @@ public override StaticCodeActionRegistrationOptions Convert(CodeActionRegistrati } #nullable restore"; - var expected = @" -using System; -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; -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; - -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ - [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] - public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions - { - public DocumentSelector? DocumentSelector { get; set; } - - [Optional] - public bool WorkDoneProgress { get; set; } - - [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] - public partial class StaticOptions : 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 { 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; } - - [Optional] - public bool WorkDoneProgress { get; set; } - } - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(await GenerationHelpers.GenerateAll(source)); } } } diff --git a/test/Generation.Tests/Generation.Tests.csproj b/test/Generation.Tests/Generation.Tests.csproj index eef43b102..4af9af6e5 100644 --- a/test/Generation.Tests/Generation.Tests.csproj +++ b/test/Generation.Tests/Generation.Tests.csproj @@ -12,5 +12,11 @@ + + + + + JsonRpcGenerationTests + diff --git a/test/Generation.Tests/GenerationHelpers.cs b/test/Generation.Tests/GenerationHelpers.cs index 5dc0da1a2..0726a2008 100644 --- a/test/Generation.Tests/GenerationHelpers.cs +++ b/test/Generation.Tests/GenerationHelpers.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using FluentAssertions; using MediatR; @@ -12,6 +13,7 @@ using Newtonsoft.Json.Linq; using OmniSharp.Extensions.DebugAdapter.Protocol.Client; using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.JsonRpc.Generators; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using Xunit; @@ -52,8 +54,12 @@ static GenerationHelpers() MetadataReferences = coreMetaReferences .Concat(otherAssemblies.Distinct().Select(x => MetadataReference.CreateFromFile(x.Location))) .ToImmutableArray(); + + AllGenerators = typeof(StronglyTypedGenerator).Assembly.GetTypes().Where(z => typeof(IIncrementalGenerator).IsAssignableFrom(z) && z.GetCustomAttributes().Any()).ToImmutableArray(); } + public static ImmutableArray AllGenerators { get; set; } + internal const string CrLf = "\r\n"; internal const string Lf = "\n"; internal const string DefaultFilePathPrefix = "Test"; @@ -87,6 +93,61 @@ public static string NormalizeToLf(string input) return input.Replace(CrLf, Lf); } + public static async Task GenerateAll(string source) + { + var document = CreateProject(source).Documents.Single(); + var tree = await document.GetSyntaxTreeAsync(); + if (tree is null) + { + throw new InvalidOperationException("Could not get the syntax tree of the sources"); + } + + var compilation = (CSharpCompilation)( await document.Project.GetCompilationAsync() )!; + if (compilation is null) + { + throw new InvalidOperationException("Could not compile the sources"); + } + + GeneratorDriver driver = CSharpGeneratorDriver.Create( + AllGenerators.Select(z => Activator.CreateInstance(z) as IIncrementalGenerator).Select(z => z.AsSourceGenerator()).ToImmutableArray(), + ImmutableArray.Empty, + compilation.SyntaxTrees[0].Options as CSharpParseOptions + ); + + driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics); + return driver.GetRunResult(); + } + + public static async Task GeneratorRun(string source) where T : IIncrementalGenerator, new() + { + var document = CreateProject(source).Documents.Single(); + var tree = await document.GetSyntaxTreeAsync(); + if (tree is null) + { + throw new InvalidOperationException("Could not get the syntax tree of the sources"); + } + + var compilation = (CSharpCompilation)( await document.Project.GetCompilationAsync() )!; + if (compilation is null) + { + throw new InvalidOperationException("Could not compile the sources"); + } + + var diagnostics = compilation.GetDiagnostics(); +// Assert.Empty(diagnostics.Where(x => x.Severity >= DiagnosticSeverity.Warning)); + + IIncrementalGenerator generator = new T(); + + GeneratorDriver driver = CSharpGeneratorDriver.Create( + ImmutableArray.Create(generator.AsSourceGenerator()), + ImmutableArray.Empty, + compilation.SyntaxTrees[0].Options as CSharpParseOptions + ); + + driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out diagnostics); + return driver.GetRunResult(); + } + public static async Task> GenerateAsync(string source) where T : IIncrementalGenerator, new() { var document = CreateProject(source).Documents.Single(); diff --git a/test/Generation.Tests/JsonRpcGenerationTests.cs b/test/Generation.Tests/JsonRpcGenerationTests.cs index 496e8eed2..614fd3cdf 100644 --- a/test/Generation.Tests/JsonRpcGenerationTests.cs +++ b/test/Generation.Tests/JsonRpcGenerationTests.cs @@ -7,6 +7,7 @@ namespace Generation.Tests { + [UsesVerify] public class JsonRpcGenerationTests { [Fact] @@ -33,42 +34,7 @@ public interface IExitHandler : IJsonRpcNotificationHandler } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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.Server; -using OmniSharp.Extensions.LanguageServer.Protocol.Test; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class ExitExtensions - { - 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 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 request) => mediator.SendNotification(request); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -112,71 +78,7 @@ public partial record ExecuteCommandParams : IRequest, IWorkDoneProgressPa } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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.Server; -using OmniSharp.Extensions.LanguageServer.Protocol.Test; -using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ - [Serial, Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial interface IExecuteCommandHandler : IJsonRpcRequestHandler, T>, IRegistration - { - } - - [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] - abstract public partial class ExecuteCommandHandlerBase : AbstractHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>, IExecuteCommandHandler - { - } -} -#nullable restore - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class ExecuteCommandExtensions1 - { - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, Task> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, CancellationToken, Task> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, ExecuteCommandCapability, CancellationToken, Task> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static Task ExecuteCommand(this IWorkspaceLanguageClient mediator, ExecuteCommandParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - public static Task ExecuteCommand(this ILanguageClient mediator, ExecuteCommandParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -206,6 +108,7 @@ public interface IExitHandler : IJsonRpcNotificationHandler var a = () => AssertGeneratedAsExpected(source, ""); await a.Should().ThrowAsync().WithMessage("*Could not infer the request router(s)*"); await a.Should().ThrowAsync("cache").WithMessage("*Could not infer the request router(s)*"); + await Verify(GenerateAll(source)); } [Fact] @@ -225,40 +128,7 @@ namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test public interface ICapabilitiesHandler : IJsonRpcNotificationHandler { } }"; - 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; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class CapabilitiesExtensions - { - 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 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 request) => mediator.SendNotification(request); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } @@ -286,41 +156,7 @@ public interface IExitHandler : IJsonRpcNotificationHandler } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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 -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class ExitExtensions - { - 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 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 request) => mediator.SendNotification(request); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -344,73 +180,11 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { [Serial, Method(TextDocumentNames.DidChange, Direction.ClientToServer), GenerateHandlerMethods, GenerateRequestMethods] public interface IDidChangeTextDocumentHandler : IJsonRpcNotificationHandler, - IRegistration + IRegistration { } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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.Server; -using OmniSharp.Extensions.LanguageServer.Protocol.Test; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class DidChangeTextDocumentExtensions - { - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static void DidChangeTextDocument(this ILanguageClient mediator, DidChangeTextDocumentParams request) => mediator.SendNotification(request); - } -#nullable restore -} -"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -440,71 +214,7 @@ public interface IFoldingRangeHandler : IJsonRpcRequestHandler>> handler, RegistrationOptionsDelegate 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, RegistrationOptionsDelegate 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, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeRegistrationOptions, FoldingRangeCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); - } - - public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); - } - - public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, FoldingRangeCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 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 -} -"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -530,69 +240,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Test public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration { } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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.Server; -using OmniSharp.Extensions.LanguageServer.Protocol.Test; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute, Obsolete(""This is obsolete"")] - public static partial class DefinitionExtensions - { - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationOrLocationLinks(value), cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } @@ -619,69 +267,7 @@ namespace Test public interface IDefinitionHandler : IJsonRpcRequestHandler, IRegistration { } }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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.Server; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Test; - -namespace Test -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class DefinitionExtensions - { - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) - { - return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); - } - - public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new LocationOrLocationLinks(value), cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } [Fact] @@ -712,39 +298,7 @@ namespace Test [Serial, Method(GeneralNames.Initialize, Direction.ClientToServer), GenerateHandlerMethods(typeof(ILanguageServerRegistry), MethodName = ""OnLanguageProtocolInitialize""), GenerateRequestMethods(typeof(ITextDocumentLanguageClient), MethodName = ""RequestLanguageProtocolInitialize"")] public interface ILanguageProtocolInitializeHandler : IJsonRpcRequestHandler {} }"; - var expected = @" -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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 -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class LanguageProtocolInitializeExtensions - { - public static ILanguageServerRegistry OnLanguageProtocolInitialize(this ILanguageServerRegistry registry, Func> 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 request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -766,67 +320,7 @@ public class AttachResponse { } [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] public class AttachRequestArguments: IRequest { } }"; - 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.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using System; -using System.Collections.Generic; -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 AttachRequestExtensions - { - 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -848,67 +342,7 @@ public class LaunchResponse { } [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] public class LaunchRequestArguments: IRequest { } }"; - 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.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -#nullable enable -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus -{ - [Method(""launch"", Direction.ClientToServer)] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial interface ILaunchRequestHandler : IJsonRpcRequestHandler where T : LaunchRequestArguments - { - } - - [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] - abstract public partial class LaunchRequestHandlerBase : AbstractHandlers.Request, ILaunchRequestHandler where T : LaunchRequestArguments - { - } - - public partial interface ILaunchRequestHandler : ILaunchRequestHandler - { - } - - [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] - abstract public partial class LaunchRequestHandlerBase : LaunchRequestHandlerBase, ILaunchRequestHandler - { - } -} -#nullable restore - -namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class LaunchRequestExtensions - { - public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""launch"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler(""launch"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) - where T : LaunchRequestArguments => registry.AddHandler(""launch"", RequestHandler.For(handler)); - public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) - where T : LaunchRequestArguments => registry.AddHandler(""launch"", RequestHandler.For(handler)); - public static Task LaunchRequest(this IDebugAdapterClient mediator, LaunchRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -930,67 +364,7 @@ public class AttachResponse { } [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] public class AttachRequestArguments: IRequest { } }"; - 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.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using System; -using System.Collections.Generic; -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 AttachRequestExtensions - { - 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -1012,67 +386,7 @@ public class AttachResponse { } [GenerateHandler(AllowDerivedRequests = true), GenerateHandlerMethods, GenerateRequestMethods] public class AttachRequestArguments: IRequest { } }"; - 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.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.JsonRpc.Generation; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using System; -using System.Collections.Generic; -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 AttachRequestExtensions - { - 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); - } -#nullable restore -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } [Fact] @@ -1104,75 +418,7 @@ public partial class RenameParams : ITextDocumentIdentifierParams, IRequest, 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 -}"; - await AssertGeneratedAsExpected(source, expected); + await Verify(GenerateAll(source)); } } } diff --git a/test/Generation.Tests/LspFeatureTests.cs b/test/Generation.Tests/LspFeatureTests.cs index da2ff3dec..50c7541a5 100644 --- a/test/Generation.Tests/LspFeatureTests.cs +++ b/test/Generation.Tests/LspFeatureTests.cs @@ -4,6 +4,7 @@ namespace Generation.Tests { + [UsesVerify] public class LspFeatureTests { // [Fact(Skip = "for testing"] @@ -11,97 +12,7 @@ public class LspFeatureTests 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.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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 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); + await Verify(GenerationHelpers.GenerateAll(source)); } [Fact] @@ -161,54 +72,19 @@ public partial class UnitTestRegistrationOptions : IWorkDoneProgressOptions } #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 -{ - [RegistrationOptionsKey(""unitTestDiscovery"")] - [RegistrationOptionsConverterAttribute(typeof(UnitTestRegistrationOptionsConverter))] - public partial class UnitTestRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions - { - [Optional] - public bool WorkDoneProgress { get; set; } - - class UnitTestRegistrationOptionsConverter : RegistrationOptionsConverterBase - { - public UnitTestRegistrationOptionsConverter() - { - } - - public override StaticOptions Convert(UnitTestRegistrationOptions source) - { - return new StaticOptions{SupportsDebugging = source.SupportsDebugging, WorkDoneProgress = source.WorkDoneProgress}; - } + await Verify(GenerationHelpers.GenerateAll(source)); } - [RegistrationOptionsKey(""unitTestDiscovery"")] - public partial class StaticOptions : IWorkDoneProgressOptions + [Fact] + public async Task Supports_Generating_Void_Task_Return() { - [Optional] - public bool SupportsDebugging { get; set; } + var source = @" +// ------------------------------------------------------------------------------ +// +// This code was generated a code generator. +// +// ------------------------------------------------------------------------------ - [Optional] - public bool WorkDoneProgress { get; set; } - } - } -} -#nullable restore"; - var expectedStrongTypes = @" using MediatR; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.JsonRpc.Generation; @@ -223,234 +99,531 @@ public partial class StaticOptions : IWorkDoneProgressOptions #nullable enable namespace Lsp.Tests.Integration.Fixtures { - [Parallel, Method(""tests/run"", Direction.ClientToServer)] + [Parallel] + [Method(ClientNames.RegisterCapability, Direction.ServerToClient)] [ - GenerateHandler, - GenerateHandlerMethods(typeof(ILanguageServerRegistry)), - GenerateRequestMethods(typeof(ILanguageClient)) + GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Client"", Name = ""RegisterCapability""), + GenerateHandlerMethods(typeof(ILanguageClientRegistry), + GenerateRequestMethods(typeof(IClientLanguageServer), typeof(ILanguageServer)) ] - [RegistrationOptions(typeof(UnitTestRegistrationOptions)), Capability(typeof(UnitTestCapability))] - public partial class UnitTest : IRequest + public class RegistrationParams : IJsonRpcRequest { - public string Name { get; set; } = null!; + public RegistrationContainer Registrations { 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 + /// + /// General parameters to to regsiter for a capability. + /// + [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] + [GenerateContainer] + public partial class Registration { - public ProgressToken? PartialResultToken { get; set; } = null!; - public ProgressToken? WorkDoneToken { get; set; } = null!; } +} +#nullable restore"; - [CapabilityKey(""workspace"", ""unitTests"")] - public partial class UnitTestCapability : DynamicCapability - { - public string Property { get; set; } = null!; - } + await Verify(GenerationHelpers.GenerateAll(source)); + } - [GenerateRegistrationOptions(""unitTestDiscovery"")] - public partial class UnitTestRegistrationOptions : IWorkDoneProgressOptions - { - [Optional] public bool SupportsDebugging { get; set; } - } -} -#nullable restore -"; - var expectedHandlers = @" -using Lsp.Tests.Integration.Fixtures; + [Fact] + public async Task Supports_Inlay_Hint() + { + var source = @" +using System.Diagnostics; using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; 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.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 System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; -#nullable enable -namespace Lsp.Tests.Integration.Fixtures +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - [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 + namespace Models { - protected DiscoverUnitTestsPartialHandlerBase(System.Guid id, IProgressManager progressManager) : base(progressManager, Container.From) + [Parallel] + [Method(TextDocumentNames.InlayHint, Direction.ClientToServer)] + [ + GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Document"", Name = ""OutlayHints""), + GenerateHandlerMethods, + GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient)) + ] + [RegistrationOptions(typeof(OutlayHintRegistrationOptions)), Capability(typeof(OutlayHintWorkspaceClientCapabilities))] + [Resolver(typeof(OutlayHint))] + public partial record OutlayHintParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, + IRequest { + /// + /// The text document. + /// + public TextDocumentIdentifier TextDocument { get; init; } + + /// + /// The visible document range for which inlay hints should be computed. + /// + public Range Range { get; init; } } - } -} -#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) + /// + /// Outlay hint information. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] + [Parallel] + [Method(TextDocumentNames.InlayHintResolve, Direction.ClientToServer)] + [GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Document"", Name = ""OutlayHintResolve"")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateTypedData] + [GenerateContainer] + [Capability(typeof(OutlayHintWorkspaceClientCapabilities))] + public partial record OutlayHint : ICanBeResolved, IRequest, IDoesNotParticipateInRegistration { - return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + /// + /// The position of this hint. + /// + public Position Position { get; init; } + + /// + /// The label of this hint. A human readable string or an array of + /// OutlayHintLabelPart label parts. + /// + /// *Note* that neither the string nor the label part can be empty. + /// + public StringOrOutlayHintLabelParts Label { get; init; } + + /// + /// The kind of this hint. Can be omitted in which case the client + /// should fall back to a reasonable default. + /// + public OutlayHintKind? Kind { get; init; } + + /// + /// Optional text edits that are performed when accepting this inlay hint. + /// + /// *Note* that edits are expected to change the document so that the inlay + /// hint (or its nearest variant) is now part of the document and the inlay + /// hint itself is now obsolete. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Container? TextEdits { get; init; } + + /// + /// The tooltip text when you hover over this item. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public StringOrMarkupContent? Tooltip { get; init; } + + /// + /// Render padding before the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingLeft { get; init; } + + /// + /// Render padding after the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingRight { get; init; } + + /// + /// A data entry field that is preserved on a document link between a + /// DocumentLinkRequest and a DocumentLinkResolveRequest. + /// + [Optional] + public JToken? Data { get; init; } + + private string DebuggerDisplay => ToString(); } + + public partial class OutlayHintContainer {} + + /// + /// An inlay hint label part allows for interactive and composite labels + /// of inlay hints. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] + public partial record OutlayHintLabelPart + { + /// + /// The value of this label part. + /// + public string Value { get; init; } + + /// + /// The tooltip text when you hover over this label part. Depending on + /// the client capability `inlayHint.resolveSupport` clients might resolve + /// this property late using the resolve request. + /// + [Optional] + public StringOrMarkupContent? Tooltip { get; init; } + + /// + /// An optional source code location that represents this + /// label part. + /// + /// The editor will use this location for the hover and for code navigation + /// features: This part will become a clickable link that resolves to the + /// definition of the symbol at the given location (not necessarily the + /// location itself), it shows the hover that shows at the given location, + /// and it shows a context menu with further code navigation commands. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Location? Location { get; init; } + + /// + /// An optional command for this label part. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Command? Command { get; init; } - public static ILanguageServerRegistry OnDiscoverUnitTests(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) + private string DebuggerDisplay => ToString(); + } + + [JsonConverter(typeof(Converter))] + [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] + public record StringOrOutlayHintLabelParts { - return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + public StringOrOutlayHintLabelParts(string value) => String = value; + + public StringOrOutlayHintLabelParts(IEnumerable inlayHintLabelParts) => OutlayHintLabelParts = new(inlayHintLabelParts); + + public string? String { get; } + public bool HasString => OutlayHintLabelParts is null; + public Container? OutlayHintLabelParts { get; } + public bool HasOutlayHintLabelParts => OutlayHintLabelParts is { }; + + public static implicit operator StringOrOutlayHintLabelParts?(string? value) => value is null ? null : new StringOrOutlayHintLabelParts(value); + + public static implicit operator StringOrOutlayHintLabelParts?(MarkupContent? markupContent) => + markupContent is null ? null : new StringOrOutlayHintLabelParts(markupContent); + + private string DebuggerDisplay => + $""{( HasString ? String : HasOutlayHintLabelParts ? string.Join("", "", OutlayHintLabelParts!.Select(z => z.ToString())) : string.Empty )}""; + + /// + public override string ToString() => DebuggerDisplay; + + internal class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, StringOrOutlayHintLabelParts value, JsonSerializer serializer) + { + if (value.HasString) + { + writer.WriteValue(value.String); + } + else + { + serializer.Serialize(writer, value.OutlayHintLabelParts ?? Array.Empty()); + } + } + + public override StringOrOutlayHintLabelParts ReadJson( + JsonReader reader, Type objectType, StringOrOutlayHintLabelParts existingValue, bool hasExistingValue, JsonSerializer serializer + ) + { + if (reader.TokenType == JsonToken.StartArray) + { + var result = JArray.Load(reader); + return new StringOrOutlayHintLabelParts(result.ToObject>()); + } + + if (reader.TokenType == JsonToken.String) + { + return new StringOrOutlayHintLabelParts(( reader.Value as string )!); + } + + return """"; + } + + public override bool CanRead => true; + } } - public static ILanguageServerRegistry OnDiscoverUnitTests(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate registrationOptions) + /// + /// Outlay hint kinds. + /// + /// @since 3.17.0 + /// + /// + [JsonConverter(typeof(NumberEnumConverter))] + public enum OutlayHintKind { - return registry.AddHandler(""tests/discover"", new LanguageProtocolDelegatingHandlers.Request, UnitTestRegistrationOptions, UnitTestCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + /// + /// An inlay hint that for a type annotation. + /// + Type = 1, + + /// + /// An inlay hint that is for a parameter. + /// + Parameter = 2 } - public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + [GenerateRegistrationOptions(nameof(ServerCapabilities.OutlayHintProvider))] + [RegistrationOptionsConverter(typeof(OutlayHintRegistrationOptionsConverter))] + [RegistrationName(TextDocumentNames.OutlayHint)] + public partial class OutlayHintRegistrationOptions : ITextDocumentRegistrationOptions, IWorkDoneProgressOptions { - return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + /// + /// The server provides support to resolve additional + /// information for a code action. + /// + /// @since 3.16.0 + /// + [Optional] + public bool ResolveProvider { get; set; } + + private class OutlayHintRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public OutlayHintRegistrationOptionsConverter(IHandlersManager handlersManager) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(OutlayHintRegistrationOptions source) + { + return new() + { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(IOutlayHintResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress, + }; + } + } } + } - public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + namespace Client.Capabilities + { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OutlayHint))] + public partial class OutlayHintWorkspaceClientCapabilities : DynamicCapability { - return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + /// + /// Indicates which properties a client can resolve lazily on a inlay + /// hint. + /// + [Optional] + public OutlayHintCapabilityResolveSupport? ResolveSupport { get; set; } } - public static ILanguageServerRegistry ObserveDiscoverUnitTests(this ILanguageServerRegistry registry, Action>, UnitTestCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + /// + /// Indicates which properties a client can resolve lazily on a inlay + /// hint. + /// + public class OutlayHintCapabilityResolveSupport { - return registry.AddHandler(""tests/discover"", _ => new LanguageProtocolDelegatingHandlers.PartialResults, UnitTest, UnitTestRegistrationOptions, UnitTestCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + /// + /// The properties that a client can resolve lazily. + /// + public Container Properties { get; set; } } + } - public static IRequestProgressObservable, Container> RequestDiscoverUnitTests(this ILanguageClient mediator, DiscoverUnitTestsParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, value => new Container(value), cancellationToken); + namespace Document + { } -#nullable restore -}"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expectedOptions); - await GenerationHelpers.AssertGeneratedAsExpected(source, expectedStrongTypes); - await GenerationHelpers.AssertGeneratedAsExpected(source, expectedHandlers); +} +"; + + await Verify(GenerationHelpers.GenerateAll(source)); } [Fact] - public async Task Supports_Generating_Void_Task_Return() + public async Task Supports_Nullable_Params_With_Typed_Data() { var source = @" -// ------------------------------------------------------------------------------ -// -// This code was generated a code generator. -// -// ------------------------------------------------------------------------------ - +using System.Diagnostics; +using System.Linq; using MediatR; +using Newtonsoft.Json.Linq; 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.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; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; -#nullable enable -namespace Lsp.Tests.Integration.Fixtures +// ReSharper disable once CheckNamespace +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test { - [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 + namespace Models { - public RegistrationContainer Registrations { get; set; } = null!; - } + [Parallel] + [Method(TextDocumentNames.CodeLens, Direction.ClientToServer)] + [GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Document.Test"")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [RegistrationOptions(typeof(SubLensRegistrationOptions))] + [Capability(typeof(SubLensCapability))] + [Resolver(typeof(SubLens))] + public partial record SubLensParams : ITextDocumentIdentifierParams, IWorkDoneProgressParams, IPartialItemsRequest + { + /// + /// The document to request code lens for. + /// + public TextDocumentIdentifier TextDocument { get; init; } = null!; + } - /// - /// General parameters to to regsiter for a capability. - /// - [DebuggerDisplay(""{"" + nameof(DebuggerDisplay) + "",nq}"")] - [GenerateContainer] - public partial class Registration - { - } -} -#nullable restore"; + public partial class SubLensContainer {} + + /// + /// 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.Test"", Name = ""SubLensResolve"")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateTypedData] + [GenerateContainer] + [Capability(typeof(SubLensCapability))] + public partial record SubLens : IRequest, ICanBeResolved, IDoesNotParticipateInRegistration + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; init; } = null!; + + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command { get; init; } - var expectedHandlers = @" -using Lsp.Tests.Integration.Fixtures; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using OmniSharp.Extensions.DebugAdapter.Protocol; -using OmniSharp.Extensions.DebugAdapter.Protocol.Events; -using OmniSharp.Extensions.DebugAdapter.Protocol.Models; -using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; -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; + /// + /// 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; init; } -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client -{ - [Parallel, Method(ClientNames.RegisterCapability, Direction.ServerToClient)] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial interface IRegisterCapabilityHandler : IJsonRpcRequestHandler - { + private string DebuggerDisplay => $""{Range}{( Command != null ? $"" {Command}"" : """" )}""; + + /// + public override string ToString() + { + return DebuggerDisplay; + } + } + + [GenerateRegistrationOptions(nameof(ServerCapabilities.SubLensProvider))] + [RegistrationOptionsConverter(typeof(SubLensRegistrationOptionsConverter))] + [RegistrationName(TextDocumentNames.CodeLens)] + public partial class SubLensRegistrationOptions : IWorkDoneProgressOptions, ITextDocumentRegistrationOptions + { + /// + /// Code lens has a resolve provider as well. + /// + [Optional] + public bool ResolveProvider { get; set; } + + private class SubLensRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + private readonly IHandlersManager _handlersManager; + + public SubLensRegistrationOptionsConverter(IHandlersManager handlersManager) + { + _handlersManager = handlersManager; + } + + public override StaticOptions Convert(SubLensRegistrationOptions source) + { + return new() + { + ResolveProvider = source.ResolveProvider || _handlersManager.Descriptors.Any(z => z.HandlerType == typeof(ISubLensResolveHandler)), + WorkDoneProgress = source.WorkDoneProgress + }; + } + } + } + + [Parallel] + [Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] + [GenerateHandler(""OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Test"")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(IWorkspaceLanguageServer), typeof(ILanguageServer))] + [Capability(typeof(SubLensWorkspaceClientCapabilities))] + public partial record SubLensRefreshParams : IRequest; } - [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] - abstract public partial class RegisterCapabilityHandlerBase : AbstractHandlers.Request, IRegisterCapabilityHandler + namespace Client.Capabilities { + [CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeLens))] + public partial class SubLensCapability : DynamicCapability + { + } + + /// + /// Capabilities specific to the code lens requests scoped to the + /// workspace. + /// + /// @since 3.16.0. + /// + [CapabilityKey(nameof(ClientCapabilities.Workspace), nameof(WorkspaceClientCapabilities.CodeLens))] + public class SubLensWorkspaceClientCapabilities : 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; } + } } -} -#nullable restore -namespace OmniSharp.Extensions.LanguageServer.Protocol.Client -{ -#nullable enable - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public static partial class RegisterCapabilityExtensions + namespace Document { - public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(HandlerAdapter.Adapt(handler))); - public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(HandlerAdapter.Adapt(handler))); } -#nullable restore -}"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expectedHandlers); +} +"; + + await Verify(GenerationHelpers.GenerateAll(source)); } } } diff --git a/test/Generation.Tests/ModuleInitializer.cs b/test/Generation.Tests/ModuleInitializer.cs new file mode 100644 index 000000000..67d97e1a7 --- /dev/null +++ b/test/Generation.Tests/ModuleInitializer.cs @@ -0,0 +1,34 @@ +using System.Runtime.CompilerServices; +using DiffEngine; +using Microsoft.CodeAnalysis; + +public static class ModuleInitializer +{ + [ModuleInitializer] + public static void Init() + { + VerifySourceGenerators.Enable(); + VerifierSettings.AddExtraSettings( + settings => { settings.Converters.Add(new SyntaxTreeConverter()); } + ); + DiffRunner.Disabled = true; + VerifierSettings.DerivePathInfo( + static (sourceFile, directory, type, method) => + { + static string GetTypeName(Type type) => type.IsNested ? $"{type.ReflectedType!.Name}.{type.Name}" : type.Name; + var typeName = GetTypeName(type); + return new(Path.Combine(Path.GetDirectoryName(sourceFile)!, "snapshots"), typeName, method.Name); + } + ); + } + + class SyntaxTreeConverter : + WriteOnlyJsonConverter + { + public override void Write(VerifyJsonWriter writer, SyntaxTree value) => + writer.WriteValue( + $@"//HintName: {value.FilePath.Replace("\\", "/", StringComparison.OrdinalIgnoreCase)} +{value.GetText()}" + ); + } +} diff --git a/test/Generation.Tests/TypedCanBeResolvedTests.cs b/test/Generation.Tests/TypedCanBeResolvedTests.cs index e3512ef7e..2d0f91e00 100644 --- a/test/Generation.Tests/TypedCanBeResolvedTests.cs +++ b/test/Generation.Tests/TypedCanBeResolvedTests.cs @@ -4,6 +4,7 @@ namespace Generation.Tests { + [UsesVerify] public class TypedCanBeResolvedTests { [Fact] @@ -59,190 +60,7 @@ public partial record CodeLens : IRequest, ICanBeResolved } #nullable restore"; - var expected = @" -using System; -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; -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 System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Immutable; -using System.Linq; - -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ - public partial record CodeLens - { - public CodeLens WithData(TData data) - where TData : class?, IHandlerIdentity? - { - return new CodeLens{Range = Range, Command = Command, Data = data}; - } - - [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(""item"")] - public static CodeLens? From(CodeLens? item) - where T : class?, IHandlerIdentity? => 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}"")] - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial record CodeLens : ICanBeResolved where T : class?, IHandlerIdentity? - { - /// - /// The range in which this code lens is valid. Should only span a single line. - /// - public Range Range { get; init; } - - [Optional] - public Command? Command { get; init; } - - /// - /// 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 => this.GetRawData()!; init => this.SetRawData(value); } - - private string DebuggerDisplay => $""{Range}{(Command != null ? $"" {Command}"" : """")}""; - public override string ToString() => DebuggerDisplay; - public CodeLens WithData(TData data) - where TData : class?, IHandlerIdentity? - { - return new CodeLens{Range = Range, Command = Command, Data = data}; - } - - JToken? ICanBeResolved.Data { get; init; } - - private JToken? JData { get => this.GetRawData(); init => this.SetRawData(value); } - - public static implicit operator CodeLens(CodeLens value) => new CodeLens{Range = value.Range, Command = value.Command, JData = 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 = value.JData}, - _ => 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 : class?, IHandlerIdentity? - { - 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 - }; - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } [Fact] @@ -298,114 +116,7 @@ public partial class CodeLens : IRequest, ICanBeResolved } #nullable restore"; - var expected = @"using System; -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; -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 System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Immutable; -using System.Linq; - -#nullable enable -namespace OmniSharp.Extensions.LanguageServer.Protocol.Test -{ - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] - public partial class CodeLensContainer : ContainerBase - { - 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 - }; - } -} -#nullable restore"; - await GenerationHelpers.AssertGeneratedAsExpected(source, expected); + await Verify(GenerationHelpers.GenerateAll(source)); } } } diff --git a/test/Generation.Tests/snapshots/AutoImplementParamsGeneratorTests.Auto_Magically_Implements_Properties.verified.cs b/test/Generation.Tests/snapshots/AutoImplementParamsGeneratorTests.Auto_Magically_Implements_Properties.verified.cs new file mode 100644 index 000000000..e3807daac --- /dev/null +++ b/test/Generation.Tests/snapshots/AutoImplementParamsGeneratorTests.Auto_Magically_Implements_Properties.verified.cs @@ -0,0 +1,23 @@ +//HintName: Test0_DeclarationParams.cs +#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 Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace Test +{ + public partial class DeclarationParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + + [Optional] + public ProgressToken? PartialResultToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/EnumLikeStringGeneratorTests.Auto_Magically_Implements_IEnumLikeString.verified.cs b/test/Generation.Tests/snapshots/EnumLikeStringGeneratorTests.Auto_Magically_Implements_IEnumLikeString.verified.cs new file mode 100644 index 000000000..106762da2 --- /dev/null +++ b/test/Generation.Tests/snapshots/EnumLikeStringGeneratorTests.Auto_Magically_Implements_IEnumLikeString.verified.cs @@ -0,0 +1,36 @@ +//HintName: Test0_ThreadEventReason.cs +#nullable enable +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Serialization.Converters; + +namespace Test +{ + [JsonConverter(typeof(EnumLikeStringConverter))] + [DebuggerDisplay("{_value}")] + public readonly partial struct ThreadEventReason : IEquatable, IEquatable, IEnumLikeString + { + private static readonly Lazy> _defaults = new Lazy>(() => + { + return new ThreadEventReason[]{Started, Exited}; + }); + public static IEnumerable Defaults => _defaults.Value; + private readonly string _value; + public ThreadEventReason(string type) => _value = type; + public static implicit operator ThreadEventReason(string kind) => new ThreadEventReason(kind); + public static implicit operator string (ThreadEventReason kind) => kind._value; + public override string ToString() => _value; + public bool Equals(ThreadEventReason other) => _value == other._value; + public bool Equals(string other) => _value == other; + public override bool Equals(object obj) => obj is string s && Equals(s) || obj is ThreadEventReason other && Equals(other); + public override int GetHashCode() => _value.GetHashCode(); + public static bool operator ==(ThreadEventReason left, ThreadEventReason right) => left.Equals(right); + public static bool operator !=(ThreadEventReason left, ThreadEventReason right) => !left.Equals(right); + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.00AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.00AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..f95248a5d --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.00AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; + +[assembly: AssemblyRegistrationOptions(typeof(CodeActionRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.01CodeActionRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.01CodeActionRegistrationOptions.verified.cs new file mode 100644 index 000000000..62d94c13b --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options.01CodeActionRegistrationOptions.verified.cs @@ -0,0 +1,68 @@ +//HintName: CodeActionRegistrationOptions.cs +using System; +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; +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; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] + [RegistrationOptionsConverterAttribute(typeof(CodeActionRegistrationOptionsConverter))] + public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.ITextDocumentRegistrationOptions, OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions + { + public TextDocumentSelector? DocumentSelector { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + + class CodeActionRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public CodeActionRegistrationOptionsConverter() + { + } + + public override StaticOptions Convert(CodeActionRegistrationOptions source) + { + return new StaticOptions{CodeActionKinds = source.CodeActionKinds, ResolveProvider = source.ResolveProvider, WorkDoneProgress = source.WorkDoneProgress}; + } + } + + [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] + public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.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 { 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; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.00AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.00AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..f95248a5d --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.00AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; + +[assembly: AssemblyRegistrationOptions(typeof(CodeActionRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.01CodeActionRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.01CodeActionRegistrationOptions.verified.cs new file mode 100644 index 000000000..5a0e34232 --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_Registration_Options_With_Converters.01CodeActionRegistrationOptions.verified.cs @@ -0,0 +1,55 @@ +//HintName: CodeActionRegistrationOptions.cs +using System; +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; +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; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] + public partial class CodeActionRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + public TextDocumentSelector? DocumentSelector { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + + [RegistrationOptionsKey(nameof(ServerCapabilities.CodeActionProvider))] + public partial class StaticOptions : 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 { 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; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.00AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.00AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..0980e8e3b --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.00AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using Test; + +[assembly: AssemblyRegistrationOptions(typeof(WorkspaceSymbolRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.01WorkspaceSymbolRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.01WorkspaceSymbolRegistrationOptions.verified.cs new file mode 100644 index 000000000..95ed84ad2 --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options.01WorkspaceSymbolRegistrationOptions.verified.cs @@ -0,0 +1,37 @@ +//HintName: WorkspaceSymbolRegistrationOptions.cs +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 +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + [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() + { + } + + public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) + { + return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; + } + } + + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class StaticOptions : OmniSharp.Extensions.LanguageServer.Protocol.Models.IWorkDoneProgressOptions + { + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.00AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.00AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..0980e8e3b --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.00AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using Test; + +[assembly: AssemblyRegistrationOptions(typeof(WorkspaceSymbolRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.01WorkspaceSymbolRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.01WorkspaceSymbolRegistrationOptions.verified.cs new file mode 100644 index 000000000..6d824bc71 --- /dev/null +++ b/test/Generation.Tests/snapshots/GeneratedRegistrationOptionsTests.Supports_Generating_Strongly_Typed_WorkDone_Registration_Options_Interface.01WorkspaceSymbolRegistrationOptions.verified.cs @@ -0,0 +1,38 @@ +//HintName: WorkspaceSymbolRegistrationOptions.cs +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 +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + [RegistrationOptionsConverterAttribute(typeof(WorkspaceSymbolRegistrationOptionsConverter))] + public partial class WorkspaceSymbolRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + [Optional] + public bool WorkDoneProgress { get; set; } + + class WorkspaceSymbolRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public WorkspaceSymbolRegistrationOptionsConverter() + { + } + + public override StaticOptions Convert(WorkspaceSymbolRegistrationOptions source) + { + return new StaticOptions{WorkDoneProgress = source.WorkDoneProgress}; + } + } + + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class StaticOptions : IWorkDoneProgressOptions + { + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.00.verified.txt b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.00.verified.txt new file mode 100644 index 000000000..d9ba20eca --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.00.verified.txt @@ -0,0 +1,30 @@ +{ + Diagnostics: [ + { + Id: JRPC1003, + Title: Cannot infer request router(s), + Severity: Error, + WarningLevel: 0, + Location: Test0.cs: (15,66)-(15,88), + Description: , + HelpLink: , + MessageFormat: Could not infer the request router(s) to use, please specify the target interface(s)., + Message: Could not infer the request router(s) to use, please specify the target interface(s)., + Category: JsonRPC, + CustomTags: [] + }, + { + Id: JRPC1003, + Title: Cannot infer request router(s), + Severity: Error, + WarningLevel: 0, + Location: Test0.cs: (15,90)-(15,112), + Description: , + HelpLink: , + MessageFormat: Could not infer the request router(s) to use, please specify the target interface(s)., + Message: Could not infer the request router(s) to use, please specify the target interface(s)., + Category: JsonRPC, + CustomTags: [] + } + ] +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.01AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.01AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..fb24aabc1 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Should_Report_Diagnostic_If_Missing_Information.01AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Test.IExitHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.00AttachRequestArguments.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.00AttachRequestArguments.verified.cs new file mode 100644 index 000000000..f357428f4 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.00AttachRequestArguments.verified.cs @@ -0,0 +1,60 @@ +//HintName: AttachRequestArguments.cs +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.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System; +using System.Collections.Generic; +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 AttachRequestExtensions + { + 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.01GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.01GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..98d717787 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests.01GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.DebugAdapter.Protocol.Bogus.IAttachRequestHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.00GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.00GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..afa35602e --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.00GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.DebugAdapter.Protocol.Bogus.ILaunchRequestHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.01LaunchRequestArguments.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.01LaunchRequestArguments.verified.cs new file mode 100644 index 000000000..3063989f1 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Derived_Requests_Nullable.01LaunchRequestArguments.verified.cs @@ -0,0 +1,60 @@ +//HintName: LaunchRequestArguments.cs +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.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus +{ + [Method("launch", Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface ILaunchRequestHandler : IJsonRpcRequestHandler where T : LaunchRequestArguments + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class LaunchRequestHandlerBase : AbstractHandlers.Request, ILaunchRequestHandler where T : LaunchRequestArguments + { + } + + public partial interface ILaunchRequestHandler : ILaunchRequestHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class LaunchRequestHandlerBase : LaunchRequestHandlerBase, ILaunchRequestHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Bogus +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class LaunchRequestExtensions + { + public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler("launch", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) => registry.AddHandler("launch", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : LaunchRequestArguments => registry.AddHandler("launch", RequestHandler.For(handler)); + public static IDebugAdapterServerRegistry OnLaunchRequest(this IDebugAdapterServerRegistry registry, Func> handler) + where T : LaunchRequestArguments => registry.AddHandler("launch", RequestHandler.For(handler)); + public static Task LaunchRequest(this IDebugAdapterClient mediator, LaunchRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.00AttachRequestArguments.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.00AttachRequestArguments.verified.cs new file mode 100644 index 000000000..f357428f4 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.00AttachRequestArguments.verified.cs @@ -0,0 +1,60 @@ +//HintName: AttachRequestArguments.cs +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.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System; +using System.Collections.Generic; +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 AttachRequestExtensions + { + 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.01GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.01GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..98d717787 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allow_Generic_Types.01GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.DebugAdapter.Protocol.Bogus.IAttachRequestHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.00AttachRequestArguments.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.00AttachRequestArguments.verified.cs new file mode 100644 index 000000000..4c980a0dc --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.00AttachRequestArguments.verified.cs @@ -0,0 +1,60 @@ +//HintName: AttachRequestArguments.cs +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.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System; +using System.Collections.Generic; +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 AttachRequestExtensions + { + 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 AttachRequest(this IDebugAdapterClient mediator, AttachRequestArguments request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.01GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.01GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..98d717787 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Allows_Nullable_Responses.01GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.DebugAdapter.Protocol.Bogus.IAttachRequestHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.00AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.00AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..56b28ef07 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.00AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Test.ILanguageProtocolInitializeHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.01ILanguageProtocolInitializeHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.01ILanguageProtocolInitializeHandler.verified.cs new file mode 100644 index 000000000..9baa8fc4c --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Custom_Method_Names.01ILanguageProtocolInitializeHandler.verified.cs @@ -0,0 +1,32 @@ +//HintName: ILanguageProtocolInitializeHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class LanguageProtocolInitializeExtensions + { + public static ILanguageServerRegistry OnLanguageProtocolInitialize(this ILanguageServerRegistry registry, Func> 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 request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.00Test0_ExecuteCommandParams1.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.00Test0_ExecuteCommandParams1.verified.cs new file mode 100644 index 000000000..c029a1565 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.00Test0_ExecuteCommandParams1.verified.cs @@ -0,0 +1,26 @@ +//HintName: Test0_ExecuteCommandParams1.cs +#nullable enable +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; +using Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + public partial record ExecuteCommandParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.01ExecuteCommandParams1.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.01ExecuteCommandParams1.verified.cs new file mode 100644 index 000000000..fb306e58b --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.01ExecuteCommandParams1.verified.cs @@ -0,0 +1,64 @@ +//HintName: ExecuteCommandParams1.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace +{ + [Serial, Method(WorkspaceNames.ExecuteCommand, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IExecuteCommandHandler : IJsonRpcRequestHandler, T>, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class ExecuteCommandHandlerBase : AbstractHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>, IExecuteCommandHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class ExecuteCommandExtensions1 + { + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, Task> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, CancellationToken, Task> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnExecuteCommand(this ILanguageServerRegistry registry, Func, ExecuteCommandCapability, CancellationToken, Task> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(WorkspaceNames.ExecuteCommand, new LanguageProtocolDelegatingHandlers.Request, T, ExecuteCommandRegistrationOptions, ExecuteCommandCapability>(HandlerAdapter.Adapt, T>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static Task ExecuteCommand(this IWorkspaceLanguageClient mediator, ExecuteCommandParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task ExecuteCommand(this ILanguageClient mediator, ExecuteCommandParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.02GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.02GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..77e84be8c --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Generic_Response_Types.02GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Workspace.IExecuteCommandHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.00AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.00AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..d39145513 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.00AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test.ICapabilitiesHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.01ICapabilitiesHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.01ICapabilitiesHandler.verified.cs new file mode 100644 index 000000000..047814fe1 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_CapabilitiesHandler.01ICapabilitiesHandler.verified.cs @@ -0,0 +1,33 @@ +//HintName: ICapabilitiesHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Client; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.DebugAdapter.Protocol.Server; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.DebugAdapter.Protocol.Events.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class CapabilitiesExtensions + { + 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 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 request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.00.verified.txt b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.00.verified.txt new file mode 100644 index 000000000..a8e983cca --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.00.verified.txt @@ -0,0 +1,17 @@ +{ + Diagnostics: [ + { + Id: JRPC1001, + Title: No Response Router Provided, + Severity: Info, + WarningLevel: 1, + Location: Test0.cs: (17,21)-(17,50), + Description: , + HelpLink: , + MessageFormat: No Response Router Provided for handler {0}, defaulting to {1}., + Message: No Response Router Provided for handler {0}, defaulting to {1}., + Category: JsonRPC, + CustomTags: [] + } + ] +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.01AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.01AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..8955cd33f --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.01AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.IDidChangeTextDocumentHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.02IDidChangeTextDocumentHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.02IDidChangeTextDocumentHandler.verified.cs new file mode 100644 index 000000000..7ac848a1a --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_DidChangeTextHandler.02IDidChangeTextDocumentHandler.verified.cs @@ -0,0 +1,61 @@ +//HintName: IDidChangeTextDocumentHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class DidChangeTextDocumentExtensions + { + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDidChangeTextDocument(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.DidChange, new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static void DidChangeTextDocument(this ILanguageClient mediator, DidChangeTextDocumentParams request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.00.verified.txt b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.00.verified.txt new file mode 100644 index 000000000..4b754600e --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.00.verified.txt @@ -0,0 +1,17 @@ +{ + Diagnostics: [ + { + Id: JRPC1001, + Title: No Response Router Provided, + Severity: Info, + WarningLevel: 1, + Location: Test0.cs: (16,21)-(16,33), + Description: , + HelpLink: , + MessageFormat: No Response Router Provided for handler {0}, defaulting to {1}., + Message: No Response Router Provided for handler {0}, defaulting to {1}., + Category: JsonRPC, + CustomTags: [] + } + ] +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.01AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.01AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..9fdf26ab7 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.01AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.IExitHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.02IExitHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.02IExitHandler.verified.cs new file mode 100644 index 000000000..54465bacd --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_ExitHandler.02IExitHandler.verified.cs @@ -0,0 +1,35 @@ +//HintName: IExitHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class ExitExtensions + { + 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 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 request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.00AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.00AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..f6973f906 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.00AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.IFoldingRangeHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.01IFoldingRangeHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.01IFoldingRangeHandler.verified.cs new file mode 100644 index 000000000..2d2b401f0 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_And_Infers_Direction_FoldingRangeHandler.01IFoldingRangeHandler.verified.cs @@ -0,0 +1,63 @@ +//HintName: IFoldingRangeHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class FoldingRangeExtensions + { + public static ILanguageServerRegistry OnFoldingRange(this ILanguageServerRegistry registry, Func>> handler, RegistrationOptionsDelegate 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, RegistrationOptionsDelegate 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, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.FoldingRange, new LanguageProtocolDelegatingHandlers.Request, FoldingRangeRegistrationOptions, FoldingRangeCapability>(HandlerAdapter.Adapt>(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.FoldingRange, _ => new LanguageProtocolDelegatingHandlers.PartialResults, FoldingRange, FoldingRangeRegistrationOptions, FoldingRangeCapability>(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), Container.From)); + } + + public static ILanguageServerRegistry ObserveFoldingRange(this ILanguageServerRegistry registry, Action>, FoldingRangeCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, Container.From, cancellationToken); + public static IRequestProgressObservable, Container> RequestFoldingRange(this ILanguageClient mediator, FoldingRangeRequestParam request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, Container.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.00AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.00AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..fb24aabc1 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.00AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Test.IExitHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.01IExitHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.01IExitHandler.verified.cs new file mode 100644 index 000000000..e49ba5dff --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Notifications_ExitHandler.01IExitHandler.verified.cs @@ -0,0 +1,34 @@ +//HintName: IExitHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class ExitExtensions + { + 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 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 request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.00AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.00AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..c9c8868a1 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.00AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Test.IDefinitionHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.01IDefinitionHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.01IDefinitionHandler.verified.cs new file mode 100644 index 000000000..4d353e742 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests.01IDefinitionHandler.verified.cs @@ -0,0 +1,62 @@ +//HintName: IDefinitionHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Test; + +namespace Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class DefinitionExtensions + { + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, LocationOrLocationLinks.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.00.verified.txt b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.00.verified.txt new file mode 100644 index 000000000..a88f4f32a --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.00.verified.txt @@ -0,0 +1,17 @@ +{ + Diagnostics: [ + { + Id: JRPC1001, + Title: No Response Router Provided, + Severity: Info, + WarningLevel: 1, + Location: Test0.cs: (17,21)-(17,39), + Description: , + HelpLink: , + MessageFormat: No Response Router Provided for handler {0}, defaulting to {1}., + Message: No Response Router Provided for handler {0}, defaulting to {1}., + Category: JsonRPC, + CustomTags: [] + } + ] +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.01AssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.01AssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..b16bc991b --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.01AssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: AssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.IDefinitionHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.02IDefinitionHandler.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.02IDefinitionHandler.verified.cs new file mode 100644 index 000000000..83fb31b79 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Generating_Requests_And_Infers_Direction.02IDefinitionHandler.verified.cs @@ -0,0 +1,62 @@ +//HintName: IDefinitionHandler.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Test; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute, Obsolete("This is obsolete")] + public static partial class DefinitionExtensions + { + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnDefinition(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.Definition, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), LocationOrLocationLinks.From)); + } + + public static ILanguageServerRegistry ObserveDefinition(this ILanguageServerRegistry registry, Action>, DefinitionCapability, CancellationToken> handler, RegistrationOptionsDelegate 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 request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, LocationOrLocationLinks.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.00GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.00GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..c6b18d692 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.00GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Bogus.Handlers.IRenameHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.01RenameParams.verified.cs b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.01RenameParams.verified.cs new file mode 100644 index 000000000..ffd2f3504 --- /dev/null +++ b/test/Generation.Tests/snapshots/JsonRpcGenerationTests.Supports_Params_Type_As_Source.01RenameParams.verified.cs @@ -0,0 +1,68 @@ +//HintName: RenameParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.00AssemblyCapabilityKeys.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.00AssemblyCapabilityKeys.verified.cs new file mode 100644 index 000000000..1a13aaaf2 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.00AssemblyCapabilityKeys.verified.cs @@ -0,0 +1,13 @@ +//HintName: AssemblyCapabilityKeys.cs +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; + +[assembly: AssemblyCapabilityKey(typeof(Lsp.Tests.Integration.Fixtures.UnitTestCapability), "workspace", "unitTests")] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.01DiscoverUnitTestsParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.01DiscoverUnitTestsParams.verified.cs new file mode 100644 index 000000000..f8b259c71 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.01DiscoverUnitTestsParams.verified.cs @@ -0,0 +1,87 @@ +//HintName: DiscoverUnitTestsParams.cs +using Lsp.Tests.Integration.Fixtures; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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, Container.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.02GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.02GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..c8f044efb --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.02GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Lsp.Tests.Integration.Fixtures.IUnitTestHandler), typeof(Lsp.Tests.Integration.Fixtures.IDiscoverUnitTestsHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.03UnitTest.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.03UnitTest.verified.cs new file mode 100644 index 000000000..fc42c89cb --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.03UnitTest.verified.cs @@ -0,0 +1,78 @@ +//HintName: UnitTest.cs +using Lsp.Tests.Integration.Fixtures; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 Lsp.Tests.Integration.Fixtures +{ + [Parallel, Method("tests/run", Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IUnitTestHandler : IJsonRpcNotificationHandler, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class UnitTestHandlerBase : AbstractHandlers.Notification, IUnitTestHandler + { + } +} +#nullable restore + +namespace Lsp.Tests.Integration.Fixtures +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class UnitTestExtensions + { + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Action handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnUnitTest(this ILanguageServerRegistry registry, Func handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler("tests/run", new LanguageProtocolDelegatingHandlers.Notification(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static void SendUnitTest(this ILanguageClient mediator, UnitTest request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.04AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.04AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..8bd5dc965 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.04AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using Lsp.Tests.Integration.Fixtures; +using OmniSharp.Extensions.LanguageServer.Protocol; + +[assembly: AssemblyRegistrationOptions(typeof(UnitTestRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.05UnitTestRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.05UnitTestRegistrationOptions.verified.cs new file mode 100644 index 000000000..5604552b9 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Custom_Language_Extensions.05UnitTestRegistrationOptions.verified.cs @@ -0,0 +1,47 @@ +//HintName: UnitTestRegistrationOptions.cs +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 +{ + [RegistrationOptionsKey("unitTestDiscovery")] + [RegistrationOptionsConverterAttribute(typeof(UnitTestRegistrationOptionsConverter))] + public partial class UnitTestRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + [Optional] + public bool WorkDoneProgress { get; set; } + + class UnitTestRegistrationOptionsConverter : RegistrationOptionsConverterBase + { + public UnitTestRegistrationOptionsConverter() + { + } + + public override StaticOptions Convert(UnitTestRegistrationOptions source) + { + return new StaticOptions{SupportsDebugging = source.SupportsDebugging, WorkDoneProgress = source.WorkDoneProgress}; + } + } + + [RegistrationOptionsKey("unitTestDiscovery")] + public partial class StaticOptions : IWorkDoneProgressOptions + { + [Optional] + public bool SupportsDebugging { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.00GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.00GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..4541b31e9 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.00GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Client.IRegisterCapabilityHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.01RegistrationParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.01RegistrationParams.verified.cs new file mode 100644 index 000000000..735e6c6cc --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.01RegistrationParams.verified.cs @@ -0,0 +1,49 @@ +//HintName: RegistrationParams.cs +using Lsp.Tests.Integration.Fixtures; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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(HandlerAdapter.Adapt(handler))); + public static ILanguageClientRegistry OnRegisterCapability(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(ClientNames.RegisterCapability, new DelegatingHandlers.Request(HandlerAdapter.Adapt(handler))); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.02RegistrationContainer.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.02RegistrationContainer.verified.cs new file mode 100644 index 000000000..1b270e475 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Generating_Void_Task_Return.02RegistrationContainer.verified.cs @@ -0,0 +1,108 @@ +//HintName: RegistrationContainer.cs +// ------------------------------------------------------------------------------ +// +// 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; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace Lsp.Tests.Integration.Fixtures +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class RegistrationContainer : ContainerBase + { + public RegistrationContainer() : this(Enumerable.Empty()) + { + } + + public RegistrationContainer(IEnumerable items) : base(items) + { + } + + public RegistrationContainer(params Registration[] items) : base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(IEnumerable? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator RegistrationContainer? (Registration[] items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(params Registration[] items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator RegistrationContainer? (Collection? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(Collection? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator RegistrationContainer? (List? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(List? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator RegistrationContainer? (in ImmutableArray? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(in ImmutableArray? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator RegistrationContainer? (ImmutableList? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static RegistrationContainer? From(ImmutableList? items) => items switch + { + not null => new RegistrationContainer(items), + _ => null + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.00AssemblyCapabilityKeys.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.00AssemblyCapabilityKeys.verified.cs new file mode 100644 index 000000000..0f2104845 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.00AssemblyCapabilityKeys.verified.cs @@ -0,0 +1,18 @@ +//HintName: AssemblyCapabilityKeys.cs +using MediatR; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +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.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; +using System.Diagnostics; + +[assembly: AssemblyCapabilityKey(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.Client.Capabilities.OutlayHintWorkspaceClientCapabilities), nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.OutlayHint))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.01Test0_OutlayHintParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.01Test0_OutlayHintParams.verified.cs new file mode 100644 index 000000000..a2a33f902 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.01Test0_OutlayHintParams.verified.cs @@ -0,0 +1,31 @@ +//HintName: Test0_OutlayHintParams.cs +#nullable enable +using System.Diagnostics; +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.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; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + public partial record OutlayHintParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.02GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.02GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..71e76711d --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.02GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Document.IOutlayHintsHandler), typeof(OmniSharp.Extensions.LanguageServer.Protocol.Document.IOutlayHintResolveHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.02Test0_OutlayHintParams1.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.02Test0_OutlayHintParams1.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.03GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.03GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.03OutlayHint.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.03OutlayHint.verified.cs new file mode 100644 index 000000000..578724f25 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.03OutlayHint.verified.cs @@ -0,0 +1,70 @@ +//HintName: OutlayHint.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +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; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Test.Models; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ + [Parallel, Method(TextDocumentNames.InlayHintResolve, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IOutlayHintResolveHandler : IJsonRpcRequestHandler, IDoesNotParticipateInRegistration, ICapability, ICanBeIdentifiedHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class OutlayHintResolveHandlerBase : AbstractHandlers.RequestCapability, IOutlayHintResolveHandler + { + protected OutlayHintResolveHandlerBase(System.Guid id) : base() + { + _id = id; + } + + protected OutlayHintResolveHandlerBase() : this(Guid.NewGuid()) + { + } + + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class OutlayHintResolveExtensions + { + public static ILanguageServerRegistry OnOutlayHintResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.InlayHintResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnOutlayHintResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.InlayHintResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnOutlayHintResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.InlayHintResolve, new LanguageProtocolDelegatingHandlers.RequestCapability(HandlerAdapter.Adapt(handler))); + public static Task ResolveOutlayHint(this ITextDocumentLanguageClient mediator, OutlayHint request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task ResolveOutlayHint(this ILanguageClient mediator, OutlayHint request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.04OutlayHint.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.04OutlayHint.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.04OutlayHintParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.04OutlayHintParams.verified.cs new file mode 100644 index 000000000..81e903049 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.04OutlayHintParams.verified.cs @@ -0,0 +1,152 @@ +//HintName: OutlayHintParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +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; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Test.Models; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ + [Parallel, Method(TextDocumentNames.InlayHint, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IOutlayHintsHandler : IJsonRpcRequestHandler, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class OutlayHintsHandlerBase : AbstractHandlers.Request, IOutlayHintsHandler, IOutlayHintResolveHandler + { + protected OutlayHintsHandlerBase(System.Guid id) : base() + { + _id = id; + } + + protected OutlayHintsHandlerBase() : this(Guid.NewGuid()) + { + } + + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + public abstract Task Handle(OutlayHint request, CancellationToken cancellationToken); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class OutlayHintsHandlerBase : OutlayHintsHandlerBase where T : class?, IHandlerIdentity? + { + protected OutlayHintsHandlerBase(Guid id) : base(id) + { + } + + protected OutlayHintsHandlerBase() : this(Guid.NewGuid()) + { + } + + public sealed override async Task Handle(OutlayHintParams request, CancellationToken cancellationToken) => await HandleParams(request, cancellationToken).ConfigureAwait(false); + public sealed override async Task Handle(OutlayHint request, CancellationToken cancellationToken) => await HandleResolve(request, cancellationToken).ConfigureAwait(false); + protected abstract Task> HandleParams(OutlayHintParams request, CancellationToken cancellationToken); + protected abstract Task> HandleResolve(OutlayHint request, CancellationToken cancellationToken); + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class OutlayHintsExtensions + { + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.InlayHintResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.InlayHintResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.InlayHint, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.InlayHintResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func?>> handler, Func, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingOutlayHintsHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, OutlayHint>(resolveHandler))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func?>> handler, Func, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingOutlayHintsHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, OutlayHint>(resolveHandler))); + } + + public static ILanguageServerRegistry OnOutlayHints(this ILanguageServerRegistry registry, Func?>> handler, Func, OutlayHintWorkspaceClientCapabilities, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingOutlayHintsHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, OutlayHint>(resolveHandler))); + } + + public static Task RequestOutlayHints(this ITextDocumentLanguageClient mediator, OutlayHintParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task RequestOutlayHints(this ILanguageClient mediator, OutlayHintParams request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + private sealed class DelegatingOutlayHintsHandler : OutlayHintsHandlerBase where T : class?, IHandlerIdentity? + { + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + protected internal override OutlayHintRegistrationOptions CreateRegistrationOptions(OutlayHintWorkspaceClientCapabilities capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + private readonly Func?>> _handleParams; + private readonly Func, OutlayHintWorkspaceClientCapabilities, CancellationToken, Task>> _handleResolve; + public DelegatingOutlayHintsHandler(RegistrationOptionsDelegate registrationOptionsFactory, Func?>> handleParams, Func, OutlayHintWorkspaceClientCapabilities, CancellationToken, Task>> handleResolve) : base() + { + _registrationOptionsFactory = registrationOptionsFactory; + _handleParams = handleParams; + _handleResolve = handleResolve; + } + + protected override Task?> HandleParams(OutlayHintParams request, CancellationToken cancellationToken) => _handleParams(request, Capability, cancellationToken); + protected override Task> HandleResolve(OutlayHint request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); + } + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.05AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.05AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..ea38385cf --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.05AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Test.Models; + +[assembly: AssemblyRegistrationOptions(typeof(OutlayHintRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.05OutlayHintParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.05OutlayHintParams.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.06OutlayHintParams1.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.06OutlayHintParams1.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.06OutlayHintRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.06OutlayHintRegistrationOptions.verified.cs new file mode 100644 index 000000000..5d2e1e0d3 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.06OutlayHintRegistrationOptions.verified.cs @@ -0,0 +1,47 @@ +//HintName: OutlayHintRegistrationOptions.cs +using System.Diagnostics; +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.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; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.OutlayHintProvider))] + public partial class OutlayHintRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + public TextDocumentSelector? DocumentSelector { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + + [RegistrationOptionsKey(nameof(ServerCapabilities.OutlayHintProvider))] + public partial class StaticOptions : IWorkDoneProgressOptions + { + /// + /// The server provides support to resolve additional + /// information for a code action. + /// + /// @since 3.16.0 + /// + [Optional] + public bool ResolveProvider { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.07AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.07AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.07OutlayHintContainer.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.07OutlayHintContainer.verified.cs new file mode 100644 index 000000000..604492ca9 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.07OutlayHintContainer.verified.cs @@ -0,0 +1,109 @@ +//HintName: OutlayHintContainer.cs +using System.Diagnostics; +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.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; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class OutlayHintContainer : ContainerBase + { + public OutlayHintContainer() : this(Enumerable.Empty()) + { + } + + public OutlayHintContainer(IEnumerable items) : base(items) + { + } + + public OutlayHintContainer(params OutlayHint[] items) : base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(IEnumerable? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (OutlayHint[] items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(params OutlayHint[] items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (Collection? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(Collection? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (List? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(List? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (in ImmutableArray? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(in ImmutableArray? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (ImmutableList? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(ImmutableList? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.08OutlayHintRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.08OutlayHintRegistrationOptions.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.08Test0_OutlayHintTyped.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.08Test0_OutlayHintTyped.verified.cs new file mode 100644 index 000000000..7adc1f307 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.08Test0_OutlayHintTyped.verified.cs @@ -0,0 +1,240 @@ +//HintName: Test0_OutlayHintTyped.cs +using System.Diagnostics; +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.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; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + public partial record OutlayHint + { + public OutlayHint WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new OutlayHint{Position = Position, Label = Label, Kind = Kind, TextEdits = TextEdits, Tooltip = Tooltip, PaddingLeft = PaddingLeft, PaddingRight = PaddingRight, Data = data}; + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static OutlayHint? From(OutlayHint? item) + where T : class?, IHandlerIdentity? => item switch + { + not null => item, + _ => null + }; + } + + /// + /// Outlay hint information. + /// + /// @since 3.17.0 + /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] + [Parallel] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document", Name = "OutlayHintResolve")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateContainer] + [Capability(typeof(OutlayHintWorkspaceClientCapabilities))] + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial record OutlayHint : ICanBeResolved where T : class?, IHandlerIdentity? + { + /// + /// The position of this hint. + /// + public Position Position { get; init; } + + /// + /// The label of this hint. A human readable string or an array of + /// OutlayHintLabelPart label parts. + /// + /// *Note* that neither the string nor the label part can be empty. + /// + public StringOrOutlayHintLabelParts Label { get; init; } + + /// + /// The kind of this hint. Can be omitted in which case the client + /// should fall back to a reasonable default. + /// + public OutlayHintKind? Kind { get; init; } + + /// + /// Optional text edits that are performed when accepting this inlay hint. + /// + /// *Note* that edits are expected to change the document so that the inlay + /// hint (or its nearest variant) is now part of the document and the inlay + /// hint itself is now obsolete. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public Container? TextEdits { get; init; } + + /// + /// The tooltip text when you hover over this item. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + /// + [Optional] + public StringOrMarkupContent? Tooltip { get; init; } + + /// + /// Render padding before the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingLeft { get; init; } + + /// + /// Render padding after the hint. + /// + /// Note: Padding should use the editor's background color, not the + /// background color of the hint itself. That means padding can be used + /// to visually align/separate an inlay hint. + /// + [Optional] + public bool? PaddingRight { get; init; } + + /// + /// A data entry field that is preserved on a document link between a + /// DocumentLinkRequest and a DocumentLinkResolveRequest. + /// + [Optional] + public T Data { get => this.GetRawData()!; init => this.SetRawData(value); } + + private string DebuggerDisplay => ToString(); + public OutlayHint WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new OutlayHint{Position = Position, Label = Label, Kind = Kind, TextEdits = TextEdits, Tooltip = Tooltip, PaddingLeft = PaddingLeft, PaddingRight = PaddingRight, Data = data}; + } + + JToken? ICanBeResolved.Data { get; init; } + + private JToken? JData { get => this.GetRawData(); init => this.SetRawData(value); } + + public static implicit operator OutlayHint(OutlayHint value) => new OutlayHint{Position = value.Position, Label = value.Label, Kind = value.Kind, TextEdits = value.TextEdits, Tooltip = value.Tooltip, PaddingLeft = value.PaddingLeft, PaddingRight = value.PaddingRight, JData = value.Data}; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("value")] + public static implicit operator OutlayHint? (OutlayHint? value) => value switch + { + not null => new OutlayHint{Position = value.Position, Label = value.Label, Kind = value.Kind, TextEdits = value.TextEdits, Tooltip = value.Tooltip, PaddingLeft = value.PaddingLeft, PaddingRight = value.PaddingRight, Data = value.JData}, + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static OutlayHint? From(OutlayHint? item) => item switch + { + not null => item, + _ => null + }; + } + + public partial class OutlayHintContainer : ContainerBase> where T : class?, IHandlerIdentity? + { + public OutlayHintContainer() : this(Enumerable.Empty>()) + { + } + + public OutlayHintContainer(IEnumerable> items) : base(items) + { + } + + public OutlayHintContainer(params OutlayHint[] items) : base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(IEnumerable>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (OutlayHint[] items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(params OutlayHint[] items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (Collection>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(Collection>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (List>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(List>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (in ImmutableArray>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(in ImmutableArray>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator OutlayHintContainer? (ImmutableList>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static OutlayHintContainer? From(ImmutableList>? items) => items switch + { + not null => new OutlayHintContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("container")] + public static implicit operator OutlayHintContainer? (OutlayHintContainer? container) => container switch + { + not null => new OutlayHintContainer(container.Select(value => (OutlayHint)value)), + _ => null + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.09OutlayHintContainer.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.09OutlayHintContainer.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.10Test0_OutlayHintTyped.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Inlay_Hint.10Test0_OutlayHintTyped.verified.cs new file mode 100644 index 000000000..e69de29bb diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.00AssemblyCapabilityKeys.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.00AssemblyCapabilityKeys.verified.cs new file mode 100644 index 000000000..917a0660e --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.00AssemblyCapabilityKeys.verified.cs @@ -0,0 +1,18 @@ +//HintName: AssemblyCapabilityKeys.cs +using MediatR; +using Newtonsoft.Json.Linq; +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.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; +using System.Diagnostics; +using System.Linq; + +[assembly: AssemblyCapabilityKey(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.Client.Capabilities.SubLensCapability), nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeLens)), AssemblyCapabilityKey(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Test.Client.Capabilities.SubLensWorkspaceClientCapabilities), nameof(ClientCapabilities.Workspace), nameof(WorkspaceClientCapabilities.CodeLens))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.01Test0_SubLensParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.01Test0_SubLensParams.verified.cs new file mode 100644 index 000000000..49c21d78e --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.01Test0_SubLensParams.verified.cs @@ -0,0 +1,33 @@ +//HintName: Test0_SubLensParams.cs +#nullable enable +using System.Diagnostics; +using System.Linq; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + public partial record SubLensParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + + [Optional] + public ProgressToken? PartialResultToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.02GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.02GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..4a53684f5 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.02GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Document.Test.ISubLensHandler), typeof(OmniSharp.Extensions.LanguageServer.Protocol.Document.Test.ISubLensResolveHandler), typeof(OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Test.ISubLensRefreshHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.03SubLens.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.03SubLens.verified.cs new file mode 100644 index 000000000..a54bc6e06 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.03SubLens.verified.cs @@ -0,0 +1,69 @@ +//HintName: SubLens.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Test; +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.Test.Models; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Test +{ + [Parallel, Method(TextDocumentNames.CodeLensResolve, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface ISubLensResolveHandler : IJsonRpcRequestHandler, IDoesNotParticipateInRegistration, ICapability, ICanBeIdentifiedHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensResolveHandlerBase : AbstractHandlers.RequestCapability, ISubLensResolveHandler + { + protected SubLensResolveHandlerBase(System.Guid id) : base() + { + _id = id; + } + + protected SubLensResolveHandlerBase() : this(Guid.NewGuid()) + { + } + + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class SubLensResolveExtensions + { + public static ILanguageServerRegistry OnSubLensResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.CodeLensResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnSubLensResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.CodeLensResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnSubLensResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.RequestCapability(HandlerAdapter.Adapt(handler))); + public static Task ResolveSubLens(this ITextDocumentLanguageClient mediator, SubLens request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task ResolveSubLens(this ILanguageClient mediator, SubLens request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.04SubLensParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.04SubLensParams.verified.cs new file mode 100644 index 000000000..083023a2d --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.04SubLensParams.verified.cs @@ -0,0 +1,259 @@ +//HintName: SubLensParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Document.Test; +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.Test.Models; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Test +{ + [Parallel, Method(TextDocumentNames.CodeLens, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface ISubLensHandler : IJsonRpcRequestHandler, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensHandlerBase : AbstractHandlers.Request, ISubLensHandler, ISubLensResolveHandler + { + protected SubLensHandlerBase(System.Guid id) : base() + { + _id = id; + } + + protected SubLensHandlerBase() : this(Guid.NewGuid()) + { + } + + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + public abstract Task Handle(SubLens request, CancellationToken cancellationToken); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensHandlerBase : SubLensHandlerBase where T : class?, IHandlerIdentity? + { + protected SubLensHandlerBase(Guid id) : base(id) + { + } + + protected SubLensHandlerBase() : this(Guid.NewGuid()) + { + } + + public sealed override async Task Handle(SubLensParams request, CancellationToken cancellationToken) => await HandleParams(request, cancellationToken).ConfigureAwait(false); + public sealed override async Task Handle(SubLens request, CancellationToken cancellationToken) => await HandleResolve(request, cancellationToken).ConfigureAwait(false); + protected abstract Task> HandleParams(SubLensParams request, CancellationToken cancellationToken); + protected abstract Task> HandleResolve(SubLens request, CancellationToken cancellationToken); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensPartialHandlerBase : AbstractHandlers.PartialResults, ISubLensHandler, ISubLensResolveHandler + { + protected SubLensPartialHandlerBase(System.Guid id, IProgressManager progressManager) : base(progressManager, SubLensContainer.From) + { + _id = id; + } + + protected SubLensPartialHandlerBase(IProgressManager progressManager) : this(Guid.NewGuid(), progressManager) + { + } + + private readonly Guid _id; + Guid ICanBeIdentifiedHandler.Id => _id; + public abstract Task Handle(SubLens request, CancellationToken cancellationToken); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensPartialHandlerBase : SubLensPartialHandlerBase where T : class?, IHandlerIdentity? + { + protected SubLensPartialHandlerBase(Guid id, IProgressManager progressManager) : base(id, progressManager) + { + } + + protected SubLensPartialHandlerBase(IProgressManager progressManager) : this(Guid.NewGuid(), progressManager) + { + } + + protected sealed override void Handle(SubLensParams request, IObserver> results, CancellationToken cancellationToken) => Handle(request, new LanguageProtocolDelegatingHandlers.TypedPartialObserver, SubLens>(results, SubLens.From), cancellationToken); + public sealed override async Task Handle(SubLens request, CancellationToken cancellationToken) + { + var response = await HandleResolve(request, cancellationToken).ConfigureAwait(false); + return response; + } + + protected abstract void Handle(SubLensParams request, IObserver>> results, CancellationToken cancellationToken); + protected abstract Task> HandleResolve(SubLens request, CancellationToken cancellationToken); + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Document.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class SubLensExtensions + { + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>, SubLensCapability, CancellationToken> handler, RegistrationOptionsDelegate registrationOptions) + { + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions))).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>, CancellationToken> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>, SubLensCapability, CancellationToken> handler, Func> resolveHandler, RegistrationOptionsDelegate registrationOptions) + { + var id = Guid.NewGuid(); + return registry.AddHandler(TextDocumentNames.CodeLens, _ => new LanguageProtocolDelegatingHandlers.PartialResults(PartialAdapter.Adapt(handler), RegistrationAdapter.Adapt(registrationOptions), _.GetService(), SubLensContainer.From)).AddHandler(TextDocumentNames.CodeLensResolve, new LanguageProtocolDelegatingHandlers.Request(id, HandlerAdapter.Adapt(resolveHandler), RegistrationAdapter.Adapt(registrationOptions))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func?>> handler, Func, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingSubLensHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func?>> handler, Func, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingSubLensHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static ILanguageServerRegistry OnSubLens(this ILanguageServerRegistry registry, Func?>> handler, Func, SubLensCapability, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(new DelegatingSubLensHandler(RegistrationAdapter.Adapt(registrationOptions), HandlerAdapter.Adapt?>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>>> handler, Func, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(_ => new DelegatingSubLensPartialHandler(_.GetService(), RegistrationAdapter.Adapt(registrationOptions), PartialAdapter.Adapt>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>>, CancellationToken> handler, Func, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(_ => new DelegatingSubLensPartialHandler(_.GetService(), RegistrationAdapter.Adapt(registrationOptions), PartialAdapter.Adapt>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static ILanguageServerRegistry ObserveSubLens(this ILanguageServerRegistry registry, Action>>, SubLensCapability, CancellationToken> handler, Func, SubLensCapability, CancellationToken, Task>> resolveHandler, RegistrationOptionsDelegate registrationOptions) + where T : class?, IHandlerIdentity? + { + return registry.AddHandler(_ => new DelegatingSubLensPartialHandler(_.GetService(), RegistrationAdapter.Adapt(registrationOptions), PartialAdapter.Adapt>(handler), HandlerAdapter.Adapt, SubLens>(resolveHandler))); + } + + public static IRequestProgressObservable, SubLensContainer?> RequestSubLens(this ITextDocumentLanguageClient mediator, SubLensParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, SubLensContainer.From, cancellationToken); + public static IRequestProgressObservable, SubLensContainer?> RequestSubLens(this ILanguageClient mediator, SubLensParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, SubLensContainer.From, cancellationToken); + private sealed class DelegatingSubLensHandler : SubLensHandlerBase where T : class?, IHandlerIdentity? + { + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + protected internal override SubLensRegistrationOptions CreateRegistrationOptions(SubLensCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + private readonly Func?>> _handleParams; + private readonly Func, SubLensCapability, CancellationToken, Task>> _handleResolve; + public DelegatingSubLensHandler(RegistrationOptionsDelegate registrationOptionsFactory, Func?>> handleParams, Func, SubLensCapability, CancellationToken, Task>> handleResolve) : base() + { + _registrationOptionsFactory = registrationOptionsFactory; + _handleParams = handleParams; + _handleResolve = handleResolve; + } + + protected override Task?> HandleParams(SubLensParams request, CancellationToken cancellationToken) => _handleParams(request, Capability, cancellationToken); + protected override Task> HandleResolve(SubLens request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); + } + + private sealed class DelegatingSubLensPartialHandler : SubLensPartialHandlerBase where T : class?, IHandlerIdentity? + { + private readonly RegistrationOptionsDelegate _registrationOptionsFactory; + protected internal override SubLensRegistrationOptions CreateRegistrationOptions(SubLensCapability capability, ClientCapabilities clientCapabilities) => _registrationOptionsFactory(capability, clientCapabilities); + private readonly Action>>, SubLensCapability, CancellationToken> _handle; + private readonly Func, SubLensCapability, CancellationToken, Task>> _handleResolve; + public DelegatingSubLensPartialHandler(IProgressManager progressManager, RegistrationOptionsDelegate registrationOptionsFactory, Action>>, SubLensCapability, CancellationToken> handle, Func, SubLensCapability, CancellationToken, Task>> handleResolve) : base(progressManager) + { + _registrationOptionsFactory = registrationOptionsFactory; + _handle = handle; + _handleResolve = handleResolve; + } + + protected override void Handle(SubLensParams request, IObserver>> results, CancellationToken cancellationToken) => _handle(request, results, Capability, cancellationToken); + protected override Task> HandleResolve(SubLens request, CancellationToken cancellationToken) => _handleResolve(request, Capability, cancellationToken); + } + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.05SubLensRefreshParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.05SubLensRefreshParams.verified.cs new file mode 100644 index 000000000..d41c4734e --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.05SubLensRefreshParams.verified.cs @@ -0,0 +1,61 @@ +//HintName: SubLensRefreshParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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.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; +using OmniSharp.Extensions.LanguageServer.Protocol.Test.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Test; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Test +{ + [Parallel, Method(WorkspaceNames.CodeLensRefresh, Direction.ServerToClient)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface ISubLensRefreshHandler : IJsonRpcNotificationHandler, ICapability + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SubLensRefreshHandlerBase : AbstractHandlers.NotificationCapability, ISubLensRefreshHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace.Test +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class SubLensRefreshExtensions + { + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Action handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, NotificationHandler.For(handler)); + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, NotificationHandler.For(handler)); + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Action handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, NotificationHandler.For(handler)); + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, NotificationHandler.For(handler)); + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Action handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, new LanguageProtocolDelegatingHandlers.NotificationCapability(HandlerAdapter.Adapt(handler))); + public static ILanguageClientRegistry OnSubLensRefresh(this ILanguageClientRegistry registry, Func handler) => registry.AddHandler(WorkspaceNames.CodeLensRefresh, new LanguageProtocolDelegatingHandlers.NotificationCapability(HandlerAdapter.Adapt(handler))); + public static void SendSubLensRefresh(this IWorkspaceLanguageServer mediator, SubLensRefreshParams request) => mediator.SendNotification(request); + public static void SendSubLensRefresh(this ILanguageServer mediator, SubLensRefreshParams request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.06AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.06AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..8906112fa --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.06AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Test.Models; + +[assembly: AssemblyRegistrationOptions(typeof(SubLensRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.07SubLensRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.07SubLensRegistrationOptions.verified.cs new file mode 100644 index 000000000..eec350d8b --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.07SubLensRegistrationOptions.verified.cs @@ -0,0 +1,43 @@ +//HintName: SubLensRegistrationOptions.cs +using System.Diagnostics; +using System.Linq; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.SubLensProvider))] + public partial class SubLensRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + public TextDocumentSelector? DocumentSelector { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + + [RegistrationOptionsKey(nameof(ServerCapabilities.SubLensProvider))] + public partial class StaticOptions : IWorkDoneProgressOptions + { + /// + /// Code lens has a resolve provider as well. + /// + [Optional] + public bool ResolveProvider { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.08SubLensContainer.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.08SubLensContainer.verified.cs new file mode 100644 index 000000000..01b4eeb97 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.08SubLensContainer.verified.cs @@ -0,0 +1,107 @@ +//HintName: SubLensContainer.cs +using System.Diagnostics; +using System.Linq; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class SubLensContainer : ContainerBase + { + public SubLensContainer() : this(Enumerable.Empty()) + { + } + + public SubLensContainer(IEnumerable items) : base(items) + { + } + + public SubLensContainer(params SubLens[] items) : base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(IEnumerable? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (SubLens[] items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(params SubLens[] items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (Collection? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(Collection? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (List? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(List? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (in ImmutableArray? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(in ImmutableArray? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (ImmutableList? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(ImmutableList? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.09Test0_SubLensTyped.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.09Test0_SubLensTyped.verified.cs new file mode 100644 index 000000000..19c4b8d68 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Nullable_Params_With_Typed_Data.09Test0_SubLensTyped.verified.cs @@ -0,0 +1,195 @@ +//HintName: Test0_SubLensTyped.cs +using System.Diagnostics; +using System.Linq; +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.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test.Models +{ + public partial record SubLens + { + public SubLens WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new SubLens{Range = Range, Command = Command, Data = data}; + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static SubLens? From(SubLens? item) + where T : class?, IHandlerIdentity? => 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] + [GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Document.Test", Name = "SubLensResolve")] + [GenerateHandlerMethods] + [GenerateRequestMethods(typeof(ITextDocumentLanguageClient), typeof(ILanguageClient))] + [GenerateContainer] + [Capability(typeof(SubLensCapability))] + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial record SubLens : ICanBeResolved where T : class?, IHandlerIdentity? + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; init; } = null !; + /// + /// The command this code lens represents. + /// + [Optional] + public Command? Command { get; init; } + + /// + /// 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 => this.GetRawData()!; init => this.SetRawData(value); } + + private string DebuggerDisplay => $"{Range}{(Command != null ? $" {Command}" : "")}"; + /// + public override string ToString() + { + return DebuggerDisplay; + } + + public SubLens WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new SubLens{Range = Range, Command = Command, Data = data}; + } + + JToken? ICanBeResolved.Data { get; init; } + + private JToken? JData { get => this.GetRawData(); init => this.SetRawData(value); } + + public static implicit operator SubLens(SubLens value) => new SubLens{Range = value.Range, Command = value.Command, JData = value.Data}; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("value")] + public static implicit operator SubLens? (SubLens? value) => value switch + { + not null => new SubLens{Range = value.Range, Command = value.Command, Data = value.JData}, + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static SubLens? From(SubLens? item) => item switch + { + not null => item, + _ => null + }; + } + + public partial class SubLensContainer : ContainerBase> where T : class?, IHandlerIdentity? + { + public SubLensContainer() : this(Enumerable.Empty>()) + { + } + + public SubLensContainer(IEnumerable> items) : base(items) + { + } + + public SubLensContainer(params SubLens[] items) : base(items) + { + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(IEnumerable>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (SubLens[] items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(params SubLens[] items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (Collection>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(Collection>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (List>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(List>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (in ImmutableArray>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(in ImmutableArray>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static implicit operator SubLensContainer? (ImmutableList>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("items")] + public static SubLensContainer? From(ImmutableList>? items) => items switch + { + not null => new SubLensContainer(items), + _ => null + }; + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("container")] + public static implicit operator SubLensContainer? (SubLensContainer? container) => container switch + { + not null => new SubLensContainer(container.Select(value => (SubLens)value)), + _ => null + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.00AssemblyCapabilityKeys.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.00AssemblyCapabilityKeys.verified.cs new file mode 100644 index 000000000..52a6b6c98 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.00AssemblyCapabilityKeys.verified.cs @@ -0,0 +1,16 @@ +//HintName: AssemblyCapabilityKeys.cs +using MediatR; +using Newtonsoft.Json.Linq; +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.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using System.Diagnostics; + +[assembly: AssemblyCapabilityKey(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities.WorkspaceSymbolCapability), nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Symbol))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.01Test0_SymbolInformationParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.01Test0_SymbolInformationParams.verified.cs new file mode 100644 index 000000000..929558a0a --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.01Test0_SymbolInformationParams.verified.cs @@ -0,0 +1,30 @@ +//HintName: Test0_SymbolInformationParams.cs +#nullable enable +using System.Diagnostics; +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; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + public partial record SymbolInformationParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + + [Optional] + public ProgressToken? PartialResultToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.02Test0_WorkspaceSymbolParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.02Test0_WorkspaceSymbolParams.verified.cs new file mode 100644 index 000000000..04c4234af --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.02Test0_WorkspaceSymbolParams.verified.cs @@ -0,0 +1,30 @@ +//HintName: Test0_WorkspaceSymbolParams.cs +#nullable enable +using System.Diagnostics; +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; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using Newtonsoft.Json; +using System.ComponentModel; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + public partial record WorkspaceSymbolParams + { + [Optional] + public ProgressToken? WorkDoneToken { get; init; } + + [Optional] + public ProgressToken? PartialResultToken { get; init; } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.03GeneratedAssemblyJsonRpcHandlers.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.03GeneratedAssemblyJsonRpcHandlers.verified.cs new file mode 100644 index 000000000..bd7d44297 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.03GeneratedAssemblyJsonRpcHandlers.verified.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(OmniSharp.Extensions.LanguageServer.Protocol.Workspace.ISymbolInformationHandler), typeof(OmniSharp.Extensions.LanguageServer.Protocol.Workspace.IWorkspaceSymbolsHandler), typeof(OmniSharp.Extensions.LanguageServer.Protocol.Workspace.IWorkspaceSymbolResolveHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.04SymbolInformationParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.04SymbolInformationParams.verified.cs new file mode 100644 index 000000000..989abb90e --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.04SymbolInformationParams.verified.cs @@ -0,0 +1,91 @@ +//HintName: SymbolInformationParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 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 ISymbolInformationHandler : IJsonRpcRequestHandler?>, IRegistration + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SymbolInformationHandlerBase : AbstractHandlers.Request?, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>, ISymbolInformationHandler + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class SymbolInformationPartialHandlerBase : AbstractHandlers.PartialResults?, SymbolInformation, WorkspaceSymbolRegistrationOptions, WorkspaceSymbolCapability>, ISymbolInformationHandler + { + protected SymbolInformationPartialHandlerBase(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 SymbolInformationExtensions + { + public static ILanguageServerRegistry OnSymbolInformation(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 OnSymbolInformation(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 OnSymbolInformation(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 ObserveSymbolInformation(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 ObserveSymbolInformation(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 ObserveSymbolInformation(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?> RequestSymbolInformation(this ITextDocumentLanguageClient mediator, SymbolInformationParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, Container.From, cancellationToken); + public static IRequestProgressObservable, Container?> RequestSymbolInformation(this ILanguageClient mediator, SymbolInformationParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, Container.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.05WorkspaceSymbol.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.05WorkspaceSymbol.verified.cs new file mode 100644 index 000000000..e705bf400 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.05WorkspaceSymbol.verified.cs @@ -0,0 +1,55 @@ +//HintName: WorkspaceSymbol.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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; +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.WorkspaceSymbolResolve, Direction.ClientToServer)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IWorkspaceSymbolResolveHandler : IJsonRpcRequestHandler, ICapability + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class WorkspaceSymbolResolveHandlerBase : AbstractHandlers.RequestCapability, IWorkspaceSymbolResolveHandler + { + } +} +#nullable restore + +namespace OmniSharp.Extensions.LanguageServer.Protocol.Workspace +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class WorkspaceSymbolResolveExtensions + { + public static ILanguageServerRegistry OnWorkspaceSymbolResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(WorkspaceNames.WorkspaceSymbolResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnWorkspaceSymbolResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(WorkspaceNames.WorkspaceSymbolResolve, RequestHandler.For(handler)); + public static ILanguageServerRegistry OnWorkspaceSymbolResolve(this ILanguageServerRegistry registry, Func> handler) => registry.AddHandler(WorkspaceNames.WorkspaceSymbolResolve, new LanguageProtocolDelegatingHandlers.RequestCapability(HandlerAdapter.Adapt(handler))); + public static Task ResolveWorkspaceSymbol(this IWorkspaceLanguageClient mediator, WorkspaceSymbol request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + public static Task ResolveWorkspaceSymbol(this ILanguageClient mediator, WorkspaceSymbol request, CancellationToken cancellationToken = default) => mediator.SendRequest(request, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.06WorkspaceSymbolParams.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.06WorkspaceSymbolParams.verified.cs new file mode 100644 index 000000000..41b4deebf --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.06WorkspaceSymbolParams.verified.cs @@ -0,0 +1,91 @@ +//HintName: WorkspaceSymbolParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json.Linq; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +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 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?, WorkspaceSymbol, 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?, WorkspaceSymbol, 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?, WorkspaceSymbol, 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?, WorkspaceSymbol, 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, Container.From, cancellationToken); + public static IRequestProgressObservable, Container?> RequestWorkspaceSymbols(this ILanguageClient mediator, WorkspaceSymbolParams request, CancellationToken cancellationToken = default) => mediator.ProgressManager.MonitorUntil(request, Container.From, cancellationToken); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.07AssemblyRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.07AssemblyRegistrationOptions.verified.cs new file mode 100644 index 000000000..374b0232e --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.07AssemblyRegistrationOptions.verified.cs @@ -0,0 +1,5 @@ +//HintName: AssemblyRegistrationOptions.cs +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; + +[assembly: AssemblyRegistrationOptions(typeof(WorkspaceSymbolRegistrationOptions))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.08WorkspaceSymbolRegistrationOptions.verified.cs b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.08WorkspaceSymbolRegistrationOptions.verified.cs new file mode 100644 index 000000000..c69e87145 --- /dev/null +++ b/test/Generation.Tests/snapshots/LspFeatureTests.Supports_Params_Type_As_Source.08WorkspaceSymbolRegistrationOptions.verified.cs @@ -0,0 +1,40 @@ +//HintName: WorkspaceSymbolRegistrationOptions.cs +using System.Diagnostics; +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; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; +using OmniSharp.Extensions.LanguageServer.Protocol.Workspace; +using OmniSharp.Extensions.LanguageServer.Protocol; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Models +{ + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class WorkspaceSymbolRegistrationOptions : OmniSharp.Extensions.LanguageServer.Protocol.IRegistrationOptions + { + [Optional] + public bool WorkDoneProgress { get; set; } + + [RegistrationOptionsKey(nameof(ServerCapabilities.WorkspaceSymbolProvider))] + public partial class StaticOptions : IWorkDoneProgressOptions + { + /// + /// The server provides support to resolve additional + /// information for a workspace symbol. + /// + [Optional] + public bool ResolveProvider { get; set; } + + [Optional] + public bool WorkDoneProgress { get; set; } + } + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_Container.verified.cs b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_Container.verified.cs new file mode 100644 index 000000000..2238bdb8b --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_Container.verified.cs @@ -0,0 +1,108 @@ +//HintName: CodeLensContainer.cs +using System; +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; +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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class CodeLensContainer : ContainerBase + { + 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 + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00CodeLensContainer.verified.cs b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00CodeLensContainer.verified.cs new file mode 100644 index 000000000..2238bdb8b --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00CodeLensContainer.verified.cs @@ -0,0 +1,108 @@ +//HintName: CodeLensContainer.cs +using System; +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; +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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial class CodeLensContainer : ContainerBase + { + 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 + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01Test0_CodeLensTyped.verified.cs b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01Test0_CodeLensTyped.verified.cs new file mode 100644 index 000000000..be79042af --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedCanBeResolvedTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01Test0_CodeLensTyped.verified.cs @@ -0,0 +1,183 @@ +//HintName: Test0_CodeLensTyped.cs +using System; +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; +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 System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Immutable; +using System.Linq; + +#nullable enable +namespace OmniSharp.Extensions.LanguageServer.Protocol.Test +{ + public partial record CodeLens + { + public CodeLens WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new CodeLens{Range = Range, Command = Command, Data = data}; + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("item")] + public static CodeLens? From(CodeLens? item) + where T : class?, IHandlerIdentity? => 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}")] + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial record CodeLens : ICanBeResolved where T : class?, IHandlerIdentity? + { + /// + /// The range in which this code lens is valid. Should only span a single line. + /// + public Range Range { get; init; } + + [Optional] + public Command? Command { get; init; } + + /// + /// 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 => this.GetRawData()!; init => this.SetRawData(value); } + + private string DebuggerDisplay => $"{Range}{(Command != null ? $" {Command}" : "")}"; + public override string ToString() => DebuggerDisplay; + public CodeLens WithData(TData data) + where TData : class?, IHandlerIdentity? + { + return new CodeLens{Range = Range, Command = Command, Data = data}; + } + + JToken? ICanBeResolved.Data { get; init; } + + private JToken? JData { get => this.GetRawData(); init => this.SetRawData(value); } + + public static implicit operator CodeLens(CodeLens value) => new CodeLens{Range = value.Range, Command = value.Command, JData = 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 = value.JData}, + _ => 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 : class?, IHandlerIdentity? + { + 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 + }; + } +} +#nullable restore diff --git a/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00.received.txt b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00.received.txt new file mode 100644 index 000000000..0f206832a --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.00.received.txt @@ -0,0 +1,17 @@ +{ + Diagnostics: [ + { + Id: JRPC1003, + Title: Cannot infer request router(s), + Severity: Error, + WarningLevel: 0, + Location: Test0.cs: (16,4)-(16,26), + Description: , + HelpLink: , + MessageFormat: Could not infer the request router(s) to use, please specify the target interface(s)., + Message: Could not infer the request router(s) to use, please specify the target interface(s)., + Category: JsonRPC, + CustomTags: [] + } + ] +} \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01GeneratedAssemblyJsonRpcHandlers.received.cs b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01GeneratedAssemblyJsonRpcHandlers.received.cs new file mode 100644 index 000000000..30d33a7db --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.01GeneratedAssemblyJsonRpcHandlers.received.cs @@ -0,0 +1,4 @@ +//HintName: GeneratedAssemblyJsonRpcHandlers.cs +using OmniSharp.Extensions.JsonRpc; + +[assembly: AssemblyJsonRpcHandlers(typeof(Test.Document.IPublishDiagnosticsHandler))] \ No newline at end of file diff --git a/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.02PublishDiagnosticsParams.received.cs b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.02PublishDiagnosticsParams.received.cs new file mode 100644 index 000000000..7acaed031 --- /dev/null +++ b/test/Generation.Tests/snapshots/TypedParamsTests.Supports_Generating_Strongly_Typed_ICanBeResolved_Data.02PublishDiagnosticsParams.received.cs @@ -0,0 +1,49 @@ +//HintName: PublishDiagnosticsParams.cs +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using OmniSharp.Extensions.DebugAdapter.Protocol; +using OmniSharp.Extensions.DebugAdapter.Protocol.Events; +using OmniSharp.Extensions.DebugAdapter.Protocol.Models; +using OmniSharp.Extensions.DebugAdapter.Protocol.Requests; +using OmniSharp.Extensions.JsonRpc; +using OmniSharp.Extensions.JsonRpc.Generation; +using OmniSharp.Extensions.LanguageServer.Protocol; +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; +using Test.Document; +using Test.Models; + +#nullable enable +namespace Test.Document +{ + [Parallel, Method(TextDocumentNames.PublishDiagnostics, Direction.ServerToClient)] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public partial interface IPublishDiagnosticsHandler : IJsonRpcNotificationHandler, ICapability + { + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + abstract public partial class PublishDiagnosticsHandlerBase : AbstractHandlers.NotificationCapability, IPublishDiagnosticsHandler + { + } +} +#nullable restore + +namespace Test.Document +{ +#nullable enable + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute, System.Runtime.CompilerServices.CompilerGeneratedAttribute] + public static partial class PublishDiagnosticsExtensions + { + public static void PublishDiagnostics(this ITextDocumentLanguageServer mediator, PublishDiagnosticsParams request) => mediator.SendNotification(request); + public static void PublishDiagnostics(this ILanguageServer mediator, PublishDiagnosticsParams request) => mediator.SendNotification(request); + } +#nullable restore +} \ No newline at end of file diff --git a/test/Lsp.Integration.Tests/DynamicRegistrationTests.cs b/test/Lsp.Integration.Tests/DynamicRegistrationTests.cs index f7787981d..c4352d021 100644 --- a/test/Lsp.Integration.Tests/DynamicRegistrationTests.cs +++ b/test/Lsp.Integration.Tests/DynamicRegistrationTests.cs @@ -59,7 +59,7 @@ public async Task Should_Register_Dynamically_While_Server_Is_Running() (@params, token) => Task.FromResult(new CompletionList()), (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ) ); @@ -109,7 +109,7 @@ public async Task Should_Unregister_Dynamically_While_Server_Is_Running() (@params, token) => Task.FromResult(new CompletionList()), (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ) ); @@ -163,18 +163,18 @@ await TestHelper.DelayUntil( client.RegistrationManager.CurrentRegistrations.Should().ContainSingle(x => x.Method == TextDocumentNames.SemanticTokensRegistration); } - private bool SelectorMatches(Registration registration, Func documentFilter) + private bool SelectorMatches(Registration registration, Func documentFilter) { return SelectorMatches(registration.RegisterOptions!, documentFilter); } - private bool SelectorMatches(object options, Func documentFilter) + private bool SelectorMatches(object options, Func documentFilter) { if (options is Registration registration) return SelectorMatches(registration.RegisterOptions!, documentFilter); if (options is ITextDocumentRegistrationOptions tdro) return tdro.DocumentSelector?.Any(documentFilter) == true; - if (options is DocumentSelector selector) + if (options is TextDocumentSelector selector) return selector.Any(documentFilter); return false; } @@ -206,7 +206,7 @@ public async Task Should_Gather_Static_Registrations() Legend = new SemanticTokensLegend(), Full = new SemanticTokensCapabilityRequestFull { Delta = true }, Range = new SemanticTokensCapabilityRequestRange(), - DocumentSelector = DocumentSelector.ForLanguage("csharp") + DocumentSelector = TextDocumentSelector.ForLanguage("csharp") }; // Our server only statically registers when it detects a server that does not support dynamic capabilities @@ -364,7 +364,7 @@ public void Configure(LanguageServerOptions options) (@params, token) => Task.FromResult(new CompletionList()), (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp"), + DocumentSelector = TextDocumentSelector.ForLanguage("csharp"), ResolveProvider = true, TriggerCharacters = new Container("a", "b"), AllCommitCharacters = new Container("1", "2"), diff --git a/test/Lsp.Integration.Tests/FluentAssertionsExtensions.cs b/test/Lsp.Integration.Tests/FluentAssertionsExtensions.cs index bba67f668..cbb682d93 100644 --- a/test/Lsp.Integration.Tests/FluentAssertionsExtensions.cs +++ b/test/Lsp.Integration.Tests/FluentAssertionsExtensions.cs @@ -14,7 +14,7 @@ public static EquivalencyAssertionOptions ConfigureForSupports(this Equiva return options .WithTracing(new TraceWriter(logger ?? NullLogger.Instance)) .ComparingByMembers>() - .ComparingByMembers>() + .ComparingByMembers>() .ComparingByMembers>() .ComparingByMembers>() .ComparingByMembers>() diff --git a/test/Lsp.Integration.Tests/InlineValueTests.cs b/test/Lsp.Integration.Tests/InlineValueTests.cs new file mode 100644 index 000000000..52bb4ce8c --- /dev/null +++ b/test/Lsp.Integration.Tests/InlineValueTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; +using NSubstitute; +using OmniSharp.Extensions.JsonRpc.Testing; +using OmniSharp.Extensions.LanguageProtocol.Testing; +using OmniSharp.Extensions.LanguageServer.Client; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Server; +using Serilog.Events; +using Xunit; +using Xunit.Abstractions; + +namespace Lsp.Integration.Tests +{ + public class InlineValueTests : LanguageProtocolTestBase + { + private readonly Func?>> _request; + + public InlineValueTests(ITestOutputHelper outputHelper) : base(new JsonRpcTestOptions().ConfigureForXUnit(outputHelper, LogEventLevel.Verbose)) + { + _request = Substitute.For?>>>(); + } + + [Fact] + public async Task Should_Get_InlineValues() + { + _request.Invoke(Arg.Any(), Arg.Any()) + .Returns( + new Container( + new InlineValueText() + { + Range = new (new (1, 1), (1, 2)), + Text = "Text Value", + }, + new InlineValueEvaluatableExpression() + { + Range = new (new (3, 1), (3, 2)), + Expression = "" + }, + new InlineValueVariableLookup() + { + Range = new (new (2, 1), (2, 2)), + VariableName = "value", + CaseSensitiveLookup = true + } + ) + ); + + + var (client, _) = await Initialize(ClientOptionsAction, ServerOptionsAction); + + var result = await client.RequestInlineValues(new InlineValueParams(), CancellationToken); + + result.Should().HaveCount(3); + result.Select(z => z.GetType()).Should().ContainInOrder( + typeof(InlineValueText), typeof(InlineValueEvaluatableExpression), typeof(InlineValueVariableLookup) + ); + } + + private void ServerOptionsAction(LanguageServerOptions obj) + { + obj.OnInlineValues( + _request, (_, _) => new InlineValueRegistrationOptions + { + DocumentSelector = TextDocumentSelector.ForLanguage("csharp"), + } + ); + } + + private void ClientOptionsAction(LanguageClientOptions obj) + { + } + } +} diff --git a/test/Lsp.Integration.Tests/Lsp.Integration.Tests.csproj b/test/Lsp.Integration.Tests/Lsp.Integration.Tests.csproj index 4d655de2e..f60a716fd 100644 --- a/test/Lsp.Integration.Tests/Lsp.Integration.Tests.csproj +++ b/test/Lsp.Integration.Tests/Lsp.Integration.Tests.csproj @@ -19,12 +19,6 @@ - + diff --git a/test/Lsp.Integration.Tests/MonikerTests.cs b/test/Lsp.Integration.Tests/MonikerTests.cs index cfaee34c7..f0109b4de 100644 --- a/test/Lsp.Integration.Tests/MonikerTests.cs +++ b/test/Lsp.Integration.Tests/MonikerTests.cs @@ -44,7 +44,7 @@ public async Task Should_Get_Monikers() var (client, _) = await Initialize(ClientOptionsAction, ServerOptionsAction); - var result = await client.RequestMoniker(new MonikerParams(), CancellationToken); + var result = await client.RequestMonikers(new MonikerParams(), CancellationToken); result.Should().HaveCount(1); result.Should().Match(z => z.Any(x => x.Kind == MonikerKind.Export)); @@ -52,10 +52,10 @@ public async Task Should_Get_Monikers() private void ServerOptionsAction(LanguageServerOptions obj) { - obj.OnMoniker( + obj.OnMonikers( _request, (_, _) => new MonikerRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp"), + DocumentSelector = TextDocumentSelector.ForLanguage("csharp"), } ); } diff --git a/test/Lsp.Integration.Tests/Properties.cs b/test/Lsp.Integration.Tests/Properties.cs index 627fca850..22c3b6b74 100644 --- a/test/Lsp.Integration.Tests/Properties.cs +++ b/test/Lsp.Integration.Tests/Properties.cs @@ -1,3 +1,3 @@ using Xunit; -[assembly: CollectionBehavior(MaxParallelThreads = 10)] +//[assembly: CollectionBehavior(MaxParallelThreads = 10)] diff --git a/test/Lsp.Integration.Tests/RenameTests.cs b/test/Lsp.Integration.Tests/RenameTests.cs index 7c4d6be93..d6128fc5e 100644 --- a/test/Lsp.Integration.Tests/RenameTests.cs +++ b/test/Lsp.Integration.Tests/RenameTests.cs @@ -228,13 +228,13 @@ private void ServerOptionsAction(LanguageServerOptions obj) obj.OnPrepareRename( _prepareRename, (_, _) => new RenameRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp") + DocumentSelector = TextDocumentSelector.ForLanguage("csharp") } ); obj.OnRename( _rename, (_, _) => new RenameRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("csharp"), + DocumentSelector = TextDocumentSelector.ForLanguage("csharp"), PrepareProvider = true, } ); diff --git a/test/Lsp.Integration.Tests/TypedCallHierarchyTests.cs b/test/Lsp.Integration.Tests/TypedCallHierarchyTests.cs index 3da1c2560..1209b0bf9 100644 --- a/test/Lsp.Integration.Tests/TypedCallHierarchyTests.cs +++ b/test/Lsp.Integration.Tests/TypedCallHierarchyTests.cs @@ -63,7 +63,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() outgoingHandlerA, (_, _) => new() { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -85,7 +85,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() outgoingHandlerB, (_, _) => new() { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); } @@ -144,7 +144,7 @@ public async Task Should_Resolve_With_Data_Capability() outgoingHandler, (_, _) => new() { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); } diff --git a/test/Lsp.Integration.Tests/TypedCodeActionTests.cs b/test/Lsp.Integration.Tests/TypedCodeActionTests.cs index d155a5a4b..d626e33eb 100644 --- a/test/Lsp.Integration.Tests/TypedCodeActionTests.cs +++ b/test/Lsp.Integration.Tests/TypedCodeActionTests.cs @@ -66,7 +66,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action => { return Task.FromResult(action with { Command = action.Command with { Name = "resolved-a" } }); }, (_, _) => new CodeActionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -95,7 +95,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action => { return Task.FromResult(action with { Command = action.Command with { Name = "resolved-b" } }); }, (_, _) => new CodeActionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -120,7 +120,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action => { return Task.FromResult(action with { Command = action.Command with { Name = "resolved-c" } }); }, (_, _) => new CodeActionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -145,7 +145,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() action => { return Task.FromResult(action with { Command = action.Command with { Name = "resolved-d" } }); }, (_, _) => new CodeActionRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ); } diff --git a/test/Lsp.Integration.Tests/TypedCodeLensTests.cs b/test/Lsp.Integration.Tests/TypedCodeLensTests.cs index 0737fd0fa..48cc3689c 100644 --- a/test/Lsp.Integration.Tests/TypedCodeLensTests.cs +++ b/test/Lsp.Integration.Tests/TypedCodeLensTests.cs @@ -39,7 +39,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() options.OnCodeLens( codeLensParams => { - return Task.FromResult( + return Task.FromResult( new CodeLensContainer( new CodeLens { @@ -64,14 +64,14 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l => { return Task.FromResult(l with { Command = l.Command with { Name = "resolved-a" } }); }, (_, _) => new CodeLensRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); options.OnCodeLens( codeLensParams => { - return Task.FromResult( + return Task.FromResult( new CodeLensContainer( new CodeLens { @@ -91,14 +91,14 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l => { return Task.FromResult(l with { Command = l.Command with { Name = "resolved-b" } }); }, (_, _) => new CodeLensRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); options.OnCodeLens( codeLensParams => { - return Task.FromResult( + return Task.FromResult( new CodeLensContainer( new CodeLens { @@ -114,14 +114,14 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l => { return Task.FromResult(l with { Command = l.Command with { Name = "resolved-c" } }); }, (_, _) => new CodeLensRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); options.OnCodeLens( codeLensParams => { - return Task.FromResult( + return Task.FromResult( new CodeLensContainer( new CodeLens { @@ -137,7 +137,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() l => { return Task.FromResult(l with { Command = l.Command with { Name = "resolved-d" } }); }, (_, _) => new CodeLensRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ); } @@ -167,7 +167,7 @@ public async Task Should_Resolve_With_Data_Capability() options.OnCodeLens( (codeLensParams, capability, token) => { - return Task.FromResult( + return Task.FromResult?>( new CodeLensContainer( new CodeLens { @@ -270,7 +270,7 @@ public async Task Should_Resolve_With_Data_CancellationToken() options.OnCodeLens( (codeLensParams, token) => { - return Task.FromResult( + return Task.FromResult?>( new CodeLensContainer( new CodeLens { diff --git a/test/Lsp.Integration.Tests/TypedCompletionTests.cs b/test/Lsp.Integration.Tests/TypedCompletionTests.cs index 61cc6faaa..95120baeb 100644 --- a/test/Lsp.Integration.Tests/TypedCompletionTests.cs +++ b/test/Lsp.Integration.Tests/TypedCompletionTests.cs @@ -64,7 +64,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem => { return Task.FromResult(completionItem with { Command = completionItem.Command with { Name = "resolved-a" } }); }, (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -91,7 +91,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem => { return Task.FromResult(completionItem with { Command = completionItem.Command with { Name = "resolved-b" } }); }, (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -114,7 +114,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem => { return Task.FromResult(completionItem with { Command = completionItem.Command with { Name = "resolved-c" } }); }, (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -137,7 +137,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() completionItem => { return Task.FromResult(completionItem with { Command = completionItem.Command with { Name = "resolved-d" } }); }, (_, _) => new CompletionRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ); } @@ -222,9 +222,24 @@ public async Task Should_Resolve_With_Partial_Data_Capability() options => { }, options => { options.ObserveCompletion( + (completionParams, token) => Task.FromResult( + new CompletionList() + { + ItemDefaults = new CompletionListItemDefaults() + { + InsertTextMode = InsertTextMode.AsIs, + EditRange = new Range() + { + End = new Position(0, 1) + }, + CommitCharacters = new Container("a", "b", "c"), + Data = JObject.FromObject(new { Test = 1 }) + } + } + ), (completionParams, observer, capability, token) => { - var a = new CompletionList( + var a = new Container>( new CompletionItem { Command = new Command @@ -260,6 +275,8 @@ public async Task Should_Resolve_With_Partial_Data_Capability() ); var completionList = await client.RequestCompletion(new CompletionParams()); + completionList.ItemDefaults.Should().NotBeNull(); + completionList.ItemDefaults.CommitCharacters.Should().ContainInOrder("a", "b", "c"); var item = completionList.First(); item = await client.ResolveCompletion(item); @@ -324,9 +341,10 @@ public async Task Should_Resolve_With_Partial_Data_CancellationToken() options => { }, options => { options.ObserveCompletion( + (completionParams, token) => Task.FromResult(new CompletionList()), (completionParams, observer, token) => { - var a = new CompletionList( + var a = new Container>( new CompletionItem { Command = new Command @@ -425,9 +443,10 @@ public async Task Should_Resolve_With_Partial_Data() options => { }, options => { options.ObserveCompletion( + (completionParams) => Task.FromResult(new CompletionList()), (completionParams, observer) => { - var a = new CompletionList( + var a = new Container>( new CompletionItem { Command = new Command @@ -512,9 +531,10 @@ public async Task Should_Resolve_Partial_Capability() options => { }, options => { options.ObserveCompletion( + (completionParams, token) => Task.FromResult(new CompletionList()), (completionParams, observer, capability, token) => { - var a = new CompletionList( + var a = new Container( new CompletionItem { Command = new Command @@ -583,9 +603,10 @@ public async Task Should_Resolve_Partial_CancellationToken() options => { }, options => { options.ObserveCompletion( + (completionParams, token) => Task.FromResult(new CompletionList()), (completionParams, observer, token) => { - var a = new CompletionList( + var a = new Container( new CompletionItem { Command = new Command @@ -654,9 +675,10 @@ public async Task Should_Resolve_Partial() options => { }, options => { options.ObserveCompletion( + (completionParams) => Task.FromResult(new CompletionList()), (completionParams, observer) => { - var a = new CompletionList( + var a = new Container( new CompletionItem { Command = new Command diff --git a/test/Lsp.Integration.Tests/TypedDocumentLinkTests.cs b/test/Lsp.Integration.Tests/TypedDocumentLinkTests.cs index 2ea362015..f3e8a238b 100644 --- a/test/Lsp.Integration.Tests/TypedDocumentLinkTests.cs +++ b/test/Lsp.Integration.Tests/TypedDocumentLinkTests.cs @@ -59,14 +59,14 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink => { return Task.FromResult(documentLink with { Tooltip = "resolved-a" }); }, (_, _) => new DocumentLinkRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); options.OnDocumentLink( codeLensParams => { - return Task.FromResult( + return Task.FromResult?>( new DocumentLinkContainer( new DocumentLink { @@ -82,7 +82,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink => { return Task.FromResult(documentLink with { Tooltip = "resolved-b" }); }, (_, _) => new DocumentLinkRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -101,7 +101,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink => { return Task.FromResult(documentLink with { Tooltip = "resolved-c" }); }, (_, _) => new DocumentLinkRegistrationOptions { - DocumentSelector = DocumentSelector.ForPattern("**/*.cs") + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") } ); @@ -120,7 +120,7 @@ public async Task Should_Aggregate_With_All_Related_Handlers() documentLink => { return Task.FromResult(documentLink with { Tooltip = "resolved-d" }); }, (_, _) => new DocumentLinkRegistrationOptions { - DocumentSelector = DocumentSelector.ForLanguage("vb") + DocumentSelector = TextDocumentSelector.ForLanguage("vb") } ); } diff --git a/test/Lsp.Integration.Tests/TypedInlayHintTests.cs b/test/Lsp.Integration.Tests/TypedInlayHintTests.cs new file mode 100644 index 000000000..e104c8fe0 --- /dev/null +++ b/test/Lsp.Integration.Tests/TypedInlayHintTests.cs @@ -0,0 +1,434 @@ +using System; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using FluentAssertions; +using Lsp.Integration.Tests.Fixtures; +using Newtonsoft.Json.Linq; +using NSubstitute; +using OmniSharp.Extensions.JsonRpc.Testing; +using OmniSharp.Extensions.LanguageProtocol.Testing; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using Serilog.Events; +using Xunit; +using Xunit.Abstractions; + +namespace Lsp.Integration.Tests +{ + public class TypedInlayHintTests : LanguageProtocolTestBase + { + public TypedInlayHintTests(ITestOutputHelper outputHelper) : base(new JsonRpcTestOptions().ConfigureForXUnit(outputHelper, LogEventLevel.Verbose)) + { + } + + [Fact] + public async Task Should_Aggregate_With_All_Related_Handlers() + { + var (client, _) = await Initialize( + options => { }, options => + { + var identifier = Substitute.For(); + identifier.GetTextDocumentAttributes(Arg.Any()).Returns( + call => new TextDocumentAttributes(call.ArgAt(0), "file", "csharp") + ); + options.AddTextDocumentIdentifier(identifier); + + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult?>( + new InlayHintContainer( + new InlayHint + { + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + ); + }, + l => + { + return Task.FromResult( + l with + { + TextEdits = new List() + { + new AnnotatedTextEdit() + { + Range = new Range(( 1, 1 ), ( 1, 3 )), + AnnotationId = "id1", + NewText = "MyText1" + } + }, + } + ); + }, + (_, _) => new InlayHintRegistrationOptions + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Kind = InlayHintKind.Parameter, + Label = new StringOrInlayHintLabelParts("my hint"), + Position = ( 1, 2 ), + PaddingLeft = true, + PaddingRight = true, + Data = new Nested + { + Date = DateTimeOffset.Now + } + } + ) + ); + }, + l => + { + return Task.FromResult( + l with + { + TextEdits = new List() + { + new TextEdit() + { + Range = new Range(( 1, 1 ), ( 1, 3 )), + NewText = "MyText2" + } + }, + } + ); + }, + (_, _) => new InlayHintRegistrationOptions + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Kind = InlayHintKind.Parameter, + Label = "my hint", + Position = ( 1, 2 ), + PaddingLeft = true, + PaddingRight = true, + } + ) + ); + }, + l => + { + return Task.FromResult( + l with + { + TextEdits = new List() + { + new AnnotatedTextEdit() + { + Range = new Range(( 1, 1 ), ( 1, 3 )), + AnnotationId = "id3", + NewText = "MyText3" + } + }, + } + ); + }, + (_, _) => new InlayHintRegistrationOptions + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + } + ) + ); + }, + l => { return Task.FromResult(l with + { + TextEdits = new List() + { + new AnnotatedTextEdit() + { + Range = new Range(( 1, 1 ), ( 1, 3 )), + AnnotationId = "id4", + NewText = "Not Found" + } + } + }); }, + (_, _) => new InlayHintRegistrationOptions + { + DocumentSelector = TextDocumentSelector.ForLanguage("vb") + } + ); + } + ); + + var inlayHints = await client.RequestInlayHints( + new InlayHintParams + { + TextDocument = new TextDocumentIdentifier("/some/path/file.cs"), + } + ); + + var lens = inlayHints.ToArray(); + + var responses = (await Task.WhenAll(lens.Select(z => client.ResolveInlayHint(z)))).SelectMany(z => z.TextEdits ?? Array.Empty()).ToArray(); + responses.Select(z => z.NewText).Should().Contain(new[] { "MyText1", "MyText2", "MyText3" }); + responses.Select(z => z.NewText).Should().NotContain("Not Found"); + lens.Length.Should().Be(3); + responses.OfType().Should().HaveCount(2); + } + + [Fact] + public async Task Should_Resolve_With_Data_Capability() + { + var (client, _) = await Initialize( + options => { }, options => + { + options.OnInlayHints( + (InlayHintParams, capability, token) => + { + return Task.FromResult?>( + new InlayHintContainer( + new InlayHint + { + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + ); + }, + (lens, capability, token) => + { + lens.Data.Id.Should().NotBeEmpty(); + lens.Data.Child.Should().NotBeNull(); + lens.Data.Name.Should().Be("name"); + return Task.FromResult(lens with { Data = lens.Data with { Name = "resolved"} }); + }, + (_, _) => new InlayHintRegistrationOptions() + ); + } + ); + + var items = await client.TextDocument.RequestInlayHints(new InlayHintParams()); + var item = items.Single(); + + item = await client.ResolveInlayHint(item); + item.GetRawData()!.Name.Should().Be("resolved"); + } + + [Fact] + public async Task Should_Resolve_With_Data_CancellationToken() + { + var (client, _) = await Initialize( + options => { }, options => + { + options.OnInlayHints( + (InlayHintParams, token) => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + ); + }, + (inlayHint, token) => + { + inlayHint.Data.Id.Should().NotBeEmpty(); + inlayHint.Data.Child.Should().NotBeNull(); + inlayHint.Data.Name.Should().Be("name"); + return Task.FromResult(inlayHint with { Data = inlayHint.Data with { Name = "resolved"} }); + }, + (_, _) => new InlayHintRegistrationOptions() + ); + } + ); + + var items = await client.RequestInlayHints(new InlayHintParams()); + + var item = items.Single(); + + item = await client.ResolveInlayHint(item); + item.GetRawData()!.Name.Should().Be("resolved"); + } + + [Fact] + public async Task Should_Resolve_With_Data() + { + var (client, _) = await Initialize( + options => { }, options => + { + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + ); + }, + inlayHint => + { + inlayHint.Data.Id.Should().NotBeEmpty(); + inlayHint.Data.Child.Should().NotBeNull(); + inlayHint.Data.Name.Should().Be("name"); + return Task.FromResult(inlayHint with { Data = inlayHint.Data with { Name = "resolved"} }); + }, + (_, _) => new InlayHintRegistrationOptions() + ); + } + ); + + var items = await client.RequestInlayHints(new InlayHintParams()); + + var item = items.Single(); + + item = await client.ResolveInlayHint(item); + item.GetRawData()!.Name.Should().Be("resolved"); + } + [Fact] + public async Task Should_Resolve_Capability() + { + var (client, _) = await Initialize( + options => { }, options => + { + options.OnInlayHints( + (InlayHintParams, capability, token) => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Data = JObject.FromObject(new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + }) + } + ) + ); + }, + (inlayHint, capability, token) => + { + inlayHint.Data["Name"] = "resolved"; + return Task.FromResult(inlayHint with { Data = inlayHint.Data}); + }, + (_, _) => new InlayHintRegistrationOptions() + ); + } + ); + + var items = await client.RequestInlayHints(new InlayHintParams()); + + var item = items.Single(); + + item = await client.ResolveInlayHint(item); + item.GetRawData()!.Name.Should().Be("resolved"); + } + + [Fact] + public async Task Should_Resolve() + { + var (client, _) = await Initialize( + options => { }, options => + { + options.OnInlayHints( + inlayHintParams => + { + return Task.FromResult( + new InlayHintContainer( + new InlayHint + { + Data = JToken.FromObject(new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + }) + } + ) + ); + }, + inlayHint => + { + inlayHint.Data["Name"] = "resolved"; + return Task.FromResult(inlayHint with { Data = inlayHint.Data}); + }, + (_, _) => new InlayHintRegistrationOptions() + ); + } + ); + + var items = await client.RequestInlayHints(new InlayHintParams()); + + var item = items.Single(); + + item = await client.ResolveInlayHint(item); + item.GetRawData()!.Name.Should().Be("resolved"); + } + } +} diff --git a/test/Lsp.Integration.Tests/TypedTypeHierarchyTests.cs b/test/Lsp.Integration.Tests/TypedTypeHierarchyTests.cs new file mode 100644 index 000000000..ffaa80f78 --- /dev/null +++ b/test/Lsp.Integration.Tests/TypedTypeHierarchyTests.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using FluentAssertions; +using Lsp.Integration.Tests.Fixtures; +using NSubstitute; +using OmniSharp.Extensions.JsonRpc.Testing; +using OmniSharp.Extensions.LanguageProtocol.Testing; +using OmniSharp.Extensions.LanguageServer.Protocol; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using Serilog.Events; +using Xunit; +using Xunit.Abstractions; + +namespace Lsp.Integration.Tests +{ + public class TypedTypeHierarchyTests : LanguageProtocolTestBase + { + public TypedTypeHierarchyTests(ITestOutputHelper outputHelper) : base(new JsonRpcTestOptions().ConfigureForXUnit(outputHelper, LogEventLevel.Verbose)) + { + } + + [Fact] + public async Task Should_Aggregate_With_All_Related_Handlers() + { + var subtypeHandlerA = Substitute.For, Task?>>>(); + var subtypeHandlerB = Substitute.For, Task?>>>(); + var supertypeHandlerA = Substitute.For, Task?>>>(); + var supertypeHandlerB = Substitute.For, Task?>>>(); + var (client, _) = await Initialize( + options => { options.EnableAllCapabilities(); }, options => + { + var identifier = Substitute.For(); + identifier.GetTextDocumentAttributes(Arg.Any()).Returns( + call => new TextDocumentAttributes(call.ArgAt(0), "file", "csharp") + ); + options.AddTextDocumentIdentifier(identifier); + + options.OnTypeHierarchy( + @params => Task.FromResult( + new Container?>( + new TypeHierarchyItem + { + Name = "Test", + Kind = SymbolKind.Boolean, + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + )!, + supertypeHandlerA, + subtypeHandlerA, + (_, _) => new() + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + + options.OnTypeHierarchy( + @params => Task.FromResult( + new Container?>( + new TypeHierarchyItem + { + Name = "Test Nested", + Kind = SymbolKind.Constant, + Data = new Nested + { + Date = DateTimeOffset.MinValue + } + } + ) + )!, + supertypeHandlerB, + subtypeHandlerB, + (_, _) => new() + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + } + ); + + var items = await client.RequestTypeHierarchyPrepare( + new TypeHierarchyPrepareParams + { + TextDocument = new TextDocumentIdentifier("/some/path/file.cs"), + } + ); + + var lens = items.ToArray(); + lens.Select(z => z.Name).Should().Contain(new[] { "Test", "Test Nested" }); + + var subtypeItems = await Task.WhenAll( + lens.Select(z => client.RequestTypeHierarchySubtypes(new TypeHierarchySubtypesParams { Item = z }).AsTask()) + ); + subtypeHandlerA.Received(1).Invoke(Arg.Any>()); + subtypeHandlerB.Received(1).Invoke(Arg.Any>()); + var supertypeItems = await Task.WhenAll( + lens.Select(z => client.RequestTypeHierarchySupertypes(new TypeHierarchySupertypesParams { Item = z }).AsTask()) + ); + supertypeHandlerA.Received(1).Invoke(Arg.Any>()); + supertypeHandlerB.Received(1).Invoke(Arg.Any>()); + } + + [Fact] + public async Task Should_Resolve_With_Data_Capability() + { + var subtypeHandler = Substitute.For, Task?>>>(); + var supertypeHandler = Substitute.For, Task?>>>(); + var (client, _) = await Initialize( + options => { options.EnableAllCapabilities(); }, options => + { + options.OnTypeHierarchy( + @params => Task.FromResult( + new Container?>( + new TypeHierarchyItem + { + Name = "Test", + Kind = SymbolKind.Boolean, + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + )!, + supertypeHandler, + subtypeHandler, + (_, _) => new() + { + DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") + } + ); + } + ); + + var items = await client.RequestTypeHierarchyPrepare( + new TypeHierarchyPrepareParams + { + TextDocument = new TextDocumentIdentifier("/some/path/file.cs"), + } + ); + + var item = items.Single(); + + var subtypeItems = await client.RequestTypeHierarchySubtypes(new TypeHierarchySubtypesParams { Item = item }); + subtypeHandler.Received(1).Invoke(Arg.Any>()); + var supertypeItems = await client.RequestTypeHierarchySupertypes(new TypeHierarchySupertypesParams { Item = item }); + supertypeHandler.Received(1).Invoke(Arg.Any>()); + } + + [Fact] + public async Task Should_Resolve_With_Partial_Data_Capability() + { + var subtypeHandler = Substitute.For, IObserver>>>(); + var supertypeHandler = Substitute.For, IObserver>>>(); + var (client, _) = await Initialize( + options => { }, options => + { + options.OnTypeHierarchy( + (completionParams, observer) => + { + var a = new Container?>( + new Container?>( + new TypeHierarchyItem + { + Name = "Test", + Kind = SymbolKind.Boolean, + Data = new Data + { + Child = new Nested + { + Date = DateTimeOffset.MinValue + }, + Id = Guid.NewGuid(), + Name = "name" + } + } + ) + ); + + observer.OnNext(a); + observer.OnCompleted(); + }, + (a, b) => + { + supertypeHandler(a, b); + b.OnNext(Enumerable.Empty()); + b.OnCompleted(); + }, + (a, b) => + { + subtypeHandler(a, b); + b.OnNext(Enumerable.Empty()); + b.OnCompleted(); + }, + (_, _) => new() + ); + } + ); + + var items = await client + .RequestTypeHierarchyPrepare(new TypeHierarchyPrepareParams { TextDocument = new TextDocumentIdentifier("/some/path/file.cs"), }) + .Take(1) + .ToTask(CancellationToken); + + var item = items.Single(); + + var subtypeItems = await client + .RequestTypeHierarchySubtypes(new TypeHierarchySubtypesParams { Item = item }) + .Take(1) + .ToTask(CancellationToken); + subtypeHandler.Received(1).Invoke(Arg.Any>(), Arg.Any>>()); + var supertypeItems = await client + .RequestTypeHierarchySupertypes(new TypeHierarchySupertypesParams { Item = item }) + .Take(1) + .ToTask(CancellationToken); + supertypeHandler.Received(1).Invoke(Arg.Any>(), Arg.Any>>()); + } + } +} diff --git a/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests.cs b/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests.cs index 3741dc966..0d01e9426 100644 --- a/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests.cs +++ b/test/Lsp.Tests/Capabilities/Client/ClientCapabilitiesTests.cs @@ -55,7 +55,7 @@ public void SimpleTest(string expected) DynamicRegistration = true, LinkSupport = true }, - Synchronization = new SynchronizationCapability { + Synchronization = new TextSynchronizationCapability { DynamicRegistration = true, WillSave = true, DidSave = true, diff --git a/test/Lsp.Tests/Capabilities/Client/SynchronizationCapabilityTests.cs b/test/Lsp.Tests/Capabilities/Client/SynchronizationCapabilityTests.cs index df9269189..0b21cabe3 100644 --- a/test/Lsp.Tests/Capabilities/Client/SynchronizationCapabilityTests.cs +++ b/test/Lsp.Tests/Capabilities/Client/SynchronizationCapabilityTests.cs @@ -12,7 +12,7 @@ public class SynchronizationCapabilityTests [JsonFixture] public void SimpleTest(string expected) { - var model = new SynchronizationCapability { + var model = new TextSynchronizationCapability { WillSave = false, WillSaveWaitUntil = false, DidSave = false, @@ -22,7 +22,7 @@ public void SimpleTest(string expected) result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } } diff --git a/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests.cs b/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests.cs index faa8c4286..d4c3b623b 100644 --- a/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests.cs +++ b/test/Lsp.Tests/Capabilities/Client/TextDocumentClientCapabilitiesTests.cs @@ -38,7 +38,7 @@ public void SimpleTest(string expected) SnippetSupport = true } }, - Synchronization = new SynchronizationCapability { + Synchronization = new TextSynchronizationCapability { DynamicRegistration = true, WillSave = true, DidSave = true, diff --git a/test/Lsp.Tests/ClientCapabilityProviderTests.cs b/test/Lsp.Tests/ClientCapabilityProviderTests.cs index 4168c7d8d..a7509f88f 100644 --- a/test/Lsp.Tests/ClientCapabilityProviderTests.cs +++ b/test/Lsp.Tests/ClientCapabilityProviderTests.cs @@ -32,7 +32,7 @@ public class ClientCapabilityProviderTests public void Should_AllowSupportedCapabilities(IJsonRpcHandler handler, object instance) { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = new SharedHandlerCollection( @@ -77,7 +77,7 @@ public void Should_AllowSupportedCapabilities(IJsonRpcHandler handler, object in public void Should_AllowUnsupportedCapabilities(IJsonRpcHandler handler, object instance) { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = new SharedHandlerCollection( @@ -115,7 +115,7 @@ public void Should_AllowUnsupportedCapabilities(IJsonRpcHandler handler, object public void Should_AllowNullSupportedCapabilities(IJsonRpcHandler handler, object instance) { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = new SharedHandlerCollection( @@ -154,7 +154,7 @@ public void Should_AllowNullSupportedCapabilities(IJsonRpcHandler handler, objec public void Should_DisallowDynamicSupportedCapabilities(IJsonRpcHandler handler, object instance) { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = new SharedHandlerCollection( @@ -194,7 +194,7 @@ public void Should_DisallowDynamicSupportedCapabilities(IJsonRpcHandler handler, public void Should_Handle_Mixed_Capabilities() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var codeActionHandler = Substitute.For(); var definitionHandler = Substitute.For(); @@ -243,7 +243,7 @@ public void Should_Handle_Mixed_Capabilities() public void GH162_TextDocumentSync_Should_Work_Without_WillSave_Or_WillSaveWaitUntil() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var collection = new SharedHandlerCollection( @@ -263,7 +263,7 @@ public void GH162_TextDocumentSync_Should_Work_Without_WillSave_Or_WillSaveWaitU { TextDocument = new TextDocumentClientCapabilities { - Synchronization = new SynchronizationCapability + Synchronization = new TextSynchronizationCapability { DidSave = true, DynamicRegistration = false, @@ -280,7 +280,7 @@ public void GH162_TextDocumentSync_Should_Work_Without_WillSave_Or_WillSaveWaitU public void GH162_TextDocumentSync_Should_Work_With_WillSave_Or_WillSaveWaitUntil() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var willSaveTextDocumentHandler = Substitute.For(); var willSaveWaitUntilTextDocumentHandler = Substitute.For(); var didSaveTextDocumentHandler = Substitute.For(); @@ -306,7 +306,7 @@ public void GH162_TextDocumentSync_Should_Work_With_WillSave_Or_WillSaveWaitUnti { TextDocument = new TextDocumentClientCapabilities { - Synchronization = new SynchronizationCapability + Synchronization = new TextSynchronizationCapability { DidSave = true, DynamicRegistration = false, diff --git a/test/Lsp.Tests/FluentAssertionsExtensions.cs b/test/Lsp.Tests/FluentAssertionsExtensions.cs index abfc4ba60..7378b1acc 100644 --- a/test/Lsp.Tests/FluentAssertionsExtensions.cs +++ b/test/Lsp.Tests/FluentAssertionsExtensions.cs @@ -14,7 +14,7 @@ public static EquivalencyAssertionOptions ConfigureForSupports(this Equiva return options .WithTracing(new TraceWriter(logger ?? NullLogger.Instance)) .ComparingByMembers>() - .ComparingByMembers>() + .ComparingByMembers>() .ComparingByMembers>() .ComparingByMembers>() .ComparingByMembers>() diff --git a/test/Lsp.Tests/FoundationTests.cs b/test/Lsp.Tests/FoundationTests.cs index 88d01deee..a46838a9c 100644 --- a/test/Lsp.Tests/FoundationTests.cs +++ b/test/Lsp.Tests/FoundationTests.cs @@ -142,7 +142,7 @@ public void Debugger_Display_Should_Not_Throw(Type type) { var instance = Activator.CreateInstance(type); var property = type.GetProperty("DebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance)!; - var a1 = () => ( property.GetValue(instance) as string )!; + var a1 = () => (property.GetValue(instance) as string)!; var a2 = () => instance!.ToString()!; a1.Should().NotThrow().And.NotBeNull(); @@ -205,7 +205,7 @@ public void Registration_Converters_Should_Have_THe_Same_Properties(Type type) source.Should().Contain(destination); } - [Theory(DisplayName = "Handler interfaces should have a abstract class")] + [Theory(DisplayName = "Handler interfaces should have an class")] [ClassData(typeof(TypeHandlerData))] public void HandlersShouldAbstractClass(ILspHandlerTypeDescriptor descriptor) { @@ -392,6 +392,7 @@ Func ForAnyParameter(Func m) var returns = ForAnyParameter(info => info.ParameterType.GetGenericArguments().LastOrDefault() == returnType); var isAction = ForAnyParameter(info => info.ParameterType.Name.StartsWith(nameof(Action))); var isFunc = ForAnyParameter(info => info.ParameterType.Name.StartsWith("Func")); + var takesParameter = ForAnyParameter(info => info.ParameterType.GetGenericArguments().FirstOrDefault() == descriptor.ParamsType); var takesCapability = ForAnyParameter(info => info.ParameterType.GetGenericArguments().Skip(1).FirstOrDefault() == descriptor.CapabilityType); @@ -522,6 +523,7 @@ Func ForAnyParameter(Func m) Func isAction = info => info.ReturnType.Name == "Void"; Func takesParameter = info => info.GetParameters().Skip(1).Any(z => z.ParameterType == descriptor.ParamsType); + if (!TypeHandlerExtensionData.HandlersToSkip.All(z => descriptor.HandlerType != z)) return; if (descriptor.IsRequest && descriptor.HasPartialItems) { Func partialReturnType = info => @@ -688,7 +690,7 @@ public HandlersShouldHaveMethodAttributeData() { 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) }) + .Except(new[] { typeof(ITextDocumentSyncHandler), typeof(INotebookDocumentSyncHandler) }) ) { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; @@ -731,7 +733,7 @@ public TypeHandlerData() ); 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), typeof(IExecuteCommandHandler<>) }) + .Except(new[] { typeof(ITextDocumentSyncHandler), typeof(INotebookDocumentSyncHandler), typeof(IExecuteCommandHandler<>) }) ) { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; @@ -747,7 +749,10 @@ public class TypeHandlerExtensionData : TheoryData z.IsInterface && typeof(IJsonRpcHandler).IsAssignableFrom(z)) .Where(z => !z.Name.EndsWith("Manager")) - .Except(new[] { typeof(ITextDocumentSyncHandler) }) + .Except(new[] { typeof(ITextDocumentSyncHandler), typeof(INotebookDocumentSyncHandler) }) ) { if (type.IsGenericTypeDefinition && !MethodAttribute.AllFrom(type).Any()) continue; @@ -813,7 +818,7 @@ private static Type GetExtensionClass(IHandlerTypeDescriptor descriptor) { var name = GetExtensionClassName(descriptor); return descriptor.HandlerType.Assembly.GetExportedTypes() - .FirstOrDefault(z => z.IsClass && z.IsAbstract && ( z.Name == name || z.Name == name + "Base" ))!; + .FirstOrDefault(z => z.IsClass && z.IsAbstract && (z.Name == name || z.Name == name + "Base"))!; } private static string GetOnMethodName(IHandlerTypeDescriptor descriptor) diff --git a/test/Lsp.Tests/HandlerResolverTests.cs b/test/Lsp.Tests/HandlerResolverTests.cs index 6273d6259..e311e6601 100644 --- a/test/Lsp.Tests/HandlerResolverTests.cs +++ b/test/Lsp.Tests/HandlerResolverTests.cs @@ -68,7 +68,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"); + var sub = (IJsonRpcHandler) TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.something"), "csharp"); handler.Add(sub); handler.Should().Contain(x => x.Method == key); @@ -133,9 +133,9 @@ 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 sub = TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); - var sub2 = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); + var sub2 = TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cake"), "csharp"); handler.Add(sub); handler.Add(sub2); @@ -155,7 +155,7 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer(Type requestHandle reg.GetRegistrationOptions(Arg.Any()) .Returns( new TextDocumentSyncRegistrationOptions() { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); handler.Add(sub); @@ -176,7 +176,7 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys( reg.GetRegistrationOptions(Arg.Any()) .Returns( new TextDocumentSyncRegistrationOptions { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); var sub2 = (IJsonRpcHandler) Substitute.For(new[] { requestHandler, type2 }, new object[0]); @@ -184,7 +184,7 @@ public void Should_Contain_AllDefinedMethods_OnLanguageServer_WithDifferentKeys( reg2.GetRegistrationOptions(Arg.Any()) .Returns( new TextDocumentSyncRegistrationOptions { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); handler.Add(sub); @@ -232,7 +232,7 @@ public void Should_DealWithClassesThatImplementMultipleHandlers_BySettingKeyAcco ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { - DocumentSelector = new DocumentSelector(DocumentFilter.ForLanguage("foo")) + DocumentSelector = new TextDocumentSelector(TextDocumentFilter.ForLanguage("foo")) } ); @@ -251,7 +251,7 @@ public static IEnumerable Should_DealWithClassesThatImplementMultipleH ( (ICodeLensHandler) codeLensHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); @@ -261,7 +261,7 @@ public static IEnumerable Should_DealWithClassesThatImplementMultipleH ( (IDocumentLinkHandler) documentLinkHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new DocumentLinkRegistrationOptions { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); @@ -271,7 +271,7 @@ public static IEnumerable Should_DealWithClassesThatImplementMultipleH ( (ICompletionHandler) completionHandler ).GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CompletionRegistrationOptions { - DocumentSelector = new DocumentSelector() + DocumentSelector = new TextDocumentSelector() } ); diff --git a/test/Lsp.Tests/LspRequestRouterTests.cs b/test/Lsp.Tests/LspRequestRouterTests.cs index 1774e5f28..a017aeaa6 100644 --- a/test/Lsp.Tests/LspRequestRouterTests.cs +++ b/test/Lsp.Tests/LspRequestRouterTests.cs @@ -45,7 +45,7 @@ public LspRequestRouterTests(ITestOutputHelper testOutputHelper) : base(testOutp public async Task ShouldRouteToCorrect_Notification() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); @@ -83,9 +83,9 @@ await textDocumentSyncHandler.Received(1) public async Task ShouldRouteToCorrect_Notification_WithManyHandlers() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentSyncHandler2 = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cake"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); textDocumentSyncHandler2.Handle(Arg.Any(), Arg.Any()) @@ -131,12 +131,12 @@ await textDocumentSyncHandler2.Received(1) public async Task ShouldRouteToCorrect_Request() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CommandOrCodeActionContainer()); @@ -175,16 +175,16 @@ public async Task ShouldRouteToCorrect_Request() public async Task ShouldRouteToCorrect_Request_WithManyHandlers() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentSyncHandler2 = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cake"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); textDocumentSyncHandler2.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CommandOrCodeActionContainer()); @@ -196,7 +196,7 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers() .Returns(new CommandOrCodeActionContainer()); registry.OnCodeAction( codeActionDelegate, - (_, _) => new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") } + (_, _) => new CodeActionRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cake") } ); var textDocumentIdentifiers = new TextDocumentIdentifiers(); @@ -237,22 +237,22 @@ public async Task ShouldRouteToCorrect_Request_WithManyHandlers() public async Task ShouldRouteToCorrect_Request_WithManyHandlers_CodeLensHandler() { var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentSyncHandler2 = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cake"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cake"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); textDocumentSyncHandler2.Handle(Arg.Any(), Arg.Any()) .Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns(new CodeLensContainer()); var codeActionHandler2 = Substitute.For(); - codeActionHandler2.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cake") }); + codeActionHandler2.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeLensRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cake") }); codeActionHandler2 .Handle(Arg.Any(), Arg.Any()) .Returns(new CodeLensContainer()); diff --git a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs index 424c9a75e..1d3271072 100644 --- a/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs +++ b/test/Lsp.Tests/Matchers/TextDocumentMatcherTests.cs @@ -90,7 +90,7 @@ public void Should_Return_Did_Open_Text_Document_Handler_Descriptor() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -121,7 +121,7 @@ public void Should_Return_Did_Open_Text_Document_Handler_Descriptor_With_Sepcial { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cshtml"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cshtml"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -152,7 +152,7 @@ public void Should_Return_Did_Change_Text_Document_Descriptor() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -181,7 +181,7 @@ public void Should_Return_Did_Save_Text_Document_Descriptor() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -210,7 +210,7 @@ public void Should_Return_Did_Close_Text_Document_Descriptor() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -239,7 +239,7 @@ public void Should_Return_Code_Lens_Descriptor() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); var textDocumentIdentifiers = new TextDocumentIdentifiers(); AutoSubstitute.Provide(textDocumentIdentifiers); var collection = new SharedHandlerCollection(SupportedCapabilitiesFixture.AlwaysTrue, textDocumentIdentifiers, Substitute.For(), @@ -253,7 +253,7 @@ public void Should_Return_Code_Lens_Descriptor() codeLensHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { - DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.cs" }) + DocumentSelector = new TextDocumentSelector(new TextDocumentFilter { Pattern = "**/*.cs" }) } ); @@ -261,7 +261,7 @@ public void Should_Return_Code_Lens_Descriptor() codeLensHandler2.GetRegistrationOptions(Arg.Any(), Arg.Any()) .Returns( new CodeLensRegistrationOptions { - DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.cake" }) + DocumentSelector = new TextDocumentSelector(new TextDocumentFilter { Pattern = "**/*.cake" }) } ); collection.Add(codeLensHandler, codeLensHandler2); @@ -294,11 +294,11 @@ public void Should_Return_Did_Folding_Range_handler() { // Given var textDocumentSyncHandler = - TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.ps*1"), "powershell"); + TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.ps*1"), "powershell"); var handler = Substitute.For(); handler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns( new FoldingRangeRegistrationOptions { - DocumentSelector = new DocumentSelector(new DocumentFilter { Pattern = "**/*.ps*1" }) + DocumentSelector = new TextDocumentSelector(new TextDocumentFilter { Pattern = "**/*.ps*1" }) } ); var textDocumentIdentifiers = new TextDocumentIdentifiers(); diff --git a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs index e322ee26f..a49a11af9 100644 --- a/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs +++ b/test/Lsp.Tests/MediatorTestsRequestHandlerOfTRequestTResponse.cs @@ -34,11 +34,11 @@ public class MediatorTestsRequestHandlerOfTRequestTResponse : AutoTestBase [Fact] public async Task RequestsCancellation() { - var textDocumentSyncHandler = TextDocumentSyncHandlerExtensions.With(DocumentSelector.ForPattern("**/*.cs"), "csharp"); + var textDocumentSyncHandler = TextDocumentSyncHandlerExtensions.With(TextDocumentSelector.ForPattern("**/*.cs"), "csharp"); textDocumentSyncHandler.Handle(Arg.Any(), Arg.Any()).Returns(Unit.Value); var codeActionHandler = Substitute.For(); - codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = DocumentSelector.ForPattern("**/*.cs") }); + codeActionHandler.GetRegistrationOptions(Arg.Any(), Arg.Any()).Returns(new CodeActionRegistrationOptions { DocumentSelector = TextDocumentSelector.ForPattern("**/*.cs") }); codeActionHandler .Handle(Arg.Any(), Arg.Any()) .Returns( diff --git a/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests.cs index ddcd2a9ce..f1bf752f1 100644 --- a/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/CodeActionRegistrationOptionsTests.cs @@ -14,12 +14,12 @@ public class CodeActionRegistrationOptionsTests public void SimpleTest(string expected) { var model = new CodeActionRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp", Pattern = "pattern", Scheme = "scheme" - }, new DocumentFilter { + }, new TextDocumentFilter { Language = "vb", Pattern = "pattern", Scheme = "scheme" diff --git a/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests.cs index 6580c82e1..4642672a8 100644 --- a/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/CodeLensRegistrationOptionsTests.cs @@ -14,12 +14,12 @@ public class CodeLensRegistrationOptionsTests public void SimpleTest(string expected) { var model = new CodeLensRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp", Pattern = "pattern", Scheme = "scheme" - }, new DocumentFilter { + }, new TextDocumentFilter { Language = "vb", Pattern = "pattern", Scheme = "scheme" diff --git a/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests.cs index c2ac494e5..6e1469343 100644 --- a/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/CompletionRegistrationOptionsTests.cs @@ -14,8 +14,8 @@ public class CompletionRegistrationOptionsTests public void SimpleTest(string expected) { var model = new CompletionRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/Models/DocumentFilterTests.cs b/test/Lsp.Tests/Models/DocumentFilterTests.cs index 5bc97de06..f7e9330db 100644 --- a/test/Lsp.Tests/Models/DocumentFilterTests.cs +++ b/test/Lsp.Tests/Models/DocumentFilterTests.cs @@ -13,12 +13,12 @@ public class DocumentFilterTests [JsonFixture] public void Empty(string expected) { - var model = new DocumentFilter(); + var model = new TextDocumentFilter(); var result = Fixture.SerializeObject(model); result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } @@ -26,14 +26,14 @@ public void Empty(string expected) [JsonFixture] public void OnlyLanguage(string expected) { - var model = new DocumentFilter { + var model = new TextDocumentFilter { Language = "csharp" }; var result = Fixture.SerializeObject(model); result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } @@ -41,14 +41,14 @@ public void OnlyLanguage(string expected) [JsonFixture] public void OnlyScheme(string expected) { - var model = new DocumentFilter { + var model = new TextDocumentFilter { Scheme = "abc" }; var result = Fixture.SerializeObject(model); result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } @@ -56,14 +56,14 @@ public void OnlyScheme(string expected) [JsonFixture] public void OnlyPattern(string expected) { - var model = new DocumentFilter { + var model = new TextDocumentFilter { Pattern = "123**" }; var result = Fixture.SerializeObject(model); result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } @@ -71,7 +71,7 @@ public void OnlyPattern(string expected) [JsonFixture] public void Mixed(string expected) { - var model = new DocumentFilter { + var model = new TextDocumentFilter { Pattern = "123**", Language = "csharp" }; @@ -79,7 +79,7 @@ public void Mixed(string expected) result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } @@ -87,7 +87,7 @@ public void Mixed(string expected) [JsonFixture] public void Full(string expected) { - var model = new DocumentFilter { + var model = new TextDocumentFilter { Pattern = "123**", Language = "csharp", Scheme = "abc" @@ -96,7 +96,7 @@ public void Full(string expected) result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } } diff --git a/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests.cs index 5cdf60282..bcbc3b33b 100644 --- a/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/DocumentLinkRegistrationOptionsTests.cs @@ -14,8 +14,8 @@ public class DocumentLinkRegistrationOptionsTests public void SimpleTest(string expected) { var model = new DocumentLinkRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests.cs index a0d8a54dc..dc2e08b0e 100644 --- a/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/DocumentOnTypeFormattingRegistrationOptionsTests.cs @@ -14,8 +14,8 @@ public class DocumentOnTypeFormattingRegistrationOptionsTests public void SimpleTest(string expected) { var model = new DocumentOnTypeFormattingRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/Models/DocumentSelectorTests.cs b/test/Lsp.Tests/Models/DocumentSelectorTests.cs index e0662a017..c342f531d 100644 --- a/test/Lsp.Tests/Models/DocumentSelectorTests.cs +++ b/test/Lsp.Tests/Models/DocumentSelectorTests.cs @@ -13,12 +13,12 @@ public class DocumentSelectorTests [JsonFixture] public void SimpleTest(string expected) { - var model = new DocumentSelector( - new DocumentFilter { + var model = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp", - }, new DocumentFilter { + }, new TextDocumentFilter { Pattern = "**/*.vb" - }, new DocumentFilter { + }, new TextDocumentFilter { Scheme = "visualbasic" } ); @@ -26,7 +26,7 @@ public void SimpleTest(string expected) result.Should().Be(expected); - var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); + var deresult = new LspSerializer(ClientVersion.Lsp3).DeserializeObject(expected); deresult.Should().BeEquivalentTo(model, x => x.UsingStructuralRecordEquality()); } } diff --git a/test/Lsp.Tests/Models/InitializeParamsTests.cs b/test/Lsp.Tests/Models/InitializeParamsTests.cs index 84f74a7a4..71e953074 100644 --- a/test/Lsp.Tests/Models/InitializeParamsTests.cs +++ b/test/Lsp.Tests/Models/InitializeParamsTests.cs @@ -45,7 +45,7 @@ public void SimpleTest(string expected) SnippetSupport = true } }, - Synchronization = new SynchronizationCapability { + Synchronization = new TextSynchronizationCapability { DynamicRegistration = true, WillSave = true, DidSave = true, diff --git a/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests.cs index 026d9a736..38ad96d60 100644 --- a/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/SignatureHelpRegistrationOptionsTests.cs @@ -14,8 +14,8 @@ public class SignatureHelpRegistrationOptionsTests public void SimpleTest(string expected) { var model = new SignatureHelpRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/Models/TextDocumentChangeRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/TextDocumentChangeRegistrationOptionsTests.cs index 3433e8b21..5d92be46b 100644 --- a/test/Lsp.Tests/Models/TextDocumentChangeRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/TextDocumentChangeRegistrationOptionsTests.cs @@ -15,8 +15,8 @@ public class TextDocumentChangeRegistrationOptionsTests public void SimpleTest(string expected) { var model = new TextDocumentChangeRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/Models/TextDocumentSaveRegistrationOptionsTests.cs b/test/Lsp.Tests/Models/TextDocumentSaveRegistrationOptionsTests.cs index a25d5231a..f7bac42c3 100644 --- a/test/Lsp.Tests/Models/TextDocumentSaveRegistrationOptionsTests.cs +++ b/test/Lsp.Tests/Models/TextDocumentSaveRegistrationOptionsTests.cs @@ -14,8 +14,8 @@ public class TextDocumentSaveRegistrationOptionsTests public void SimpleTest(string expected) { var model = new TextDocumentSaveRegistrationOptions { - DocumentSelector = new DocumentSelector( - new DocumentFilter { + DocumentSelector = new TextDocumentSelector( + new TextDocumentFilter { Language = "csharp" } ), diff --git a/test/Lsp.Tests/SemanticTokensDocumentTests.cs b/test/Lsp.Tests/SemanticTokensDocumentTests.cs index 41752c565..71ded91b9 100644 --- a/test/Lsp.Tests/SemanticTokensDocumentTests.cs +++ b/test/Lsp.Tests/SemanticTokensDocumentTests.cs @@ -299,14 +299,14 @@ private void Tokenize(string document, SemanticTokensBuilder builder) var faker = new Faker() .RuleFor( z => z.Type, - f => f.PickRandom(SemanticTokenType.Defaults).OrNull(f, 0.2f) ?? new SemanticTokenType("none") + f => f.PickRandom(_legend.TokenTypes.AsEnumerable()).OrNull(f, 0.2f) ?? new SemanticTokenType("none") ) .RuleFor( x => x.Modifiers, f => Enumerable.Range(0, f.Random.Int(0, 3)) .Select( z => - f.PickRandom(SemanticTokenModifier.Defaults).OrNull(f, 0.2f) ?? + f.PickRandom(_legend.TokenModifiers.AsEnumerable()).OrNull(f, 0.2f) ?? new SemanticTokenModifier("none") ) .ToArray() @@ -503,6 +503,6 @@ static void Main(string[] args) } } } -".Replace("\r\n", "\n"); +".Replace("\r\n", "\n", StringComparison.Ordinal); } } diff --git a/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs b/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs index 93e010b9a..e899ca4a1 100644 --- a/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs +++ b/test/Lsp.Tests/TextDocumentSyncHandlerExtensions.cs @@ -8,15 +8,15 @@ namespace Lsp.Tests { internal static class TextDocumentSyncHandlerExtensions { - public static ITextDocumentSyncHandler With(DocumentSelector? documentSelector, string language) => + public static ITextDocumentSyncHandler With(TextDocumentSelector? documentSelector, string language) => Substitute.For().With(documentSelector, language); - public static ITextDocumentSyncHandler With(this ITextDocumentSyncHandler handler, DocumentSelector? documentSelector, string language) + public static ITextDocumentSyncHandler With(this ITextDocumentSyncHandler handler, TextDocumentSelector? documentSelector, string language) { - ( (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 }); + ( (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));