@@ -9,15 +9,17 @@ open FSharpLint.Rules.Utilities.LibraryHeuristics
99open Helper.Naming .Asynchronous
1010open FSharp.Compiler .Syntax
1111open FSharp.Compiler .Text
12+ open Utilities.TypedTree
13+ open FSharp.Compiler .Symbols
1214
1315[<RequireQualifiedAccess>]
1416type Config = {
1517 Mode: AsynchronousFunctionsMode
1618}
1719
1820type 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
2224type 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