@@ -565,17 +565,77 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) =
565565 return this.NavigateToItem( item, cancellationToken)
566566 }
567567
568- member this.NavigateToExternalDeclarationAsync
569- (
570- targetSymbolUse : FSharpSymbolUse ,
571- metadataReferences : seq < MetadataReference >
572- ) =
573- foregroundCancellableTask
574- {
575- let! cancellationToken = CancellableTask.getCancellationToken()
576- do ! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync( cancellationToken)
577- return this.NavigateToExternalDeclaration( targetSymbolUse, metadataReferences, cancellationToken)
578- }
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+ {
594+ let! cancellationToken = CancellableTask.getCancellationToken()
595+ do ! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync( cancellationToken)
596+
597+ let tmpProjInfo , tmpDocInfo =
598+ MetadataAsSource.generateTemporaryDocument (
599+ AssemblyIdentity( targetSymbolUse.Symbol.Assembly.QualifiedName),
600+ fileName,
601+ metadataReferences
602+ )
603+ let tmpShownDocOpt =
604+ metadataAsSource.ShowDocument( tmpProjInfo, tmpDocInfo.FilePath, SourceText.From( text.ToString()))
605+
606+ match tmpShownDocOpt with
607+ | ValueNone ->
608+ return false
609+ | ValueSome tmpShownDoc ->
610+ let! _ , checkResults = tmpShownDoc.GetFSharpParseAndCheckResultsAsync( " NavigateToExternalDeclaration" )
611+
612+ let r =
613+ // This tries to find the best possible location of the target symbol's location in the metadata source.
614+ // We really should rely on symbol equality within FCS instead of doing it here,
615+ // but the generated metadata as source isn't perfect for symbol equality.
616+ let symbols = checkResults.GetAllUsesOfAllSymbolsInFile( cancellationToken)
617+
618+ symbols
619+ |> Seq.tryFindV ( tryFindExternalSymbolUse targetSymbolUse)
620+ |> ValueOption.map ( fun x -> x.Range)
621+
622+ let! span =
623+ cancellableTask {
624+ let! cancellationToken = CancellableTask.getCancellationToken()
625+
626+ match r with
627+ | ValueNone -> return TextSpan.empty
628+ | ValueSome r ->
629+ let! text = tmpShownDoc.GetTextAsync( cancellationToken)
630+
631+ match RoslynHelpers.TryFSharpRangeToTextSpan( text, r) with
632+ | ValueSome span -> return span
633+ | _ -> return TextSpan.empty
634+ }
635+
636+ let navItem = FSharpGoToDefinitionNavigableItem( tmpShownDoc, span)
637+ return this.NavigateToItem( navItem, cancellationToken)
638+ }
579639
580640 member this.NavigateToExternalDeclaration
581641 (
@@ -718,17 +778,12 @@ type internal FSharpNavigation(metadataAsSource: FSharpMetadataAsSourceService,
718778 let gtd = GoToDefinition( metadataAsSource)
719779 let! result = gtd.FindDefinitionAtPosition( initialDoc, position)
720780
721-
722781 match result with
723782 | ValueSome( FSharpGoToDefinitionResult.NavigableItem( navItem), _) ->
724783 return ImmutableArray.create navItem
725784 | ValueSome( FSharpGoToDefinitionResult.ExternalAssembly( targetSymbolUse, metadataReferences), _) ->
726- let! res = gtd.NavigateToExternalDeclarationAsync( targetSymbolUse, metadataReferences)
727- if not res then
728- return ImmutableArray.empty
729- else
730- // TODO: return something? Maybe cancelled task?
731- return ImmutableArray.empty
785+ do ! gtd.NavigateToExternalDeclarationAsync( targetSymbolUse, metadataReferences) |> CancellableTask.ignore
786+ return ImmutableArray.empty
732787 | _ ->
733788 return ImmutableArray.empty
734789 }
0 commit comments