Hoffs / omnisharp-extended-lsp.nvim

Extended 'textDocument/definition' handler for OmniSharp Neovim LSP (now also `textDocument/references`, `textDocument/implementation` and source generated files)
142 stars 18 forks source link

Handler for `textDocument/reference` when source generators are involved? #18

Closed cptchuckles closed 6 months ago

cptchuckles commented 1 year ago

I use Godot engine with C#, which involves the use of source-generators. I noticed that textDocument/reference fails when I try it on any identifier that is referenced in something that's generated, and I'm wondering if it can be solved in a similar way that this plugin is currently solving textDocument/definition?

One of the generators I use is GodotOnReady, such that if I try vim.lsp.buf.references() on a member like this:

[OnReadyGet("something")] private Node _something;

I get the following error:

Error executing vim.schedule lua callback: /usr/share/nvim/runtime/lua/vim/lsp/util.lua:1735: index out of range
stack traceback:
        [C]: in function '_str_byteindex_enc'
        /usr/share/nvim/runtime/lua/vim/lsp/util.lua:1735: in function 'locations_to_items'
        /usr/share/nvim/runtime/lua/vim/lsp/handlers.lua:193: in function 'handler'
        /usr/share/nvim/runtime/lua/vim/lsp.lua:1383: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>

Alas, I don't even know exactly how source generation works (I will be reading up) -- how much more complicated is this problem compared to the problem that this plugin already solves?

Hoffs commented 1 year ago

Hi,

Sorry for late reply, I've been looking into this for a bit now and I have been slowly working on addressing source generated files. Source generated files actually break textDocument/definition as well, since a source of partial class is split between actual class and generated one.

Primary issue is that locations_to_items tries to get a single line from the file to show in quickfix list. This fails for source generated files as they are not accessible. In case of decompiled files, this is worked around by "preloading" buffers with exact names, so that locations_to_items would not fail. Same solution can be applied for source generated files, but these files are not as easily accessible. To get it's contents it is required to provide project id and document id. textDocument/definition and textDocument/reference return just "imaginary" file path, e.g. file:///GodotOnReady.Generator/GodotOnReady.Generator.GodotOnReadySourceGenerator/Partial_TextDocReferenceRepro_MyClass.cs without any of the required id's. To get these id's it is required to use omnisharp native commands like o#/v2/gotodefinition which contain extra info, like source generated file info.

So the fix is not that hard and it is kinda needed to fix textDocument/definition functionality with source generators. I can probably add reference handler too. I will try to get it done this week or so.

cptchuckles commented 1 year ago

Awesome. I had also recently checked how this behaves in VSCode, and the textDocument/definition and reference handlers link to generated files but they are obviously broken links, with the only difference being that VSCode is still able to list real files without the handler failing, but opening generated files shows an error. If you manage to get this working as described, then neovim will actually have a capability that VSCode currently doesn't!

Hoffs commented 1 year ago

If you want, you can try checking out the plugin on branch feat/sourcegen-support. It has support for source generated files and references handler. README in that branch should contain all the information on how to use it. I still got to test it a bit before I merge it to main branch.

cptchuckles commented 1 year ago

This is working beautifully.

Now, I've just noticed we also need this functionality for textDocument/implementations... :smiling_face_with_tear:

Edit: I've just noticed that textDocument/definitions from within a source generated buffer errors, unlike from within a $metadata$ buffer:

Error executing vim.schedule lua callback: ...ker/start/omnisharp-extended-lsp.nvim/lua/definition.lua:77: attempt to concatenate local 'err' (a table
 value)
stack traceback:
        ...ker/start/omnisharp-extended-lsp.nvim/lua/definition.lua:77: in function 'handle_gotodefinition'
        ...ker/start/omnisharp-extended-lsp.nvim/lua/definition.lua:168: in function 'handler'
        /usr/share/nvim/runtime/lua/vim/lsp.lua:1383: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>
Press ENTER or type command to continue

textDocument/hover also throws an error in generated buffers:

omnisharp: -32603: Internal Error - System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'index')
   at Microsoft.CodeAnalysis.Text.SourceText.LineInfo.get_Item(Int32 index)
   at Microsoft.CodeAnalysis.Text.TextLineCollection.GetPosition(LinePosition position)
   at OmniSharp.Extensions.SourceTextExtensions.GetTextPosition(SourceText sourceText, Request request) in /home/vsts/work/1/s/src/OmniSharp.Roslyn/Ex
tensions/SourceTextExtensions.cs:line 11
   at OmniSharp.Roslyn.CSharp.Services.QuickInfoProvider.Handle(QuickInfoRequest request) in /home/vsts/work/1/s/src/OmniSharp.Roslyn.CSharp/Services/
QuickInfoProvider.cs:line 61
   at OmniSharp.LanguageServerProtocol.Handlers.OmniSharpHoverHandler.Handle(HoverParams request, CancellationToken token) in /home/vsts/work/1/s/src/
OmniSharp.LanguageServerProtocol/Handlers/OmniSharpHoverHandler.cs:line 41
   at OmniSharp.Extensions.LanguageServer.Server.Pipelines.SemanticTokensDeltaPipeline`2.Handle(TRequest request, CancellationToken cancellationToken,
 RequestHandlerDelegate`1 next)
   at OmniSharp.Extensions.LanguageServer.Server.Pipelines.ResolveCommandPipeline`2.Handle(TRequest request, CancellationToken cancellationToken, Requ
estHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next
)
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next
)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`
1 next)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`
1 next)
   at OmniSharp.Extensions.JsonRpc.RequestRouterBase`1.<RouteRequest>g__InnerRoute|7_0(IServiceScopeFactory serviceScopeFactory, Request request, TDes
criptor descriptor, Object params, CancellationToken token, ILogger logger)
   at OmniSharp.Extensions.JsonRpc.RequestRouterBase`1.RouteRequest(IRequestDescriptor`1 descriptors, Request request, CancellationToken token)
Press ENTER or type command to continue
   at OmniSharp.Extensions.JsonRpc.DefaultRequestInvoker.<>c__DisplayClass10_0.<<RouteRequest>b__5>d.MoveNext()
Press ENTER or type command to continue
Hoffs commented 1 year ago

Edit: I've just noticed that textDocument/definitions from within a source generated buffer errors, unlike from within a $metadata$ buffer:

As far as I could see this is not supposed to work, due to how source generated files are treated, "objects" rather than files. Plugin error is something that I need to fix tho.

Hoffs commented 6 months ago

Only took almost a year, but the latest version should support source generated files on all commands