From 9d1cb2e972cd88cc3993e40cf3b8483cb8dd49f7 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 11 Apr 2023 18:21:47 +0200 Subject: [PATCH 1/8] Hints refactoring --- .../src/FSharp.Editor/Hints/HintService.fs | 72 ++++++-------- .../Hints/InlineParameterNameHints.fs | 93 ++++++++++--------- .../Hints/InlineReturnTypeHints.fs | 9 +- .../FSharp.Editor/Hints/InlineTypeHints.fs | 20 ++-- 4 files changed, 93 insertions(+), 101 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index d83b182348..f137a7a540 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -5,59 +5,39 @@ namespace Microsoft.VisualStudio.FSharp.Editor.Hints open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Text open Microsoft.VisualStudio.FSharp.Editor -open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols open Hints module HintService = - type private NativeHintResolver = FSharpSymbolUse seq -> NativeHint seq - - let inline private getTypeHints parseResults symbol : NativeHintResolver = - Seq.filter (InlineTypeHints.isValidForHint parseResults symbol) - >> Seq.collect (InlineTypeHints.getHints symbol) - - let inline private getReturnTypeHints parseResults symbol = - Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) - - let inline private getHintsForMemberOrFunctionOrValue (sourceText: SourceText) parseResults symbol : NativeHintResolver = - Seq.filter (InlineParameterNameHints.isMemberOrFunctionOrValueValidForHint symbol) - >> Seq.collect (InlineParameterNameHints.getHintsForMemberOrFunctionOrValue sourceText parseResults symbol) - - let inline private getHintsForUnionCase parseResults symbol : NativeHintResolver = - Seq.filter (InlineParameterNameHints.isUnionCaseValidForHint symbol) - >> Seq.collect (InlineParameterNameHints.getHintsForUnionCase parseResults symbol) - - let private getHintResolvers (sourceText: SourceText) parseResults hintKinds (symbol: FSharpSymbol) : NativeHintResolver seq = - let rec resolve hintKinds resolvers = + let private getHints sourceText parseResults hintKinds symbolUses (symbol: FSharpSymbol) = + let rec getHints hintKinds acc = match hintKinds with - | [] -> resolvers |> Seq.choose id + | [] -> acc | hintKind :: hintKinds -> - match hintKind with - | HintKind.TypeHint -> - match symbol with - | :? FSharpMemberOrFunctionOrValue as symbol -> getTypeHints parseResults symbol |> Some - | _ -> None - | HintKind.ReturnTypeHint -> - match symbol with - | :? FSharpMemberOrFunctionOrValue as symbol -> getReturnTypeHints parseResults symbol |> Some - | _ -> None - | HintKind.ParameterNameHint -> - match symbol with - | :? FSharpMemberOrFunctionOrValue as symbol -> - getHintsForMemberOrFunctionOrValue sourceText parseResults symbol |> Some - | :? FSharpUnionCase as symbol -> getHintsForUnionCase parseResults symbol |> Some - | _ -> None - // we'll be adding other stuff gradually here - :: resolvers - |> resolve hintKinds - - resolve hintKinds [] - - let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol: FSharpSymbol, symbolUses: FSharpSymbolUse seq) = + match (hintKind, symbol) with + | HintKind.TypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses + |> Seq.collect (InlineTypeHints(parseResults, symbol)).getHints + | HintKind.ReturnTypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses + |> Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) + | HintKind.ParameterNameHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses + |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForMemberOrFunctionOrValue sourceText symbol) + | HintKind.ParameterNameHint, (:? FSharpUnionCase as symbol) -> + symbolUses + |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForUnionCase symbol) + | _ -> [] + :: acc + |> getHints hintKinds + + getHints (hintKinds |> Set.toList) [] + + let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol, symbolUses) = symbol - |> getHintResolvers sourceText parseResults hintKinds - |> Seq.collect (fun resolve -> resolve symbolUses) + |> getHints sourceText parseResults hintKinds symbolUses + |> Seq.concat let getHintsForDocument sourceText (document: Document) hintKinds userOpName cancellationToken = async { @@ -69,6 +49,6 @@ module HintService = return checkResults.GetAllUsesOfAllSymbolsInFile cancellationToken |> Seq.groupBy (fun symbolUse -> symbolUse.Symbol) - |> Seq.collect (getHintsForSymbol sourceText parseResults (hintKinds |> Set.toList)) + |> Seq.collect (getHintsForSymbol sourceText parseResults hintKinds) |> Seq.toList } diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index 77ea933f22..543ab4de5c 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -9,29 +9,28 @@ open FSharp.Compiler.EditorServices open FSharp.Compiler.Symbols open FSharp.Compiler.Text open Hints -open Microsoft.VisualStudio.FSharp.Editor -module InlineParameterNameHints = +type InlineParameterNameHints(parseResults: FSharpParseFileResults) = - let private getParameterHint (range: range, parameter: FSharpParameter) = + let getParameterHint (range: range, parameter: FSharpParameter) = { Kind = HintKind.ParameterNameHint Range = range.StartRange Parts = [ TaggedText(TextTag.Text, $"{parameter.DisplayName} = ") ] } - let private getFieldHint (range: range, field: FSharpField) = + let getFieldHint (range: range, field: FSharpField) = { Kind = HintKind.ParameterNameHint Range = range.StartRange Parts = [ TaggedText(TextTag.Text, $"{field.Name} = ") ] } - let private doesParameterNameExist (parameter: FSharpParameter) = parameter.DisplayName <> "" + let doesParameterNameExist (parameter: FSharpParameter) = parameter.DisplayName <> "" - let private doesFieldNameExist (field: FSharpField) = not field.IsNameGenerated + let doesFieldNameExist (field: FSharpField) = not field.IsNameGenerated - let private getArgumentLocations (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = + let getArgumentLocations (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = let position = Position.mkPos (symbolUse.Range.End.Line) (symbolUse.Range.End.Column + 1) @@ -43,20 +42,20 @@ module InlineParameterNameHints = |> Option.filter (not << Seq.isEmpty) |> Option.defaultValue Seq.empty - let private getTupleRanges = + let getTupleRanges = Seq.map (fun location -> location.ArgumentRange) >> Seq.toList - let private getCurryRanges (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = + let getCurryRanges (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = parseResults.GetAllArgumentsForFunctionApplicationAtPosition symbolUse.Range.Start |> Option.defaultValue [] - let private isNamedArgument range = + let isNamedArgument range = Seq.filter (fun location -> location.IsNamedArgument) >> Seq.map (fun location -> location.ArgumentRange) >> Seq.contains range - let private getSourceTextAtRange (sourceText: SourceText) (range: range) = + let getSourceTextAtRange (sourceText: SourceText) (range: range) = (RoslynHelpers.FSharpRangeToTextSpan(sourceText, range) |> sourceText.GetSubText) .ToString() @@ -76,49 +75,49 @@ module InlineParameterNameHints = false let isUnionCaseValidForHint (symbol: FSharpUnionCase) (symbolUse: FSharpSymbolUse) = - symbolUse.IsFromUse && symbol.DisplayName <> "(::)" + symbolUse.IsFromUse + && symbol.DisplayName <> "(::)" + // If a case does not use field names, don't even bother getting applied argument ranges + && Seq.toList symbol.Fields |> Seq.exists doesFieldNameExist - let getHintsForMemberOrFunctionOrValue + member _.getHintsForMemberOrFunctionOrValue (sourceText: SourceText) - (parseResults: FSharpParseFileResults) (symbol: FSharpMemberOrFunctionOrValue) - (symbolUse: FSharpSymbolUse) - = - - let parameters = symbol.CurriedParameterGroups |> Seq.concat - let argumentLocations = parseResults |> getArgumentLocations symbolUse - - let tupleRanges = argumentLocations |> getTupleRanges - let curryRanges = parseResults |> getCurryRanges symbolUse + (symbolUse: FSharpSymbolUse) = - let ranges = - if tupleRanges |> (not << Seq.isEmpty) then - tupleRanges - else - curryRanges - |> Seq.filter (fun range -> argumentLocations |> (not << isNamedArgument range)) + if isMemberOrFunctionOrValueValidForHint symbol symbolUse then + let parameters = symbol.CurriedParameterGroups |> Seq.concat + let argumentLocations = parseResults |> getArgumentLocations symbolUse - let argumentNames = ranges |> Seq.map (getSourceTextAtRange sourceText) + let tupleRanges = argumentLocations |> getTupleRanges + let curryRanges = parseResults |> getCurryRanges symbolUse - parameters - |> Seq.zip ranges // Seq.zip is important as List.zip requires equal lengths - |> Seq.where (snd >> doesParameterNameExist) - |> Seq.zip argumentNames - |> Seq.choose (fun (argumentName, (range, parameter)) -> - if argumentName <> parameter.DisplayName then - Some(getParameterHint (range, parameter)) - else - None) - |> Seq.toList - - let getHintsForUnionCase (parseResults: FSharpParseFileResults) (symbol: FSharpUnionCase) (symbolUse: FSharpSymbolUse) = + let ranges = + if tupleRanges |> (not << Seq.isEmpty) then + tupleRanges + else + curryRanges + |> Seq.filter (fun range -> argumentLocations |> (not << isNamedArgument range)) + + let argumentNames = ranges |> Seq.map (getSourceTextAtRange sourceText) + + parameters + |> Seq.zip ranges // Seq.zip is important as List.zip requires equal lengths + |> Seq.where (snd >> doesParameterNameExist) + |> Seq.zip argumentNames + |> Seq.choose (fun (argumentName, (range, parameter)) -> + if argumentName <> parameter.DisplayName then + Some(getParameterHint (range, parameter)) + else + None) + |> Seq.toList + else + [] - let fields = Seq.toList symbol.Fields + member _.getHintsForUnionCase (symbol: FSharpUnionCase) (symbolUse: FSharpSymbolUse) = + if isUnionCaseValidForHint symbol symbolUse then - // If a case does not use field names, don't even bother getting applied argument ranges - if fields |> List.exists doesFieldNameExist |> not then - [] - else + let fields = Seq.toList symbol.Fields let ranges = parseResults.GetAllArgumentsForFunctionApplicationAtPosition symbolUse.Range.Start @@ -131,3 +130,5 @@ module InlineParameterNameHints = |> List.map getFieldHint | _ -> [] + else + [] diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs index f9152c6e88..058f22eb1a 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs @@ -8,7 +8,9 @@ open FSharp.Compiler.Symbols open FSharp.Compiler.Text open Hints -type InlineReturnTypeHints(parseFileResults: FSharpParseFileResults, symbol: FSharpMemberOrFunctionOrValue) = +type InlineReturnTypeHints( + parseFileResults: FSharpParseFileResults, + symbol: FSharpMemberOrFunctionOrValue) = let getHintParts (symbolUse: FSharpSymbolUse) = symbol.GetReturnTypeLayout symbolUse.DisplayContext @@ -28,9 +30,12 @@ type InlineReturnTypeHints(parseFileResults: FSharpParseFileResults, symbol: FSh Parts = parts }) + let isValidForHint (symbol: FSharpMemberOrFunctionOrValue) = + symbol.IsFunction + member _.getHints(symbolUse: FSharpSymbolUse) = [ - if symbol.IsFunction then + if isValidForHint symbol then yield! parseFileResults.TryRangeOfReturnTypeHint symbolUse.Range.Start |> Option.bind (getHint symbolUse) diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs index 94aba509bc..7cb3bd3b24 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs @@ -9,9 +9,11 @@ open FSharp.Compiler.Text open FSharp.Compiler.Text.Position open Hints -module InlineTypeHints = +type InlineTypeHints( + parseResults: FSharpParseFileResults, + symbol: FSharpMemberOrFunctionOrValue) = - let private getHintParts (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = + let getHintParts (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = match symbol.GetReturnTypeLayout symbolUse.DisplayContext with | Some typeInfo -> @@ -21,14 +23,14 @@ module InlineTypeHints = // not sure when this can happen | None -> [] - let private getHint symbol (symbolUse: FSharpSymbolUse) = + let getHint symbol (symbolUse: FSharpSymbolUse) = { Kind = HintKind.TypeHint Range = symbolUse.Range.EndRange Parts = getHintParts symbol symbolUse } - let private isSolved (symbol: FSharpMemberOrFunctionOrValue) = + let isSolved (symbol: FSharpMemberOrFunctionOrValue) = if symbol.GenericParameters.Count > 0 then symbol.GenericParameters |> Seq.forall (fun p -> p.IsSolveAtCompileTime) @@ -38,7 +40,7 @@ module InlineTypeHints = else true - let isValidForHint (parseFileResults: FSharpParseFileResults) (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = + let isValidForHint (symbolUse: FSharpSymbolUse) = let isOptionalParameter = symbolUse.IsFromDefinition @@ -53,7 +55,7 @@ module InlineTypeHints = symbolUse.Range.Start let isNotAnnotatedManually = - not (parseFileResults.IsTypeAnnotationGivenAtPosition adjustedRangeStart) + not (parseResults.IsTypeAnnotationGivenAtPosition adjustedRangeStart) let isNotAfterDot = symbolUse.IsFromDefinition && not symbol.IsMemberThisValue @@ -65,4 +67,8 @@ module InlineTypeHints = && isNotAfterDot && isNotTypeAlias - let getHints symbol symbolUse = [ getHint symbol symbolUse ] + member _.getHints symbolUse = + [ + if isValidForHint symbolUse then + getHint symbol symbolUse + ] From 84006b7e92d2ebb7c18bbc41af47491b93bcdb9a Mon Sep 17 00:00:00 2001 From: Petr Date: Thu, 13 Apr 2023 19:21:47 +0200 Subject: [PATCH 2/8] up --- .../src/FSharp.Editor/Hints/HintService.fs | 14 +++++--------- .../Hints/InlineParameterNameHints.fs | 11 ++++++----- .../FSharp.Editor/Hints/InlineReturnTypeHints.fs | 7 ++----- .../src/FSharp.Editor/Hints/InlineTypeHints.fs | 8 +++----- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index f137a7a540..4dadfb9621 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -17,16 +17,14 @@ module HintService = | hintKind :: hintKinds -> match (hintKind, symbol) with | HintKind.TypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses - |> Seq.collect (InlineTypeHints(parseResults, symbol)).getHints + symbolUses |> Seq.collect (InlineTypeHints(parseResults, symbol)).getHints | HintKind.ReturnTypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses - |> Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) + symbolUses |> Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) | HintKind.ParameterNameHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses + symbolUses |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForMemberOrFunctionOrValue sourceText symbol) | HintKind.ParameterNameHint, (:? FSharpUnionCase as symbol) -> - symbolUses + symbolUses |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForUnionCase symbol) | _ -> [] :: acc @@ -35,9 +33,7 @@ module HintService = getHints (hintKinds |> Set.toList) [] let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol, symbolUses) = - symbol - |> getHints sourceText parseResults hintKinds symbolUses - |> Seq.concat + symbol |> getHints sourceText parseResults hintKinds symbolUses |> Seq.concat let getHintsForDocument sourceText (document: Document) hintKinds userOpName cancellationToken = async { diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index 543ab4de5c..5ea33ef846 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -42,8 +42,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = |> Option.filter (not << Seq.isEmpty) |> Option.defaultValue Seq.empty - let getTupleRanges = - Seq.map (fun location -> location.ArgumentRange) >> Seq.toList + let getTupleRanges = Seq.map (fun location -> location.ArgumentRange) >> Seq.toList let getCurryRanges (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = @@ -75,7 +74,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = false let isUnionCaseValidForHint (symbol: FSharpUnionCase) (symbolUse: FSharpSymbolUse) = - symbolUse.IsFromUse + symbolUse.IsFromUse && symbol.DisplayName <> "(::)" // If a case does not use field names, don't even bother getting applied argument ranges && Seq.toList symbol.Fields |> Seq.exists doesFieldNameExist @@ -83,9 +82,10 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = member _.getHintsForMemberOrFunctionOrValue (sourceText: SourceText) (symbol: FSharpMemberOrFunctionOrValue) - (symbolUse: FSharpSymbolUse) = + (symbolUse: FSharpSymbolUse) + = - if isMemberOrFunctionOrValueValidForHint symbol symbolUse then + if isMemberOrFunctionOrValueValidForHint symbol symbolUse then let parameters = symbol.CurriedParameterGroups |> Seq.concat let argumentLocations = parseResults |> getArgumentLocations symbolUse @@ -118,6 +118,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = if isUnionCaseValidForHint symbol symbolUse then let fields = Seq.toList symbol.Fields + let ranges = parseResults.GetAllArgumentsForFunctionApplicationAtPosition symbolUse.Range.Start diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs index 058f22eb1a..e0a0a9e8f3 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineReturnTypeHints.fs @@ -8,9 +8,7 @@ open FSharp.Compiler.Symbols open FSharp.Compiler.Text open Hints -type InlineReturnTypeHints( - parseFileResults: FSharpParseFileResults, - symbol: FSharpMemberOrFunctionOrValue) = +type InlineReturnTypeHints(parseFileResults: FSharpParseFileResults, symbol: FSharpMemberOrFunctionOrValue) = let getHintParts (symbolUse: FSharpSymbolUse) = symbol.GetReturnTypeLayout symbolUse.DisplayContext @@ -30,8 +28,7 @@ type InlineReturnTypeHints( Parts = parts }) - let isValidForHint (symbol: FSharpMemberOrFunctionOrValue) = - symbol.IsFunction + let isValidForHint (symbol: FSharpMemberOrFunctionOrValue) = symbol.IsFunction member _.getHints(symbolUse: FSharpSymbolUse) = [ diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs index 7cb3bd3b24..93501e19a7 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs @@ -9,9 +9,7 @@ open FSharp.Compiler.Text open FSharp.Compiler.Text.Position open Hints -type InlineTypeHints( - parseResults: FSharpParseFileResults, - symbol: FSharpMemberOrFunctionOrValue) = +type InlineTypeHints(parseResults: FSharpParseFileResults, symbol: FSharpMemberOrFunctionOrValue) = let getHintParts (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = @@ -67,8 +65,8 @@ type InlineTypeHints( && isNotAfterDot && isNotTypeAlias - member _.getHints symbolUse = + member _.getHints symbolUse = [ if isValidForHint symbolUse then - getHint symbol symbolUse + getHint symbol symbolUse ] From e119a24bd6193a3430d81ed32f869ff291950ca5 Mon Sep 17 00:00:00 2001 From: Petr Date: Thu, 13 Apr 2023 19:27:00 +0200 Subject: [PATCH 3/8] up --- .../src/FSharp.Editor/Hints/InlineParameterNameHints.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index 5ea33ef846..1574aaeff6 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -30,7 +30,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = let doesFieldNameExist (field: FSharpField) = not field.IsNameGenerated - let getArgumentLocations (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = + let getArgumentLocations (symbolUse: FSharpSymbolUse) = let position = Position.mkPos (symbolUse.Range.End.Line) (symbolUse.Range.End.Column + 1) @@ -44,7 +44,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = let getTupleRanges = Seq.map (fun location -> location.ArgumentRange) >> Seq.toList - let getCurryRanges (symbolUse: FSharpSymbolUse) (parseResults: FSharpParseFileResults) = + let getCurryRanges (symbolUse: FSharpSymbolUse) = parseResults.GetAllArgumentsForFunctionApplicationAtPosition symbolUse.Range.Start |> Option.defaultValue [] @@ -87,10 +87,10 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = if isMemberOrFunctionOrValueValidForHint symbol symbolUse then let parameters = symbol.CurriedParameterGroups |> Seq.concat - let argumentLocations = parseResults |> getArgumentLocations symbolUse + let argumentLocations = getArgumentLocations symbolUse let tupleRanges = argumentLocations |> getTupleRanges - let curryRanges = parseResults |> getCurryRanges symbolUse + let curryRanges = getCurryRanges symbolUse let ranges = if tupleRanges |> (not << Seq.isEmpty) then From 60f6bbd457f67b09651c619f9a1e7467cc44fb81 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 14 Apr 2023 13:39:36 +0200 Subject: [PATCH 4/8] piping, naming --- .../src/FSharp.Editor/Hints/HintService.fs | 3 ++- .../Hints/InlineParameterNameHints.fs | 22 +++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index 4dadfb9621..af984a4da7 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -33,7 +33,8 @@ module HintService = getHints (hintKinds |> Set.toList) [] let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol, symbolUses) = - symbol |> getHints sourceText parseResults hintKinds symbolUses |> Seq.concat + let hints = getHints sourceText parseResults hintKinds symbolUses symbol + hints |> Seq.concat let getHintsForDocument sourceText (document: Document) hintKinds userOpName cancellationToken = async { diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index 1574aaeff6..dc69c47d7e 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -26,9 +26,9 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = Parts = [ TaggedText(TextTag.Text, $"{field.Name} = ") ] } - let doesParameterNameExist (parameter: FSharpParameter) = parameter.DisplayName <> "" + let parameterNameExists (parameter: FSharpParameter) = parameter.DisplayName <> "" - let doesFieldNameExist (field: FSharpField) = not field.IsNameGenerated + let fieldNameExists (field: FSharpField) = not field.IsNameGenerated let getArgumentLocations (symbolUse: FSharpSymbolUse) = @@ -77,7 +77,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = symbolUse.IsFromUse && symbol.DisplayName <> "(::)" // If a case does not use field names, don't even bother getting applied argument ranges - && Seq.toList symbol.Fields |> Seq.exists doesFieldNameExist + && Seq.toList symbol.Fields |> Seq.exists fieldNameExists member _.getHintsForMemberOrFunctionOrValue (sourceText: SourceText) @@ -86,24 +86,24 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = = if isMemberOrFunctionOrValueValidForHint symbol symbolUse then - let parameters = symbol.CurriedParameterGroups |> Seq.concat + let parameters = Seq.concat symbol.CurriedParameterGroups let argumentLocations = getArgumentLocations symbolUse - let tupleRanges = argumentLocations |> getTupleRanges + let tupleRanges = getTupleRanges argumentLocations let curryRanges = getCurryRanges symbolUse let ranges = - if tupleRanges |> (not << Seq.isEmpty) then - tupleRanges - else + if Seq.isEmpty tupleRanges then curryRanges + else + tupleRanges |> Seq.filter (fun range -> argumentLocations |> (not << isNamedArgument range)) - let argumentNames = ranges |> Seq.map (getSourceTextAtRange sourceText) + let argumentNames = Seq.map (getSourceTextAtRange sourceText) ranges parameters |> Seq.zip ranges // Seq.zip is important as List.zip requires equal lengths - |> Seq.where (snd >> doesParameterNameExist) + |> Seq.where (snd >> parameterNameExists) |> Seq.zip argumentNames |> Seq.choose (fun (argumentName, (range, parameter)) -> if argumentName <> parameter.DisplayName then @@ -127,7 +127,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = | Some ranges when ranges.Length = fields.Length -> fields |> List.zip ranges - |> List.where (snd >> doesFieldNameExist) + |> List.where (snd >> fieldNameExists) |> List.map getFieldHint | _ -> [] From 5394f0cd80e52e8669399cee90ab60a09b845c57 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 14 Apr 2023 13:42:14 +0200 Subject: [PATCH 5/8] piping, naming --- vsintegration/src/FSharp.Editor/Hints/HintService.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index af984a4da7..4ab1cbc90e 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -34,7 +34,7 @@ module HintService = let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol, symbolUses) = let hints = getHints sourceText parseResults hintKinds symbolUses symbol - hints |> Seq.concat + Seq.concat hints let getHintsForDocument sourceText (document: Document) hintKinds userOpName cancellationToken = async { From 6b6044d5cbb2b74a75a1f5f0b54cf07ce74b0640 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 14 Apr 2023 13:57:38 +0200 Subject: [PATCH 6/8] up --- .../src/FSharp.Editor/Hints/InlineParameterNameHints.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index dc69c47d7e..07125fcc1d 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -77,14 +77,14 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = symbolUse.IsFromUse && symbol.DisplayName <> "(::)" // If a case does not use field names, don't even bother getting applied argument ranges - && Seq.toList symbol.Fields |> Seq.exists fieldNameExists + && symbol.Fields |> Seq.exists fieldNameExists member _.getHintsForMemberOrFunctionOrValue (sourceText: SourceText) (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = - + if isMemberOrFunctionOrValueValidForHint symbol symbolUse then let parameters = Seq.concat symbol.CurriedParameterGroups let argumentLocations = getArgumentLocations symbolUse From f7a4289fb91c81bb531abc92c1dc3d3ec27cca26 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 14 Apr 2023 13:58:55 +0200 Subject: [PATCH 7/8] up --- .../src/FSharp.Editor/Hints/InlineParameterNameHints.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index 07125fcc1d..bba5224e53 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -42,7 +42,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = |> Option.filter (not << Seq.isEmpty) |> Option.defaultValue Seq.empty - let getTupleRanges = Seq.map (fun location -> location.ArgumentRange) >> Seq.toList + let getTupleRanges = Seq.map (fun location -> location.ArgumentRange) let getCurryRanges (symbolUse: FSharpSymbolUse) = @@ -94,7 +94,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = let ranges = if Seq.isEmpty tupleRanges then - curryRanges + curryRanges |> List.toSeq else tupleRanges |> Seq.filter (fun range -> argumentLocations |> (not << isNamedArgument range)) From 38fb3af3785f5faa6f526cce46765a03dc940f6a Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 14 Apr 2023 14:11:18 +0200 Subject: [PATCH 8/8] up --- .../src/FSharp.Editor/Hints/HintService.fs | 33 ++++++++++--------- .../Hints/InlineParameterNameHints.fs | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs index 4ab1cbc90e..d4c49ca9e0 100644 --- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs +++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs @@ -11,29 +11,30 @@ open Hints module HintService = let private getHints sourceText parseResults hintKinds symbolUses (symbol: FSharpSymbol) = + + let getHintsPerKind hintKind = + match hintKind, symbol with + | HintKind.TypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses |> Seq.collect (InlineTypeHints(parseResults, symbol)).getHints + | HintKind.ReturnTypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses |> Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) + | HintKind.ParameterNameHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> + symbolUses + |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForMemberOrFunctionOrValue sourceText symbol) + | HintKind.ParameterNameHint, (:? FSharpUnionCase as symbol) -> + symbolUses + |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForUnionCase symbol) + | _ -> [] + let rec getHints hintKinds acc = match hintKinds with | [] -> acc - | hintKind :: hintKinds -> - match (hintKind, symbol) with - | HintKind.TypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses |> Seq.collect (InlineTypeHints(parseResults, symbol)).getHints - | HintKind.ReturnTypeHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses |> Seq.collect (InlineReturnTypeHints(parseResults, symbol).getHints) - | HintKind.ParameterNameHint, (:? FSharpMemberOrFunctionOrValue as symbol) -> - symbolUses - |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForMemberOrFunctionOrValue sourceText symbol) - | HintKind.ParameterNameHint, (:? FSharpUnionCase as symbol) -> - symbolUses - |> Seq.collect (InlineParameterNameHints(parseResults).getHintsForUnionCase symbol) - | _ -> [] - :: acc - |> getHints hintKinds + | hintKind :: hintKinds -> getHintsPerKind hintKind :: acc |> getHints hintKinds getHints (hintKinds |> Set.toList) [] let private getHintsForSymbol (sourceText: SourceText) parseResults hintKinds (symbol, symbolUses) = - let hints = getHints sourceText parseResults hintKinds symbolUses symbol + let hints = getHints sourceText parseResults hintKinds symbolUses symbol Seq.concat hints let getHintsForDocument sourceText (document: Document) hintKinds userOpName cancellationToken = diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index bba5224e53..c4da088944 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -84,7 +84,7 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = (symbol: FSharpMemberOrFunctionOrValue) (symbolUse: FSharpSymbolUse) = - + if isMemberOrFunctionOrValueValidForHint symbol symbolUse then let parameters = Seq.concat symbol.CurriedParameterGroups let argumentLocations = getArgumentLocations symbolUse