diff --git a/vsintegration/src/FSharp.Editor/Common/InternalOptionBuilder.fs b/vsintegration/src/FSharp.Editor/Common/InternalOptionBuilder.fs
new file mode 100644
index 000000000000..66d78b7845c4
--- /dev/null
+++ b/vsintegration/src/FSharp.Editor/Common/InternalOptionBuilder.fs
@@ -0,0 +1,13 @@
+module internal Microsoft.VisualStudio.FSharp.Editor.InternalOptionBuilder
+
+type InternalOptionBuilder() =
+ member _.Bind(x, f) = Option.bind f x
+ member _.Return(x) = Some x
+ member _.ReturnFrom(x) = x
+ member _.Zero() = Some()
+
+let internalOption = InternalOptionBuilder()
+let inline (|>>) v f = Option.map f v
+let inline (|>!) v f = Option.bind f v
+let inline (>->) f g v = f v |>> g
+let inline (>=>) f g v = f v >>= g
diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
index 015d28448cb2..dd6104d84c8d 100644
--- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
+++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
@@ -42,6 +42,7 @@
+
diff --git a/vsintegration/src/FSharp.Editor/Refactor/AddExplicitReturnType.fs b/vsintegration/src/FSharp.Editor/Refactor/AddExplicitReturnType.fs
index a5d0c6c90e03..02954e80388d 100644
--- a/vsintegration/src/FSharp.Editor/Refactor/AddExplicitReturnType.fs
+++ b/vsintegration/src/FSharp.Editor/Refactor/AddExplicitReturnType.fs
@@ -19,15 +19,16 @@ open Microsoft.CodeAnalysis.CodeRefactorings
open Microsoft.CodeAnalysis.CodeActions
open CancellableTasks
open System.Diagnostics
+open InternalOptionBuilder
[]
type internal AddExplicitReturnType [] () =
inherit CodeRefactoringProvider()
static member isValidMethodWithoutTypeAnnotation
- (funcOrValue: FSharpMemberOrFunctionOrValue)
(symbolUse: FSharpSymbolUse)
(parseFileResults: FSharpParseFileResults)
+ (funcOrValue: FSharpMemberOrFunctionOrValue)
=
let typeAnnotationRange =
parseFileResults.TryRangeOfReturnTypeHint(symbolUse.Range.Start, false)
@@ -36,10 +37,15 @@ type internal AddExplicitReturnType [] () =
funcOrValue.IsFunction
&& parseFileResults.IsBindingALambdaAtPosition symbolUse.Range.Start
- (not funcOrValue.IsValue || not isLambdaIfFunction)
- && not (funcOrValue.ReturnParameter.Type.IsUnresolved)
- && not (parseFileResults.IsTypeAnnotationGivenAtPosition symbolUse.Range.Start)
- && not typeAnnotationRange.IsNone
+ let res =
+ (not funcOrValue.IsValue || not isLambdaIfFunction)
+ && not (funcOrValue.ReturnParameter.Type.IsUnresolved)
+ && not (parseFileResults.IsTypeAnnotationGivenAtPosition symbolUse.Range.Start)
+ && not typeAnnotationRange.IsNone
+
+ match res with
+ | true -> Some funcOrValue
+ | false -> None
static member refactor
(context: CodeRefactoringContext)
@@ -76,6 +82,11 @@ type internal AddExplicitReturnType [] () =
do context.RegisterRefactoring(codeAction)
+ static member ofFSharpMemberOrFunctionOrValue(symbol: FSharpSymbol) =
+ match symbol with
+ | :? FSharpMemberOrFunctionOrValue as v -> Some v
+ | _ -> None
+
override _.ComputeRefactoringsAsync context =
backgroundTask {
let document = context.Document
@@ -96,23 +107,26 @@ type internal AddExplicitReturnType [] () =
|> CancellableTask.start ct
let res =
- lexerSymbol
- |> Option.bind (fun lexer ->
- checkFileResults.GetSymbolUseAtLocation(
- fcsTextLineNumber,
- lexer.Ident.idRange.EndColumn,
- textLine.ToString(),
- lexer.FullIsland
- ))
- |> Option.bind (fun symbolUse ->
- match symbolUse.Symbol with
- | :? FSharpMemberOrFunctionOrValue as v when
- AddExplicitReturnType.isValidMethodWithoutTypeAnnotation v symbolUse parseFileResults
- ->
- Some(symbolUse, v)
- | _ -> None)
- |> Option.map (fun (symbolUse, memberFunc) ->
- AddExplicitReturnType.refactor context (symbolUse, memberFunc, parseFileResults))
+ internalOption {
+ let! lexerSymbol = lexerSymbol
+
+ let! symbolUse =
+ checkFileResults.GetSymbolUseAtLocation(
+ fcsTextLineNumber,
+ lexerSymbol.Ident.idRange.EndColumn,
+ textLine.ToString(),
+ lexerSymbol.FullIsland
+ )
+
+ let! memberFunc =
+ symbolUse.Symbol |> AddExplicitReturnType.ofFSharpMemberOrFunctionOrValue
+ |>! AddExplicitReturnType.isValidMethodWithoutTypeAnnotation symbolUse parseFileResults
+
+ let res =
+ AddExplicitReturnType.refactor context (symbolUse, memberFunc, parseFileResults)
+
+ return res
+ }
return res
}
diff --git a/vsintegration/src/FSharp.Editor/Refactor/RemoveExplicitReturnType.fs b/vsintegration/src/FSharp.Editor/Refactor/RemoveExplicitReturnType.fs
index f0d35316fa77..299f5c12eb1a 100644
--- a/vsintegration/src/FSharp.Editor/Refactor/RemoveExplicitReturnType.fs
+++ b/vsintegration/src/FSharp.Editor/Refactor/RemoveExplicitReturnType.fs
@@ -19,6 +19,7 @@ open Microsoft.CodeAnalysis.CodeActions
open CancellableTasks
open System.Diagnostics
open Microsoft.CodeAnalysis.Text
+open InternalOptionBuilder
[]
type internal RemoveExplicitReturnType [] () =
@@ -65,9 +66,9 @@ type internal RemoveExplicitReturnType [] () =
newSpan
static member isValidMethodWithoutTypeAnnotation
- (funcOrValue: FSharpMemberOrFunctionOrValue)
(symbolUse: FSharpSymbolUse)
(parseFileResults: FSharpParseFileResults)
+ (funcOrValue: FSharpMemberOrFunctionOrValue)
=
let returnTypeHintAlreadyPresent =
parseFileResults.TryRangeOfReturnTypeHint(symbolUse.Range.Start, false)
@@ -77,8 +78,13 @@ type internal RemoveExplicitReturnType [] () =
funcOrValue.IsFunction
&& parseFileResults.IsBindingALambdaAtPosition symbolUse.Range.Start
- (not funcOrValue.IsValue || not isLambdaIfFunction)
- && returnTypeHintAlreadyPresent
+ let res =
+ (not funcOrValue.IsValue || not isLambdaIfFunction)
+ && returnTypeHintAlreadyPresent
+
+ match res with
+ | true -> Some funcOrValue
+ | false -> None
static member refactor
(context: CodeRefactoringContext)
@@ -114,6 +120,11 @@ type internal RemoveExplicitReturnType [] () =
do context.RegisterRefactoring(codeAction)
+ static member ofFSharpMemberOrFunctionOrValue(symbol: FSharpSymbol) =
+ match symbol with
+ | :? FSharpMemberOrFunctionOrValue as v -> Some v
+ | _ -> None
+
override _.ComputeRefactoringsAsync context =
backgroundTask {
let document = context.Document
@@ -134,23 +145,26 @@ type internal RemoveExplicitReturnType [] () =
|> CancellableTask.start ct
let res =
- lexerSymbol
- |> Option.bind (fun lexer ->
- checkFileResults.GetSymbolUseAtLocation(
- fcsTextLineNumber,
- lexer.Ident.idRange.EndColumn,
- textLine.ToString(),
- lexer.FullIsland
- ))
- |> Option.bind (fun symbolUse ->
- match symbolUse.Symbol with
- | :? FSharpMemberOrFunctionOrValue as v when
- RemoveExplicitReturnType.isValidMethodWithoutTypeAnnotation v symbolUse parseFileResults
- ->
- Some(v, symbolUse)
- | _ -> None)
- |> Option.map (fun (memberFunc, symbolUse) ->
- RemoveExplicitReturnType.refactor context memberFunc parseFileResults symbolUse)
+ internalOption {
+ let! lexerSymbol = lexerSymbol
+
+ let! symbolUse =
+ checkFileResults.GetSymbolUseAtLocation(
+ fcsTextLineNumber,
+ lexerSymbol.Ident.idRange.EndColumn,
+ textLine.ToString(),
+ lexerSymbol.FullIsland
+ )
+
+ let! memberFunc =
+ symbolUse.Symbol |> RemoveExplicitReturnType.ofFSharpMemberOrFunctionOrValue
+ |>! RemoveExplicitReturnType.isValidMethodWithoutTypeAnnotation symbolUse parseFileResults
+
+ let res =
+ RemoveExplicitReturnType.refactor context memberFunc parseFileResults symbolUse
+
+ return res
+ }
return res
}