From b9ad7d5fd3785eca4580660296f6af22155012e8 Mon Sep 17 00:00:00 2001 From: Jakub Majocha <1760221+majocha@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:59:53 +0100 Subject: [PATCH 1/4] Make Alt-F1 work for inline hints --- .../Hints/FSharpInlayHintsService.fs | 28 +++++++++++-------- .../src/FSharp.Editor/Hints/HintService.fs | 7 ++++- .../src/FSharp.Editor/Hints/Hints.fs | 2 ++ .../Hints/NativeToRoslynHintConverter.fs | 8 ++---- .../Hints/HintTestFramework.fs | 4 ++- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs index 678e903ff99..c6f7d1c1a44 100644 --- a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs @@ -4,25 +4,30 @@ namespace Microsoft.VisualStudio.FSharp.Editor.Hints open System.Collections.Immutable open System.ComponentModel.Composition +open System.Threading.Tasks open Microsoft.CodeAnalysis.ExternalAccess.FSharp.InlineHints open Microsoft.VisualStudio.FSharp.Editor -open Microsoft.VisualStudio.FSharp.Editor.Telemetry open CancellableTasks -open System.Threading.Tasks // So the Roslyn interface is called IFSharpInlineHintsService // but our implementation is called just HintsService. // That's because we'll likely use this API for things other than inlay hints, // e.g. signature hints above the line, pipeline hints on the side and so on. -[)>] +[)>] type internal FSharpInlayHintsService [] (settings: EditorOptions) = static let userOpName = "Hints" - interface IFSharpInlineHintsService with - member _.GetInlineHintsAsync(document, _, cancellationToken) = - let hintKinds = OptionParser.getHintKinds settings.Advanced + interface IFSharpInlineHintsService2 with + member _.GetInlineHintsAsync(document, textSpan, displayAllOverride, cancellationToken) = + let hintKinds = + if displayAllOverride then + Hints.allHintKinds + else + OptionParser.getHintKinds settings.Advanced + + //DebugHelpers.FSharpOutputPane.logMsg $"hints: {hintKinds} \n" if hintKinds.IsEmpty then Task.FromResult ImmutableArray.Empty @@ -31,14 +36,15 @@ type internal FSharpInlayHintsService [] (settings: Editor let! cancellationToken = CancellableTask.getCancellationToken () let! sourceText = document.GetTextAsync cancellationToken - let! nativeHints = HintService.getHintsForDocument sourceText document hintKinds userOpName + let! nativeHints = HintService.getHintsForDocument sourceText document hintKinds textSpan userOpName - let tasks = + let roslynHints = nativeHints - |> Seq.map (fun hint -> NativeToRoslynHintConverter.convert sourceText hint cancellationToken) + |> Seq.map (NativeToRoslynHintConverter.convert sourceText) + |> ImmutableArray.CreateRange - let! roslynHints = Task.WhenAll(tasks) + //DebugHelpers.FSharpOutputPane.logMsg $"hints count: {roslynHints.Length}\n" - return roslynHints.ToImmutableArray() + return roslynHints } |> CancellableTask.start cancellationToken diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index 34871bcbb66..c09dc07aebd 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -39,7 +39,7 @@ module HintService = let hints = getHints sourceText parseResults hintKinds symbolUses symbol Seq.concat hints - let getHintsForDocument sourceText (document: Document) hintKinds userOpName = + let getHintsForDocument (sourceText: SourceText) (document: Document) hintKinds (textSpan: TextSpan) userOpName = cancellableTask { if isSignatureFile document.FilePath then return List.empty @@ -75,3 +75,8 @@ module HintService = return nativeHints } + |> CancellableTask.map ( + List.filter (fun hint -> + let hintSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, hint.Range) + textSpan.IntersectsWith hintSpan) + ) diff --git a/vsintegration/src/FSharp.Editor/Hints/Hints.fs b/vsintegration/src/FSharp.Editor/Hints/Hints.fs index 0dd7fbff263..0e9f0372621 100644 --- a/vsintegration/src/FSharp.Editor/Hints/Hints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/Hints.fs @@ -14,6 +14,8 @@ module Hints = | ParameterNameHint | ReturnTypeHint + let allHintKinds = Set [ HintKind.TypeHint; HintKind.ParameterNameHint; HintKind.ReturnTypeHint ] + // Relatively convenient for testing type NativeHint = { diff --git a/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs b/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs index 61442b6b547..7e3e33b3e02 100644 --- a/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs +++ b/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs @@ -33,9 +33,7 @@ module NativeToRoslynHintConverter = } |> CancellableTask.start ct - cancellableTask { - let span = rangeToSpan hint.Range sourceText - let displayParts = hint.Parts |> Seq.map nativeToRoslynText + let span = rangeToSpan hint.Range sourceText + let displayParts = hint.Parts |> Seq.map nativeToRoslynText - return FSharpInlineHint(span, displayParts.ToImmutableArray(), getDescriptionAsync) - } + FSharpInlineHint(span, displayParts.ToImmutableArray(), getDescriptionAsync) diff --git a/vsintegration/tests/FSharp.Editor.Tests/Hints/HintTestFramework.fs b/vsintegration/tests/FSharp.Editor.Tests/Hints/HintTestFramework.fs index df6d3c73c0c..def34bfc516 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Hints/HintTestFramework.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Hints/HintTestFramework.fs @@ -3,6 +3,7 @@ namespace FSharp.Editor.Tests.Hints open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.Text open Microsoft.VisualStudio.FSharp.Editor open Microsoft.VisualStudio.FSharp.Editor.Hints open Hints @@ -47,7 +48,8 @@ module HintTestFramework = } let! sourceText = document.GetTextAsync ct |> Async.AwaitTask - let! hints = HintService.getHintsForDocument sourceText document hintKinds "test" ct + let textSpan = TextSpan(0, sourceText.Length) + let! hints = HintService.getHintsForDocument sourceText document hintKinds textSpan "test" ct let! tooltips = hints |> Seq.map getTooltip |> Async.Parallel return tooltips |> Seq.zip hints |> Seq.map convert } From ffd631aadae060ed6e0d35ba519c84a7256529d7 Mon Sep 17 00:00:00 2001 From: Jakub Majocha <1760221+majocha@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:10:24 +0100 Subject: [PATCH 2/4] release notes --- docs/release-notes/.VisualStudio/18.vNext.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.VisualStudio/18.vNext.md b/docs/release-notes/.VisualStudio/18.vNext.md index 8e59087813c..a7a62a728f8 100644 --- a/docs/release-notes/.VisualStudio/18.vNext.md +++ b/docs/release-notes/.VisualStudio/18.vNext.md @@ -4,6 +4,7 @@ * Fixed Find All References crash when F# project contains non-F# files like `.cshtml`. ([Issue #16394](https://github.com/dotnet/fsharp/issues/16394), [PR #19252](https://github.com/dotnet/fsharp/pull/19252)) * Find All References for external DLL symbols now only searches projects that reference the specific assembly. ([Issue #10227](https://github.com/dotnet/fsharp/issues/10227), [PR #19252](https://github.com/dotnet/fsharp/pull/19252)) * Improve static compilation of state machines. ([PR #19297](https://github.com/dotnet/fsharp/pull/19297)) +* Make Alt+F1 (momentary toggle) work for inlay hints. ([PR #19421](https://github.com/dotnet/fsharp/pull/19421)) ### Changed From 7579602bba2a95b65c6fe8318e9e7356041043e8 Mon Sep 17 00:00:00 2001 From: Jakub Majocha <1760221+majocha@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:15:24 +0100 Subject: [PATCH 3/4] cleanup --- .../src/FSharp.Editor/Hints/FSharpInlayHintsService.fs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs index c6f7d1c1a44..472ec0bb360 100644 --- a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs @@ -27,8 +27,6 @@ type internal FSharpInlayHintsService [] (settings: Editor else OptionParser.getHintKinds settings.Advanced - //DebugHelpers.FSharpOutputPane.logMsg $"hints: {hintKinds} \n" - if hintKinds.IsEmpty then Task.FromResult ImmutableArray.Empty else @@ -43,8 +41,6 @@ type internal FSharpInlayHintsService [] (settings: Editor |> Seq.map (NativeToRoslynHintConverter.convert sourceText) |> ImmutableArray.CreateRange - //DebugHelpers.FSharpOutputPane.logMsg $"hints count: {roslynHints.Length}\n" - return roslynHints } |> CancellableTask.start cancellationToken From 395ad45d43127ca18792176621d60f5b21941b2b Mon Sep 17 00:00:00 2001 From: Jakub Majocha <1760221+majocha@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:24:59 +0100 Subject: [PATCH 4/4] fantomas --- .../src/FSharp.Editor/Hints/FSharpInlayHintsService.fs | 4 ++-- vsintegration/src/FSharp.Editor/Hints/Hints.fs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs index 472ec0bb360..85ac8ef6edc 100644 --- a/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/FSharpInlayHintsService.fs @@ -20,13 +20,13 @@ type internal FSharpInlayHintsService [] (settings: Editor static let userOpName = "Hints" interface IFSharpInlineHintsService2 with - member _.GetInlineHintsAsync(document, textSpan, displayAllOverride, cancellationToken) = + member _.GetInlineHintsAsync(document, textSpan, displayAllOverride, cancellationToken) = let hintKinds = if displayAllOverride then Hints.allHintKinds else OptionParser.getHintKinds settings.Advanced - + if hintKinds.IsEmpty then Task.FromResult ImmutableArray.Empty else diff --git a/vsintegration/src/FSharp.Editor/Hints/Hints.fs b/vsintegration/src/FSharp.Editor/Hints/Hints.fs index 0e9f0372621..ca4fb7ee8c5 100644 --- a/vsintegration/src/FSharp.Editor/Hints/Hints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/Hints.fs @@ -14,7 +14,8 @@ module Hints = | ParameterNameHint | ReturnTypeHint - let allHintKinds = Set [ HintKind.TypeHint; HintKind.ParameterNameHint; HintKind.ReturnTypeHint ] + let allHintKinds = + Set [ HintKind.TypeHint; HintKind.ParameterNameHint; HintKind.ReturnTypeHint ] // Relatively convenient for testing type NativeHint =