@@ -29,7 +29,7 @@ open System.Text.RegularExpressions
29
29
open CancellableTasks
30
30
open Microsoft.VisualStudio .FSharp .Editor .Telemetry
31
31
open Microsoft.VisualStudio .Telemetry
32
- open System. Collections . Generic
32
+ open Microsoft. VisualStudio . Threading
33
33
34
34
module private Symbol =
35
35
let fullName ( root : ISymbol ) : string =
@@ -565,6 +565,77 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) =
565
565
return this.NavigateToItem( item, cancellationToken)
566
566
}
567
567
568
+ member this.NavigateToExternalDeclarationAsync ( targetSymbolUse : FSharpSymbolUse , metadataReferences : seq < MetadataReference >) =
569
+ let textOpt =
570
+ match targetSymbolUse.Symbol with
571
+ | :? FSharpEntity as symbol -> symbol.TryGetMetadataText() |> Option.map ( fun text -> text, symbol.DisplayName)
572
+ | :? FSharpMemberOrFunctionOrValue as symbol ->
573
+ symbol.ApparentEnclosingEntity.TryGetMetadataText()
574
+ |> Option.map ( fun text -> text, symbol.ApparentEnclosingEntity.DisplayName)
575
+ | :? FSharpField as symbol ->
576
+ match symbol.DeclaringEntity with
577
+ | Some entity ->
578
+ let text = entity.TryGetMetadataText()
579
+
580
+ match text with
581
+ | Some text -> Some( text, entity.DisplayName)
582
+ | None -> None
583
+ | None -> None
584
+ | :? FSharpUnionCase as symbol ->
585
+ symbol.DeclaringEntity.TryGetMetadataText()
586
+ |> Option.map ( fun text -> text, symbol.DisplayName)
587
+ | _ -> None
588
+
589
+ match textOpt with
590
+ | None -> CancellableTask.singleton false
591
+ | Some( text, fileName) ->
592
+ foregroundCancellableTask {
593
+ let! cancellationToken = CancellableTask.getCancellationToken ()
594
+ do ! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync( cancellationToken)
595
+
596
+ let tmpProjInfo , tmpDocInfo =
597
+ MetadataAsSource.generateTemporaryDocument (
598
+ AssemblyIdentity( targetSymbolUse.Symbol.Assembly.QualifiedName),
599
+ fileName,
600
+ metadataReferences
601
+ )
602
+
603
+ let tmpShownDocOpt =
604
+ metadataAsSource.ShowDocument( tmpProjInfo, tmpDocInfo.FilePath, SourceText.From( text.ToString()))
605
+
606
+ match tmpShownDocOpt with
607
+ | ValueNone -> return false
608
+ | ValueSome tmpShownDoc ->
609
+ let! _ , checkResults = tmpShownDoc.GetFSharpParseAndCheckResultsAsync( " NavigateToExternalDeclaration" )
610
+
611
+ let r =
612
+ // This tries to find the best possible location of the target symbol's location in the metadata source.
613
+ // We really should rely on symbol equality within FCS instead of doing it here,
614
+ // but the generated metadata as source isn't perfect for symbol equality.
615
+ let symbols = checkResults.GetAllUsesOfAllSymbolsInFile( cancellationToken)
616
+
617
+ symbols
618
+ |> Seq.tryFindV ( tryFindExternalSymbolUse targetSymbolUse)
619
+ |> ValueOption.map ( fun x -> x.Range)
620
+
621
+ let! span =
622
+ cancellableTask {
623
+ let! cancellationToken = CancellableTask.getCancellationToken ()
624
+
625
+ match r with
626
+ | ValueNone -> return TextSpan.empty
627
+ | ValueSome r ->
628
+ let! text = tmpShownDoc.GetTextAsync( cancellationToken)
629
+
630
+ match RoslynHelpers.TryFSharpRangeToTextSpan( text, r) with
631
+ | ValueSome span -> return span
632
+ | _ -> return TextSpan.empty
633
+ }
634
+
635
+ let navItem = FSharpGoToDefinitionNavigableItem( tmpShownDoc, span)
636
+ return this.NavigateToItem( navItem, cancellationToken)
637
+ }
638
+
568
639
member this.NavigateToExternalDeclaration
569
640
(
570
641
targetSymbolUse : FSharpSymbolUse ,
@@ -706,10 +777,15 @@ type internal FSharpNavigation(metadataAsSource: FSharpMetadataAsSourceService,
706
777
let gtd = GoToDefinition( metadataAsSource)
707
778
let! result = gtd.FindDefinitionAtPosition( initialDoc, position)
708
779
709
- return
710
- match result with
711
- | ValueSome( FSharpGoToDefinitionResult.NavigableItem( navItem), _) -> ImmutableArray.create navItem
712
- | _ -> ImmutableArray.empty
780
+ match result with
781
+ | ValueSome( FSharpGoToDefinitionResult.NavigableItem( navItem), _) -> return ImmutableArray.create navItem
782
+ | ValueSome( FSharpGoToDefinitionResult.ExternalAssembly( targetSymbolUse, metadataReferences), _) ->
783
+ do !
784
+ gtd.NavigateToExternalDeclarationAsync( targetSymbolUse, metadataReferences)
785
+ |> CancellableTask.ignore
786
+
787
+ return ImmutableArray.empty
788
+ | _ -> return ImmutableArray.empty
713
789
}
714
790
715
791
member _.TryGoToDefinition ( position , cancellationToken ) =
0 commit comments