Skip to content

Commit 478d332

Browse files
authored
Merge pull request #17606 from dotnet/merges/main-to-release/dev17.12
Merge main to release/dev17.12
2 parents 454ba02 + cc19b54 commit 478d332

File tree

3 files changed

+85
-74
lines changed

3 files changed

+85
-74
lines changed

docs/release-notes/.VisualStudio/17.12.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
### Added
66

77
### Changed
8+
* Fix unwanted navigation on hover [PR #17592](https://github.com/dotnet/fsharp/pull/17592))
9+
810

911
### Breaking Changes
1012
* Enable FSharp 9.0 Language Version ([Issue #17497](https://github.com/dotnet/fsharp/issues/17438)), [PR](https://github.com/dotnet/fsharp/pull/17500)))

vsintegration/src/FSharp.Editor/LanguageService/MetadataAsSource.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ module internal MetadataAsSource =
9999
ErrorHandler.ThrowOnFailure(windowFrame.SetProperty(int __VSFPROPID5.VSFPROPID_OverrideToolTip, name))
100100
|> ignore
101101

102-
windowFrame.Show() |> ignore
102+
// This is commented out as a temporary fix for https://github.com/dotnet/fsharp/issues/17230
103+
// With the new IFindDefinitionService interface we don't need to manipulate VS text windows directly.
104+
105+
// windowFrame.Show() |> ignore
103106

104107
let textContainer = textBuffer.AsTextContainer()
105108
let mutable workspace = Unchecked.defaultof<_>

vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,76 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) =
199199
return None
200200
}
201201

202+
member _.TryGetExternalDeclarationAsync(targetSymbolUse: FSharpSymbolUse, metadataReferences: seq<MetadataReference>) =
203+
let textOpt =
204+
match targetSymbolUse.Symbol with
205+
| :? FSharpEntity as symbol -> symbol.TryGetMetadataText() |> Option.map (fun text -> text, symbol.DisplayName)
206+
| :? FSharpMemberOrFunctionOrValue as symbol ->
207+
symbol.ApparentEnclosingEntity.TryGetMetadataText()
208+
|> Option.map (fun text -> text, symbol.ApparentEnclosingEntity.DisplayName)
209+
| :? FSharpField as symbol ->
210+
match symbol.DeclaringEntity with
211+
| Some entity ->
212+
let text = entity.TryGetMetadataText()
213+
214+
match text with
215+
| Some text -> Some(text, entity.DisplayName)
216+
| None -> None
217+
| None -> None
218+
| :? FSharpUnionCase as symbol ->
219+
symbol.DeclaringEntity.TryGetMetadataText()
220+
|> Option.map (fun text -> text, symbol.DisplayName)
221+
| _ -> None
222+
223+
match textOpt with
224+
| None -> CancellableTask.singleton None
225+
| Some(text, fileName) ->
226+
foregroundCancellableTask {
227+
let! cancellationToken = CancellableTask.getCancellationToken ()
228+
do! ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken)
229+
230+
let tmpProjInfo, tmpDocInfo =
231+
MetadataAsSource.generateTemporaryDocument (
232+
AssemblyIdentity(targetSymbolUse.Symbol.Assembly.QualifiedName),
233+
fileName,
234+
metadataReferences
235+
)
236+
237+
let tmpShownDocOpt =
238+
metadataAsSource.ShowDocument(tmpProjInfo, tmpDocInfo.FilePath, SourceText.From(text.ToString()))
239+
240+
match tmpShownDocOpt with
241+
| ValueNone -> return None
242+
| ValueSome tmpShownDoc ->
243+
let! _, checkResults = tmpShownDoc.GetFSharpParseAndCheckResultsAsync("NavigateToExternalDeclaration")
244+
245+
let r =
246+
// This tries to find the best possible location of the target symbol's location in the metadata source.
247+
// We really should rely on symbol equality within FCS instead of doing it here,
248+
// but the generated metadata as source isn't perfect for symbol equality.
249+
let symbols = checkResults.GetAllUsesOfAllSymbolsInFile(cancellationToken)
250+
251+
symbols
252+
|> Seq.tryFindV (tryFindExternalSymbolUse targetSymbolUse)
253+
|> ValueOption.map (fun x -> x.Range)
254+
255+
let! span =
256+
cancellableTask {
257+
let! cancellationToken = CancellableTask.getCancellationToken ()
258+
259+
match r with
260+
| ValueNone -> return TextSpan.empty
261+
| ValueSome r ->
262+
let! text = tmpShownDoc.GetTextAsync(cancellationToken)
263+
264+
match RoslynHelpers.TryFSharpRangeToTextSpan(text, r) with
265+
| ValueSome span -> return span
266+
| _ -> return TextSpan.empty
267+
}
268+
269+
return Some(FSharpGoToDefinitionNavigableItem(tmpShownDoc, span) :> FSharpNavigableItem)
270+
}
271+
202272
/// Helper function that is used to determine the navigation strategy to apply, can be tuned towards signatures or implementation files.
203273
member private _.FindSymbolHelper(originDocument: Document, originRange: range, sourceText: SourceText, preferSignature: bool) =
204274
let originTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, originRange)
@@ -566,75 +636,13 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) =
566636
}
567637

568638
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-
}
639+
foregroundCancellableTask {
640+
let! cancellationToken = CancellableTask.getCancellationToken ()
634641

635-
let navItem = FSharpGoToDefinitionNavigableItem(tmpShownDoc, span)
636-
return this.NavigateToItem(navItem, cancellationToken)
637-
}
642+
match! this.TryGetExternalDeclarationAsync(targetSymbolUse, metadataReferences) with
643+
| Some navItem -> return this.NavigateToItem(navItem, cancellationToken)
644+
| None -> return false
645+
}
638646

639647
member this.NavigateToExternalDeclaration
640648
(
@@ -780,11 +788,9 @@ type internal FSharpNavigation(metadataAsSource: FSharpMetadataAsSourceService,
780788
match result with
781789
| ValueSome(FSharpGoToDefinitionResult.NavigableItem(navItem), _) -> return ImmutableArray.create navItem
782790
| ValueSome(FSharpGoToDefinitionResult.ExternalAssembly(targetSymbolUse, metadataReferences), _) ->
783-
do!
784-
gtd.NavigateToExternalDeclarationAsync(targetSymbolUse, metadataReferences)
785-
|> CancellableTask.ignore
786-
787-
return ImmutableArray.empty
791+
match! gtd.TryGetExternalDeclarationAsync(targetSymbolUse, metadataReferences) with
792+
| Some navItem -> return ImmutableArray.Create navItem
793+
| _ -> return ImmutableArray.empty
788794
| _ -> return ImmutableArray.empty
789795
}
790796

0 commit comments

Comments
 (0)