@@ -568,46 +568,46 @@ type internal FSharpNavigation(metadataAsSource: FSharpMetadataAsSourceService,
568568 && solution.TryGetDocumentIdFromFSharpRange( range, initialDoc.Project.Id)
569569 |> Option.isSome
570570
571- member _.RelativePath ( range : range ) =
572- let relativePathEscaped =
573- match solution.FilePath with
574- | null -> range.FileName
575- | sfp ->
576- let targetUri = Uri ( range.FileName )
577- Uri ( sfp ) .MakeRelativeUri ( targetUri ) .ToString ()
578-
579- relativePathEscaped |> Uri.UnescapeDataString
580-
581- member _.NavigateTo ( range : range , cancellationToken : CancellationToken ) =
582- asyncMaybe {
583- let targetPath = range.FileName
584- let! targetDoc = solution.TryGetDocumentFromFSharpRange ( range , initialDoc.Project.Id )
585- let! targetSource = targetDoc.GetTextAsync ( cancellationToken )
586- let! targetTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan ( targetSource , range )
587- let gtd = GoToDefinition ( metadataAsSource )
588-
589- // To ensure proper navigation decsions, we need to check the type of document the navigation call
590- // is originating from and the target we're provided by default:
591- // - signature files (.fsi) should navigate to other signature files
592- // - implementation files (.fs) should navigate to other implementation files
593- let (| Signature | Implementation |) filepath =
594- if isSignatureFile filepath then
595- Signature
596- else
597- Implementation
598-
599- match initialDoc.FilePath , targetPath with
600- | Signature , Signature
601- | Implementation , Implementation -> return gtd.TryNavigateToTextSpan ( targetDoc , targetTextSpan , cancellationToken)
602-
603- // Adjust the target from signature to implementation .
604- | Implementation , Signature -> return ! gtd.NavigateToSymbolDefinitionAsync ( targetDoc , targetSource , range , cancellationToken )
605-
606- // Adjust the target from implmentation to signature .
607- | Signature , Implementation -> return ! gtd.NavigateToSymbolDeclarationAsync ( targetDoc , targetSource , range , cancellationToken )
608- }
609- |> Async.Ignore
610- |> Async.StartImmediate
571+ member _.NavigateTo ( range : range ) =
572+ try
573+ ThreadHelper.JoinableTaskFactory.Run (
574+ SR.NavigatingTo (),
575+ ( fun _progress cancellationToken ->
576+ Async.StartImmediateAsTask (
577+ asyncMaybe {
578+ let! targetDoc = solution.TryGetDocumentFromFSharpRange ( range , initialDoc.Project.Id )
579+ let! targetSource = targetDoc.GetTextAsync ( cancellationToken )
580+ let! targetTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan ( targetSource , range )
581+ let gtd = GoToDefinition ( metadataAsSource )
582+
583+ // Whenever possible:
584+ // - signature files (.fsi) should navigate to other signature files
585+ // - implementation files (.fs) should navigate to other implementation files
586+ if isSignatureFile initialDoc.FilePath then
587+ // Target range will point to .fsi file if only there is one so we can just use Roslyn navigation service.
588+ return gtd.TryNavigateToTextSpan ( targetDoc , targetTextSpan , cancellationToken )
589+ else
590+ // Navigation request was made in a .fs file, so we try to find the implmentation of the symbol at target range.
591+ // This is the part that may take some time, because of type checks involved.
592+ let! result =
593+ gtd.NavigateToSymbolDefinitionAsync ( targetDoc , targetSource , range , cancellationToken )
594+ |> liftAsync
595+
596+ if result.IsNone then
597+ // In case the above fails, we just navigate to target range.
598+ return gtd.TryNavigateToTextSpan ( targetDoc , targetTextSpan , cancellationToken )
599+ }
600+ |> Async.Ignore ,
601+ cancellationToken
602+ )),
603+ // Default wait time before VS shows the dialog allowing to cancel the long running task is 2 seconds .
604+ // This seems a bit too long to leave the user without any feedback, so we shorten it to 1 second.
605+ // Note: it seems anything less than 1 second will get rounded down to zero, resulting in flashing dialog
606+ // on each navigation, so 1 second is as low as we cen get from JoinableTaskFactory .
607+ TimeSpan.FromSeconds 1
608+ )
609+ with :? OperationCanceledException ->
610+ ()
611611
612612 member _.FindDefinitions ( position , cancellationToken ) =
613613 let gtd = GoToDefinition( metadataAsSource)
@@ -701,7 +701,7 @@ type FSharpNavigableLocation(metadataAsSource: FSharpMetadataAsSourceService, sy
701701 | Signature -> return ! gtd.NavigateToSymbolDefinitionAsync( targetDoc, targetSource, symbolRange, cancellationToken)
702702 | Implementation -> return ! gtd.NavigateToSymbolDeclarationAsync( targetDoc, targetSource, symbolRange, cancellationToken)
703703 }
704- |> Async.map ( fun a -> a.IsSome )
704+ |> Async.map Option.isSome
705705 |> RoslynHelpers.StartAsyncAsTask cancellationToken
706706
707707[<Export( typeof< IFSharpCrossLanguageSymbolNavigationService>) >]
0 commit comments