-
Notifications
You must be signed in to change notification settings - Fork 833
VS Go to definition from C# to F# #14377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VS Go to definition from C# to F# #14377
Conversation
|
This is ready for the first iteration, please see comments in the OP, regarding tests and what's supported. |
|
|
||
| let mutable locations = Seq.empty | ||
|
|
||
| for project in projects do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could probably do this in parallel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a fool-proof, we expect it always be only a single project, parallel then will give you a bunch of overhead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, didn't notice where it's coming from. Is it even theoretically possible there will be multiple projects with the same assembly name? Because maybe you could replace filter with tryFind and it would be a bit simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it even theoretically possible there will be multiple projects with the same assembly name?
Very unlikely, I have never seen it before.
Because maybe you could replace
filterwithtryFindand it would be a bit simpler.
I'll see how it looks with option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With option it could look something like this (After also adding DocCommentId.EntityPath):
let project = workspace.CurrentSolution.Projects |> Seq.tryFind (fun p -> p.IsFSharp && p.AssemblyName = assemblyName)
let locations =
project
|> Option.map (fun project ->
let! checker, _, _, options = project.GetFSharpCompilationOptionsAsync(cancellationToken)
let! result = checker.ParseAndCheckProject(options)
let entity = path.EntityPath |> result.AssemblySignature.FindEntityByPath
match path with
| DocCommentId.Member ({ MemberOrValName = memberOrVal; GenericParameters = genericParametersCount }, memberType) ->
entity |> tryFindVal memberOrVal documentationCommentId memberType genericParametersCount
| DocCommentId.Field { MemberOrValName = memberOrVal } ->
entity |> tryFindFieldByName memberOrVal
| DocCommentId.Type _ ->
Seq.singleton entity.DeclarationLocation
| DocCommentId.None ->
Seq.empty
|> Seq.map (fun m -> (m, project)))
|> Option.defaultValue Seq.emptyA bit easier to see what's going on with arrows only going in one direction :)
| | DocCommentId.Member ({ EntityPath = entityPath; MemberOrValName = memberOrVal; GenericParameters = genericParametersCount }, memberType) -> | ||
| let entity = result.AssemblySignature.FindEntityByPath (entityPath) | ||
| match entity with | ||
| | Some e -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably should replace with Option.map/iter or something
|
Annoying question - any idea/chance to test this? |
No, I've asked the same question in the first paragraph |
KevinRansom
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, no tests yet though. (That's rich coming from me :-))
Yeah, that's the question - I'm not yet entirely sure how to do that. |
…ytovskii/fsharp into vs-external-goto-definition
|
Ok, this is ready, I failed (gave up really) to add proper tests in headless VS, but added to the important part - parser for doccomment id. |
WIP VS Go to definition from C# to F#|
|
||
| let mutable locations = Seq.empty | ||
|
|
||
| for project in projects do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With option it could look something like this (After also adding DocCommentId.EntityPath):
let project = workspace.CurrentSolution.Projects |> Seq.tryFind (fun p -> p.IsFSharp && p.AssemblyName = assemblyName)
let locations =
project
|> Option.map (fun project ->
let! checker, _, _, options = project.GetFSharpCompilationOptionsAsync(cancellationToken)
let! result = checker.ParseAndCheckProject(options)
let entity = path.EntityPath |> result.AssemblySignature.FindEntityByPath
match path with
| DocCommentId.Member ({ MemberOrValName = memberOrVal; GenericParameters = genericParametersCount }, memberType) ->
entity |> tryFindVal memberOrVal documentationCommentId memberType genericParametersCount
| DocCommentId.Field { MemberOrValName = memberOrVal } ->
entity |> tryFindFieldByName memberOrVal
| DocCommentId.Type _ ->
Seq.singleton entity.DeclarationLocation
| DocCommentId.None ->
Seq.empty
|> Seq.map (fun m -> (m, project)))
|> Option.defaultValue Seq.emptyA bit easier to see what's going on with arrows only going in one direction :)
T:prefix for typesT:N.X.Nested- typeT:N.X.D- delegateM:prefix is for methodsM:N.X.#ctor- constructorM:N.X.#ctor(System.Int32)- constructor with one parameterM:N.X.f- method with unit parameterM:N.X.bb(System.String,System.Int32@)- method with two parametersM:N.X.gg(System.Int16[],System.Int32[0:,0:])- method with two parameters, 1d and 2d arrayM:N.X.op_Addition(N.X,N.X)- operatorM:N.X.op_Explicit(N.X)~System.Int32- operator with return typeM:N.GenericMethod.WithNestedType``1(N.GenericType{``0}.NestedType)- generic type with one parameterM:N.GenericMethod.WithIntOfNestedType``1(N.GenericType{System.Int32}.NestedType)- generic type with one parameterM:N.X.N#IX{N#KVP{System#String,System#Int32}}#IXA(N.KVP{System.String,System.Int32})- explicit interface implementationE:prefix for eventsE:N.X.d.F:prefix for fieldsF:N.X.q- fieldP:prefix for propertiesP:N.X.prop- property with getter and setterSupported scenarios:
The following are out of scope for this 1st implementation:
Next steps:
IStreamingFindUsagesPresenterwhen we can't distinguish which exact method/function to go to.