Skip to content

Commit 40d54e5

Browse files
committed
SimpleAsyncComplementaryHelpers: check typed tree
If there is no explicit return type.
1 parent aaa4990 commit 40d54e5

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

src/FSharpLint.Core/Rules/Conventions/Naming/SimpleAsyncComplementaryHelpers.fs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ open FSharpLint.Rules.Utilities.LibraryHeuristics
99
open Helper.Naming.Asynchronous
1010
open FSharp.Compiler.Syntax
1111
open FSharp.Compiler.Text
12+
open Utilities.TypedTree
13+
open FSharp.Compiler.Symbols
1214

1315
[<RequireQualifiedAccess>]
1416
type Config = {
1517
Mode: AsynchronousFunctionsMode
1618
}
1719

1820
type private ReturnType =
19-
| Async of typeParam: Option<SynType> * isLowercase: bool
20-
| Task of typeParam: Option<SynType>
21+
| Async of typeParamString: Option<string> * isLowercase: bool
22+
| Task of typeParamString: Option<string>
2123

2224
type private Func =
2325
{
@@ -49,11 +51,6 @@ let runner (config: Config) (args: AstNodeRuleParams) =
4951
| Some text -> text
5052
| None -> failwithf "Invalid range: %A" func.Range
5153

52-
let tryGetTypeParamString (maybeTypeParam: Option<SynType>) =
53-
match maybeTypeParam with
54-
| Some typeParam -> ExpressionUtilities.tryFindTextOfRange typeParam.Range args.FileContent
55-
| None -> None
56-
5754
let message =
5855
match func.ReturnType with
5956
| Async (typeParam, isLowercase) ->
@@ -69,7 +66,7 @@ let runner (config: Config) (args: AstNodeRuleParams) =
6966
else
7067
newFuncName
7168
let typeDefString =
72-
match tryGetTypeParamString typeParam with
69+
match typeParam with
7370
| Some "unit" -> ": Task"
7471
| Some str -> $": Task<{str}>"
7572
| None -> String.Empty
@@ -84,7 +81,7 @@ let runner (config: Config) (args: AstNodeRuleParams) =
8481
| Task typeParam ->
8582
let newFuncName = funcDefinitionString.Replace(func.BaseName + asyncSuffixOrPrefix, asyncSuffixOrPrefix + func.BaseName)
8683
let typeDefString =
87-
match tryGetTypeParamString typeParam with
84+
match typeParam with
8885
| Some str -> $": Async<{str}>"
8986
| None -> String.Empty
9087
String.Format(
@@ -112,6 +109,20 @@ let runner (config: Config) (args: AstNodeRuleParams) =
112109
| None
113110
| Some(SynAccess.Public _) -> true
114111
| _ -> config.Mode = AllAPIs
112+
113+
let tryGetReturnTypeParamDisplayName (returnType: FSharpType) =
114+
match tryGetLastGenericArg returnType with
115+
| Some paramType->
116+
if paramType.HasTypeDefinition then
117+
// TryGetFullDisplayName() sometimes returns None even when DisplayName doesn't fail,
118+
// so use DisplayName instead but in try-with block.
119+
try
120+
Some paramType.TypeDefinition.DisplayName
121+
with
122+
| _ -> None
123+
else
124+
None
125+
| _ -> None
115126

116127
let tryGetFunction (binding: SynBinding) =
117128
match binding with
@@ -120,8 +131,19 @@ let runner (config: Config) (args: AstNodeRuleParams) =
120131
let returnTypeParam =
121132
match returnInfo with
122133
| Some(SynBindingReturnInfo(SynType.App(SynType.LongIdent(SynLongIdent _), _, [ typeParam ], _, _, _, _), _, _, _)) ->
123-
Some typeParam
124-
| _ -> None
134+
ExpressionUtilities.tryFindTextOfRange typeParam.Range args.FileContent
135+
| _ ->
136+
match args.CheckInfo with
137+
| Some checkInfo ->
138+
match getFunctionReturnType checkInfo args.Lines funcIdent with
139+
| Some returnType ->
140+
match returnType with
141+
| FSharpTypeAsync -> tryGetReturnTypeParamDisplayName returnType
142+
| FSharpTypeTask -> tryGetReturnTypeParamDisplayName returnType
143+
| FSharpTypeTaskNonGeneric -> Some "unit"
144+
| FSharpTypeNonAsync -> None
145+
| None -> None
146+
| None -> None
125147

126148
let funcArgs =
127149
match argPats with

0 commit comments

Comments
 (0)