diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
index cdfc599466..ab04e3f105 100644
--- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
+++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
@@ -126,8 +126,12 @@
+
+
+
+
diff --git a/vsintegration/src/FSharp.Editor/Hints/HintService.fs b/vsintegration/src/FSharp.Editor/Hints/HintService.fs
index 13edb5448d..c04ccef51f 100644
--- a/vsintegration/src/FSharp.Editor/Hints/HintService.fs
+++ b/vsintegration/src/FSharp.Editor/Hints/HintService.fs
@@ -6,64 +6,28 @@ open Microsoft.CodeAnalysis
open Microsoft.VisualStudio.FSharp.Editor
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.Symbols
-open FSharp.Compiler.Text
+open Hints
module HintService =
-
- // Relatively convenient for testing
- type NativeHint = {
- Range: range
- Parts: TaggedText list
- }
-
- let private isValidForHint
- (parseFileResults: FSharpParseFileResults)
- (symbol: FSharpMemberOrFunctionOrValue)
- (symbolUse: FSharpSymbolUse) =
-
- let isNotAnnotatedManually =
- not (parseFileResults.IsTypeAnnotationGivenAtPosition symbolUse.Range.Start)
-
- let isNotAfterDot =
- symbolUse.IsFromDefinition
- && not symbol.IsMemberThisValue
-
- let isNotTypeAlias =
- not symbol.IsConstructorThisValue
-
- symbol.IsValue // we'll be adding other stuff gradually here
- && isNotAnnotatedManually
- && isNotAfterDot
- && isNotTypeAlias
-
- let private getHintParts
- (symbol: FSharpMemberOrFunctionOrValue)
- (symbolUse: FSharpSymbolUse) =
-
- match symbol.GetReturnTypeLayout symbolUse.DisplayContext with
- | Some typeInfo ->
- let colon = TaggedText(TextTag.Text, ": ")
- colon :: (typeInfo |> Array.toList)
-
- // not sure when this can happen but better safe than sorry
- | None ->
- []
-
- let private getHintsForSymbol parseResults (symbolUse: FSharpSymbolUse) =
+ let private getHintsForSymbol parseResults hintKinds (symbolUse: FSharpSymbolUse) =
match symbolUse.Symbol with
- | :? FSharpMemberOrFunctionOrValue as mfvSymbol
- when isValidForHint parseResults mfvSymbol symbolUse ->
+ | :? FSharpMemberOrFunctionOrValue as symbol
+ when hintKinds |> Set.contains HintKind.TypeHint
+ && InlineTypeHints.isValidForHint parseResults symbol symbolUse ->
- [ {
- Range = symbolUse.Range
- Parts = getHintParts mfvSymbol symbolUse
- } ]
+ InlineTypeHints.getHints symbol symbolUse
+ | :? FSharpMemberOrFunctionOrValue as symbol
+ when hintKinds |> Set.contains HintKind.ParameterNameHint
+ && InlineParameterNameHints.isValidForHint symbol ->
+
+ InlineParameterNameHints.getHints parseResults symbol symbolUse
+
// we'll be adding other stuff gradually here
| _ ->
[]
- let getHintsForDocument (document: Document) userOpName cancellationToken =
+ let getHintsForDocument (document: Document) hintKinds userOpName cancellationToken =
async {
if isSignatureFile document.FilePath
then
@@ -75,5 +39,5 @@ module HintService =
return
checkResults.GetAllUsesOfAllSymbolsInFile cancellationToken
|> Seq.toList
- |> List.collect (getHintsForSymbol parseResults)
+ |> List.collect (getHintsForSymbol parseResults hintKinds)
}
diff --git a/vsintegration/src/FSharp.Editor/Hints/Hints.fs b/vsintegration/src/FSharp.Editor/Hints/Hints.fs
new file mode 100644
index 0000000000..9e6bab5c29
--- /dev/null
+++ b/vsintegration/src/FSharp.Editor/Hints/Hints.fs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Microsoft.VisualStudio.FSharp.Editor.Hints
+
+open FSharp.Compiler.Text
+
+module Hints =
+
+ type HintKind =
+ | TypeHint
+ | ParameterNameHint
+
+ // Relatively convenient for testing
+ type NativeHint = {
+ Kind: HintKind
+ Range: range
+ Parts: TaggedText list
+ }
\ No newline at end of file
diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs
new file mode 100644
index 0000000000..4e4baa5687
--- /dev/null
+++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Microsoft.VisualStudio.FSharp.Editor.Hints
+
+open Microsoft.VisualStudio.FSharp.Editor
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.Symbols
+open FSharp.Compiler.Text
+open Hints
+
+module InlineParameterNameHints =
+
+ let private getHint (range: range, parameter: FSharpParameter) =
+ {
+ Kind = HintKind.ParameterNameHint
+ Range = range.StartRange
+ Parts = [ TaggedText(TextTag.Text, $"{parameter.DisplayName} = ") ]
+ }
+
+ let private doesParameterNameExist (parameter: FSharpParameter) =
+ parameter.DisplayName <> ""
+
+ let isValidForHint (symbol: FSharpMemberOrFunctionOrValue) =
+ // is there a better way?
+ let isNotBuiltInOperator =
+ symbol.DeclaringEntity
+ |> Option.exists (fun entity -> entity.CompiledName <> "Operators")
+
+ symbol.IsFunction
+ && isNotBuiltInOperator // arguably, hints for those would be rather useless
+
+ let getHints
+ (parseResults: FSharpParseFileResults)
+ (symbol: FSharpMemberOrFunctionOrValue)
+ (symbolUse: FSharpSymbolUse) =
+
+ let parameters = symbol.CurriedParameterGroups |> Seq.concat
+ let ranges = parseResults.GetAllArgumentsForFunctionApplicationAtPosition symbolUse.Range.Start
+
+ match ranges with
+ | Some ranges ->
+ parameters
+ |> Seq.zip ranges
+ |> Seq.where (snd >> doesParameterNameExist)
+ |> Seq.map getHint
+ |> Seq.toList
+
+ // this is the case at least for custom operators
+ | None -> []
diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs
new file mode 100644
index 0000000000..09566e0514
--- /dev/null
+++ b/vsintegration/src/FSharp.Editor/Hints/InlineTypeHints.fs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Microsoft.VisualStudio.FSharp.Editor.Hints
+
+open Microsoft.VisualStudio.FSharp.Editor
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.Symbols
+open FSharp.Compiler.Text
+open Hints
+
+module InlineTypeHints =
+
+ let private getHintParts
+ (symbol: FSharpMemberOrFunctionOrValue)
+ (symbolUse: FSharpSymbolUse) =
+
+ match symbol.GetReturnTypeLayout symbolUse.DisplayContext with
+ | Some typeInfo ->
+ let colon = TaggedText(TextTag.Text, ": ")
+ colon :: (typeInfo |> Array.toList)
+
+ // not sure when this can happen
+ | None ->
+ []
+
+ let private getHint symbol (symbolUse: FSharpSymbolUse) =
+ {
+ Kind = HintKind.TypeHint
+ Range = symbolUse.Range.EndRange
+ Parts = getHintParts symbol symbolUse
+ }
+
+ let isValidForHint
+ (parseFileResults: FSharpParseFileResults)
+ (symbol: FSharpMemberOrFunctionOrValue)
+ (symbolUse: FSharpSymbolUse) =
+
+ let isNotAnnotatedManually =
+ not (parseFileResults.IsTypeAnnotationGivenAtPosition symbolUse.Range.Start)
+
+ let isNotAfterDot =
+ symbolUse.IsFromDefinition
+ && not symbol.IsMemberThisValue
+
+ let isNotTypeAlias =
+ not symbol.IsConstructorThisValue
+
+ symbol.IsValue // we'll be adding other stuff gradually here
+ && isNotAnnotatedManually
+ && isNotAfterDot
+ && isNotTypeAlias
+
+ let getHints symbol symbolUse =
+ [ getHint symbol symbolUse ]
diff --git a/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs b/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs
index 9396d7d925..8433b1a638 100644
--- a/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs
+++ b/vsintegration/src/FSharp.Editor/Hints/NativeToRoslynHintConverter.fs
@@ -7,7 +7,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.ExternalAccess.FSharp.InlineHints
open Microsoft.VisualStudio.FSharp.Editor
open FSharp.Compiler.Text
-open HintService
+open Hints
module NativeToRoslynHintConverter =
diff --git a/vsintegration/src/FSharp.Editor/Hints/OptionParser.fs b/vsintegration/src/FSharp.Editor/Hints/OptionParser.fs
new file mode 100644
index 0000000000..c7602aedb4
--- /dev/null
+++ b/vsintegration/src/FSharp.Editor/Hints/OptionParser.fs
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Microsoft.VisualStudio.FSharp.Editor.Hints
+
+open Microsoft.VisualStudio.FSharp.Editor
+open Hints
+
+module OptionParser =
+
+ let getHintKinds options =
+ Set
+ [ if options.IsInlineTypeHintsEnabled then
+ HintKind.TypeHint
+
+ if options.IsInlineParameterNameHintsEnabled then
+ HintKind.ParameterNameHint ]
\ No newline at end of file
diff --git a/vsintegration/src/FSharp.Editor/Hints/RoslynAdapter.fs b/vsintegration/src/FSharp.Editor/Hints/RoslynAdapter.fs
index 01fde06102..cddf8d250f 100644
--- a/vsintegration/src/FSharp.Editor/Hints/RoslynAdapter.fs
+++ b/vsintegration/src/FSharp.Editor/Hints/RoslynAdapter.fs
@@ -22,17 +22,19 @@ type internal RoslynAdapter
interface IFSharpInlineHintsService with
member _.GetInlineHintsAsync(document, _, cancellationToken) =
async {
- if not settings.Advanced.IsInlineHintsEnabled
- then return ImmutableArray.Empty
-
- else
- let! sourceText = document.GetTextAsync cancellationToken |> Async.AwaitTask
- let! nativeHints =
- HintService.getHintsForDocument document userOpName cancellationToken
+ let! sourceText = document.GetTextAsync cancellationToken |> Async.AwaitTask
+ let hintKinds = OptionParser.getHintKinds settings.Advanced
+
+ let! nativeHints =
+ HintService.getHintsForDocument
+ document
+ hintKinds
+ userOpName
+ cancellationToken
- let roslynHints =
- nativeHints
- |> Seq.map (NativeToRoslynHintConverter.convert sourceText)
+ let roslynHints =
+ nativeHints
+ |> Seq.map (NativeToRoslynHintConverter.convert sourceText)
- return roslynHints.ToImmutableArray()
+ return roslynHints.ToImmutableArray()
} |> RoslynHelpers.StartAsyncAsTask cancellationToken
diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
index e9a05b99c7..4ee2d14273 100644
--- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
+++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
@@ -86,11 +86,13 @@ type LensOptions =
type AdvancedOptions =
{ IsBlockStructureEnabled: bool
IsOutliningEnabled: bool
- IsInlineHintsEnabled: bool }
+ IsInlineTypeHintsEnabled: bool
+ IsInlineParameterNameHintsEnabled: bool }
static member Default =
{ IsBlockStructureEnabled = true
IsOutliningEnabled = true
- IsInlineHintsEnabled = false }
+ IsInlineTypeHintsEnabled = false
+ IsInlineParameterNameHintsEnabled = false }
[]
type FormattingOptions =
diff --git a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
index 4e80e56c6f..1a80650b15 100644
--- a/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
+++ b/vsintegration/src/FSharp.UIResources/AdvancedOptionsControl.xaml
@@ -25,8 +25,12 @@
Content="{x:Static local:Strings.Show_Outlining}"/>
-
+
+
+
+
diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
index 23f3b72320..c2c44bfb4a 100644
--- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
+++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs
@@ -212,7 +212,7 @@ public static string Inline_Hints {
return ResourceManager.GetString("Inline_Hints", resourceCulture);
}
}
-
+
///
/// Looks up a localized string similar to IntelliSense Performance Options.
///
@@ -339,15 +339,24 @@ public static string Show_guides {
}
}
+ ///
+ /// Looks up a localized string similar to Display inline parameter name hints (experimental).
+ ///
+ public static string Show_Inline_Parameter_Name_Hints {
+ get {
+ return ResourceManager.GetString("Show_Inline_Parameter_Name_Hints", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Display inline type hints (experimental).
///
- public static string Show_Inline_Hints {
+ public static string Show_Inline_Type_Hints {
get {
- return ResourceManager.GetString("Show_Inline_Hints", resourceCulture);
+ return ResourceManager.GetString("Show_Inline_Type_Hints", resourceCulture);
}
}
-
+
///
/// Looks up a localized string similar to S_how navigation links as.
///
diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx
index e6f9fccd9d..f87b2edd98 100644
--- a/vsintegration/src/FSharp.UIResources/Strings.resx
+++ b/vsintegration/src/FSharp.UIResources/Strings.resx
@@ -192,7 +192,7 @@
Inline Hints
-
+
Display inline type hints (experimental)
@@ -243,4 +243,7 @@
Enable parallel reference resolution
+
+ Display inline parameter name hints (experimental)
+
\ No newline at end of file
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
index 2c2fe934b7..d50c7ea6d1 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
index b946628c02..d4d347fbc8 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
index 9212a40cb0..2591eae9f3 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
index 5fa8f1caea..8f7821d9ae 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
index a5732c33ea..447da25a46 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
index 30a7d45df9..a2f3594e54 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
index ef59262a11..e03949a0ba 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
index b388b74d48..71e9dbf228 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
index 43082d7a46..96ec77b97f 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
index dfe465c025..7e45d8e8d2 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
index 7717e353c2..c05d626e70 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
index 7e5b5761e6..abe99a445c 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
index c24a02fb05..4e5a0bacc5 100644
--- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
+++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf
@@ -82,7 +82,12 @@
Parallelization (requires restart)
-
+
+ Display inline parameter name hints (experimental)
+ Display inline parameter name hints (experimental)
+
+
+
Display inline type hints (experimental)
Display inline type hints (experimental)
diff --git a/vsintegration/tests/UnitTests/HintTestFramework.fs b/vsintegration/tests/UnitTests/HintTestFramework.fs
index 87d4438abc..135f2721be 100644
--- a/vsintegration/tests/UnitTests/HintTestFramework.fs
+++ b/vsintegration/tests/UnitTests/HintTestFramework.fs
@@ -5,9 +5,9 @@ namespace VisualFSharp.UnitTests.Editor.Hints
open System.Threading
open Microsoft.VisualStudio.FSharp.Editor
open Microsoft.VisualStudio.FSharp.Editor.Hints
-open Microsoft.VisualStudio.FSharp.Editor.Hints.HintService
open VisualFSharp.UnitTests.Editor
open Microsoft.CodeAnalysis.Text
+open Hints
module HintTestFramework =
@@ -44,9 +44,23 @@ let getFsiAndFsDocuments (fsiCode: string) (fsCode: string) =
"test.fs",
SourceText.From fsCode)
-let getHints document =
+let getHints document hintKinds =
async {
- let! hints = HintService.getHintsForDocument document "test" CancellationToken.None
+ let! hints = HintService.getHintsForDocument document hintKinds "test" CancellationToken.None
return hints |> Seq.map convert
}
|> Async.RunSynchronously
+
+let getTypeHints document =
+ getHints document (Set.empty.Add(HintKind.TypeHint))
+
+let getParameterNameHints document =
+ getHints document (Set.empty.Add(HintKind.ParameterNameHint))
+
+let getAllHints document =
+ let hintKinds =
+ Set.empty
+ .Add(HintKind.TypeHint)
+ .Add(HintKind.ParameterNameHint)
+
+ getHints document hintKinds
\ No newline at end of file
diff --git a/vsintegration/tests/UnitTests/InlineParameterNameHintTests.fs b/vsintegration/tests/UnitTests/InlineParameterNameHintTests.fs
new file mode 100644
index 0000000000..9fbebcd139
--- /dev/null
+++ b/vsintegration/tests/UnitTests/InlineParameterNameHintTests.fs
@@ -0,0 +1,175 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace VisualFSharp.UnitTests.Editor.Hints
+
+open NUnit.Framework
+open HintTestFramework
+
+module InlineParameterNameHintTests =
+
+[]
+let ``Hint is shown for a let binding`` () =
+ let code = """
+let greet friend = $"hello {friend}"
+let greeting = greet "darkness"
+"""
+ let document = getFsDocument code
+ let expected = [{ Content = "friend = "; Location = (2, 22) }]
+
+ let actual = getParameterNameHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hints are shown for multiple function calls`` () =
+ let code = """
+let greet friend = $"hello {friend}"
+let greeting1 = greet "Noel"
+let greeting2 = greet "Liam"
+"""
+ let document = getFsDocument code
+ let expected = [
+ { Content = "friend = "; Location = (2, 23) }
+ { Content = "friend = "; Location = (3, 23) }
+ ]
+
+ let actual = getParameterNameHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hints are shown for multiple parameters`` () =
+ let code = """
+let greet friend1 friend2 = $"hello {friend1} and {friend2}"
+let greeting = greet "Liam" "Noel"
+"""
+ let document = getFsDocument code
+ let expected = [
+ { Content = "friend1 = "; Location = (2, 22) }
+ { Content = "friend2 = "; Location = (2, 29) }
+ ]
+
+ let actual = getParameterNameHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hints are shown for tuple items`` () =
+ let code = """
+let greet (friend1, friend2) = $"hello {friend1} and {friend2}"
+let greeting = greet ("Liam", "Noel")
+"""
+ let document = getFsDocument code
+ let expected = [
+ { Content = "friend1 = "; Location = (2, 23) }
+ { Content = "friend2 = "; Location = (2, 31) }
+ ]
+
+ let actual = getParameterNameHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hints are shown for active patterns`` () =
+ let code = """
+let (|Even|Odd|) n =
+ if n % 2 = 0 then Even
+ else Odd
+
+let evenOrOdd number =
+ match number with
+ | Even -> "even"
+ | Odd -> "odd"
+
+let even = evenOrOdd 42
+let odd = evenOrOdd 41
+"""
+ let document = getFsDocument code
+ let expected = [
+ { Content = "number = "; Location = (10, 22) }
+ { Content = "number = "; Location = (11, 21) }
+ ]
+
+ let actual = getParameterNameHints document
+
+ Assert.AreEqual(expected, actual)
+
+
+[] // here we don't want an empty hint before "x"
+let ``Hints are not shown for nameless parameters`` () =
+ let code = """
+let exists predicate option =
+ match option with
+ | None -> false
+ | Some x -> predicate x
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
+[] // here we don't want a useless (?) hint "value = "
+let ``Hints are not shown for parameters of built-in operators`` () =
+ let code = """
+let postTrue = not true
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hints are not shown for parameters of custom operators`` () =
+ let code = """
+let (===) value1 value2 = value1 = value2
+
+let c = "javascript" === "javascript"
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hints are not (yet) shown for method parameters`` () =
+ let code = """
+let theAnswer = System.Console.WriteLine 42
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hints are not (yet) shown for constructor parameters`` () =
+ let code = """
+type WrappedThing(x) =
+ let unwrapped = x
+
+let wrapped = WrappedThing 42
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hints are not (yet) shown for dicrimanted unions`` () =
+ let code = """
+type Shape =
+ | Square of side : float
+ | Circle of radius : float
+
+let circle = Circle 42
+"""
+ let document = getFsDocument code
+
+ let result = getParameterNameHints document
+
+ Assert.IsEmpty(result)
+
diff --git a/vsintegration/tests/UnitTests/InlineTypeHintTests.fs b/vsintegration/tests/UnitTests/InlineTypeHintTests.fs
new file mode 100644
index 0000000000..36aabb4c8a
--- /dev/null
+++ b/vsintegration/tests/UnitTests/InlineTypeHintTests.fs
@@ -0,0 +1,115 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace VisualFSharp.UnitTests.Editor.Hints
+
+open NUnit.Framework
+open HintTestFramework
+
+module InlineTypeHintTests =
+
+[]
+let ``Hint is shown for a let binding`` () =
+ let code = """
+type Song = { Artist: string; Title: string }
+
+let s = { Artist = "Moby"; Title = "Porcelain" }
+"""
+ let document = getFsDocument code
+ let expected = [{ Content = ": Song"; Location = (3, 6) }]
+
+ let actual = getTypeHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hint is shown for a parameter`` () =
+ let code = """
+type Song = { Artist: string; Title: string }
+
+let whoSings s = s.Artist
+"""
+ let document = getFsDocument code
+ let expected = [{ Content = ": Song"; Location = (3, 15) }]
+
+ let actual = getTypeHints document
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Hints are not shown in signature files`` () =
+ let fsiCode = """
+module Test
+
+val numbers: int[]
+"""
+ let fsCode = """
+module Test
+
+let numbers = [|42|]
+"""
+ let fsiDocument, _ = getFsiAndFsDocuments fsiCode fsCode
+
+ let result = getTypeHints fsiDocument
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hints are not shown for let-bound functions yet`` () =
+ let code = """
+let setConsoleOut = System.Console.SetOut
+"""
+ let document = getFsDocument code
+
+ let result = getTypeHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hint is not shown for a let binding when the type is manually specified`` () =
+ let code = """
+type Song = { Artist: string; Title: string }
+
+let s: Song = { Artist = "Moby"; Title = "Porcelain" }
+"""
+ let document = getFsDocument code
+
+ let result = getTypeHints document
+
+ Assert.IsEmpty(result)
+
+[]
+let ``Hint is not shown for a parameter when the type is manually specified`` () =
+ let code = """
+type Song = { Artist: string; Title: string }
+
+let whoSings (s: Song) = s.Artist
+"""
+ let document = getFsDocument code
+
+ let result = getTypeHints document
+
+ Assert.IsEmpty(result)
+
+[] // here we don't want a hint after "this"
+let ``Hint is not shown for type self-identifiers`` () =
+ let code = """
+type Song() =
+ member this.GetName() = "Porcelain"
+"""
+ let document = getFsDocument code
+
+ let result = getTypeHints document
+
+ Assert.IsEmpty(result)
+
+[] // here we don't want a hint after "x"
+let ``Hint is not shown for type aliases`` () =
+ let code = """
+type Song() as x =
+ member this.Name = "Porcelain"
+"""
+ let document = getFsDocument code
+
+ let result = getTypeHints document
+
+ Assert.IsEmpty(result)
diff --git a/vsintegration/tests/UnitTests/OptionParserTests.fs b/vsintegration/tests/UnitTests/OptionParserTests.fs
new file mode 100644
index 0000000000..365bf1ef7c
--- /dev/null
+++ b/vsintegration/tests/UnitTests/OptionParserTests.fs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace VisualFSharp.UnitTests.Editor.Hints
+
+open NUnit.Framework
+open Microsoft.VisualStudio.FSharp.Editor
+open Microsoft.VisualStudio.FSharp.Editor.Hints
+open Microsoft.VisualStudio.FSharp.Editor.Hints.Hints
+
+// best tests ever - very scalable
+module OptionParserTests =
+
+[]
+let ``Type hints off, parameter name hints off`` () =
+ let options = { AdvancedOptions.Default with
+ IsInlineTypeHintsEnabled = false
+ IsInlineParameterNameHintsEnabled = false }
+
+ let expected = []
+
+ let actual = OptionParser.getHintKinds options
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Type hints on, parameter name hints off`` () =
+ let options = { AdvancedOptions.Default with
+ IsInlineTypeHintsEnabled = true
+ IsInlineParameterNameHintsEnabled = false }
+
+ let expected = [HintKind.TypeHint]
+
+ let actual = OptionParser.getHintKinds options
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Type hints off, parameter name hints on`` () =
+ let options = { AdvancedOptions.Default with
+ IsInlineTypeHintsEnabled = false
+ IsInlineParameterNameHintsEnabled = true }
+
+ let expected = [HintKind.ParameterNameHint]
+
+ let actual = OptionParser.getHintKinds options
+
+ Assert.AreEqual(expected, actual)
+
+[]
+let ``Type hints on, parameter name hints on`` () =
+ let options = { AdvancedOptions.Default with
+ IsInlineTypeHintsEnabled = true
+ IsInlineParameterNameHintsEnabled = true }
+
+ let expected = [HintKind.TypeHint; HintKind.ParameterNameHint]
+
+ let actual = OptionParser.getHintKinds options
+
+ Assert.AreEqual(expected, actual)
\ No newline at end of file
diff --git a/vsintegration/tests/UnitTests/OverallHintExperienceTests.fs b/vsintegration/tests/UnitTests/OverallHintExperienceTests.fs
new file mode 100644
index 0000000000..fb1dcbe801
--- /dev/null
+++ b/vsintegration/tests/UnitTests/OverallHintExperienceTests.fs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace VisualFSharp.UnitTests.Editor.Hints
+
+open NUnit.Framework
+open HintTestFramework
+
+// just some kind of higher level testing
+module OverallHintExperienceTests =
+
+[]
+let ``Current baseline hints`` () =
+ let code = """
+type Song = { Artist: string; Title: string }
+let whoSings song = song.Artist
+
+let artist = whoSings { Artist = "Květy"; Title = "Je podzim" }
+"""
+ let document = getFsDocument code
+ let expected = [
+ { Content = ": Song"; Location = (2, 18) }
+ { Content = ": string"; Location = (4, 11) }
+ { Content = "song = "; Location = (4, 23) }
+ ]
+
+ let actual = getAllHints document
+
+ CollectionAssert.AreEquivalent(expected, actual)
diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj
index 15b068503d..6889c74771 100644
--- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj
+++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj
@@ -105,8 +105,17 @@
Editor\Hints\HintTestFramework.fs
-
- Editor\Hints\HintServiceTests.fs
+
+ Editor\Hints\InlineParameterNameHintTests.fs
+
+
+ Editor\Hints\InlineTypeHintTests.fs
+
+
+ Editor\Hints\OptionParserTests.fs
+
+
+ Editor\Hints\OverallHintExperienceTests.fs
Editor\GoToDefinitionServiceTests.fs