Closed cloudRoutine closed 2 years ago
This is definitely something we'd like to get to.
See comments in https://github.com/dotnet/roslyn/issues/16511.
This would be an awesome feature and is holding us back to start using F# in existing C# projects.
Reading through the visualfsharp github I found these tickets that seem to indicate that the Roslyn team should "use SVsSymbolicNavigationManager
" so the visualfsharp team can finish this feature:
https://github.com/Microsoft/visualfsharp/issues/3497 https://github.com/Microsoft/visualfsharp/pull/3357#issuecomment-317261778
Is this correct? Would this be a big change?
I definitely would not want to those ancient APIs for this purpose. It would be good to define something much more modern and usable for this purpose.
@CyrusNajmabadi It turns out you recommended them 😄 https://github.com/dotnet/roslyn/issues/16511#issuecomment-272642995
What more modern alternative could be defined? We did a short investigation into what it took to interface with ISymbol and it was kinda rough
@CyrusNajmabadi It turns out you recommended them 😄 #16511 (comment)
Haha. I'm nothing if not inconsistent :D
What more modern alternative could be defined?
Maybe someting entirely managed. And a proper free threaded, async, cancellable, MEF, interface that simply says: please try to navigate to this definition and return a bool saying if you were able to. maybe something like this:
public interface ISymbolicNavigationService
{
Task<bool> TryNavigateToSymbol(ISymbol symbol, CancellationToken cancellationToken);
Task<bool> TryNavigateToSymbol(string rqName, CancellationToken cancellationToken);
}
Tagging @jasonmalinowski for his thoughts here. It really doesn't seem like it would be super difficult to do this.
It really doesn't seem like it would be super difficult to do this.
Well, it's easy until you said you wanted it free-threaded, cancellable, and async. :smile:
@CyrusNajmabadi @jasonmalinowski is there any way we could make progress on this?
@cartermp am I correct that on the F# side everything is ready to get this feature (jump to definition) to work, and you are just waiting for (something like) ISymbolicNavigationService to be implemented in Roslyn? Can you confirm this?
It would be great if we could realize a quick win here.
@jasonmalinowski
Well, it's easy until you said you wanted it free-threaded, cancellable, and async.
@jannesiera
It would be great if we could realize a quick win here.
I don't think there is any quick win here. We'd have to define the interface and make sure that both sides could understand each other. For example, i know roslyn can produce rqnames... but i'm not sure if we can consume them and map them to symbols (if so, that would make things much easier).
would [free-threaded, cancellable, and async] really be that bad? i mean, all we'd be doing is basically is basically just importing people who could respond to that API. And, similarly, we would respond to it as well.
I guess my observation is the implementation of the API requires things like:
All of which today require us calling into other parts of Visual Studio. And those APIs are all UI-thread bound, offer no cancellation and are synchronous.
Gotcha. I did not think that those parts woudl be under teh purview of this API. This API would just be about the language saying "i can take it from here". i.e. in an async-cancellable manner, it would introspect itself and say "yup! that looks like a symbol from my language (or not)". And it woudl return true/false accordingly. If 'false', nothing left for it to do. If 'true', it would take over and actually do the navigation however it wanted. In this brave-new-world of JTF, it seems like it would just bounce to the UI thread, and tehn navigate however it wanted. But that would not be part of what was represented in this API.
Does that seems reasonable? is it a terrible idea? Thanks!
@CyrusNajmabadi if I were to introduce this interface as a pull request, how would I go about this? Happy to contribute but need some guidance.
I'd probably start with a PR that defines the new interface, then shows how roslyn would both consume it (i.e. notify 3rd parties of a symbol to navigate to) as well as how it would export it (i.e. roslyn could navigate to a symbol on behalf of 3rd party). Let the team look at the interface/impl and make sure nothing is wonky. At the same time, create a PR on F# to show how it could consume/export the same interface (though hve that PR use a copy of hte interface since Roslyn won't actually have published the real thing yet). Once the teams take a look and approve things. Get the interface/impl merged into roslyn. Then, once F# picks up the latest Roslyn bits, move your F# PR over to using the real API.
Does that make sense?
@CyrusNajmabadi I was able to set up a testing environment. Currently, I'm hooking into GoToDefinitionHelpers.TryGoToDefinition since I have a symbol available there and from there I trigger ISymbolicNavigationService.
Besides the fact that this seems like a concern not belonging in GoToDefinitionHelpers, is this somewhat how you envisioned this? Any advice woul be welcome.
Besides the fact that this seems like a concern not belonging in GoToDefinitionHelpers, is this somewhat how you envisioned this? Any advice woul be welcome.
So far so good. It may not be exactly the right location. But it is probably more than good enough to get a ProofOfConcept up and running.
I'd probably start with a PR that defines the new interface, then shows how roslyn would both consume it (i.e. notify 3rd parties of a symbol to navigate to) as well as how it would export it (i.e. roslyn could navigate to a symbol on behalf of 3rd party). Let the team look at the interface/impl and make sure nothing is wonky. At the same time, create a PR on F# to show how it could consume/export the same interface (though hve that PR use a copy of hte interface since Roslyn won't actually have published the real thing yet). Once the teams take a look and approve things. Get the interface/impl merged into roslyn. Then, once F# picks up the latest Roslyn bits, move your F# PR over to using the real API.
Does that make sense?
Do you happen to have a document any where with guidelines when working on issues that cross the boundaries between components? This is pretty clear and doesn't seem like it is terribly specific to the process at hand. Would be nice if these guidelines were some where for people trying to jump in. I wanted to investigate go to definition going from xaml to C# and vice versa but was not sure how I would show a proof of concept for it.
Thanks for writing that up, at the very least I plan on keeping it in mind when I look into issues like this in the future.
The ability to go to a C# definition from F# code works in VS Code. How does VS Code achieve this? Can Visual Studio do the same without the need for a new interface like ISymbolicNavigationService
(as described above)?
@bender2k14 the F# tools for VS also allow navigating to C# constructs. It's C# --> F# that doesn't work.
@cartermp That is true for C# constructs you define in .csproj
s you own, but I don't think that is true for C# whose source code you don't have (like from nuget packages).
@dharmaturtle What you're referring to is a different feature altogether, Go to Metadata. That is unsupported for F# at this time (we have a tracking issue on the F# repo). It's unrelated to C# <-> F# interop.
@cartermp Can you provide a link to that issue?
@bender2k14 https://github.com/dotnet/fsharp/issues/1939
Dupe of https://github.com/dotnet/fsharp/issues/13882. Roslyn has an API for F# to use (https://github.com/dotnet/roslyn/pull/64475). So it's up to them to add this support.
Hi I work on VisualFSharpPowerTools and I've been trying to figure out how to hook into Rosyln's goto definition service to allow jumping from F# source to a class's definition in a C# project. If this is possible I'd really appreciate it if someone could point me to the part of the codebase related to this functionality. Also if there's a service we could expose through VisualFSharpPowerTools or Visual FSharp Tools if it needs to be directly through the language service I'd be happy to implement it to allow definition jumps from C# source to F# projects.