Skip to content

Commit

Permalink
Add constraints to return types inner generics (#1342)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAngryByrd authored Jan 14, 2025
1 parent c8546f6 commit d2b0e84
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 9 deletions.
22 changes: 15 additions & 7 deletions src/FsAutoComplete.Core/SignatureFormatter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,24 @@ module SignatureFormatter =
"Unknown"

let retTypeConstraint =
if func.ReturnParameter.Type.IsGenericParameter then
let formattedParam =
formatGenericParameter false displayContext func.ReturnParameter.Type.GenericParameter
let genericParamConstraints = ResizeArray<string>()

if String.IsNullOrWhiteSpace formattedParam then
formattedParam
let rec getGenericParameters (f : FSharpType) =
if f.IsGenericParameter then
let formattedParam = formatGenericParameter false displayContext f.GenericParameter
if not <| String.IsNullOrWhiteSpace formattedParam then
genericParamConstraints.Add formattedParam
else
"(requires " + formattedParam + " )"
try
f.GenericArguments |> Seq.iter getGenericParameters
with
| e -> () // Sometimes GenericArguments throws an exception when accessing it

getGenericParameters func.ReturnParameter.Type
if Seq.isEmpty genericParamConstraints then ""
else
""
let formattedParam = genericParamConstraints |> String.join " and " |> _.Trim()
"(requires " + formattedParam + ")"

let safeParameterName (p: FSharpParameter) =
match Option.defaultValue p.DisplayNameCore p.Name with
Expand Down
17 changes: 16 additions & 1 deletion test/FsAutoComplete.Tests.Lsp/CoreTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,22 @@ let tooltipTests state =
" input: Expr"
" -> option<objnull * System.Type>" ])
#endif
verifySignature
77u
5u
(concatLines [
"val testIWSAMTest:"
" unit"
" -> Result<string,'e> (requires :> IWSAMTest<'e>)"
])
verifySignature
90u
25u
(concatLines [
"static member GetAwaiter:"
" awaitable: 'Awaitable (requires member GetAwaiter )"
" -> Awaiter<^Awaiter,'TResult> (requires :> ICriticalNotifyCompletion and member IsCompleted and member GetResult)"
])
verifySignature
65u
7u
Expand All @@ -442,7 +458,6 @@ let tooltipTests state =
70u
7u
(concatLines

#if NET8_0
[ "active pattern ValueWithName: "
" input: Expr"
Expand Down
25 changes: 24 additions & 1 deletion test/FsAutoComplete.Tests.Lsp/TestCases/Tooltips/Script.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,27 @@ let testActivePatternSignatureWithSubStringName (expr: Quotations.Expr) =

match expr with
| ValueWithName t -> t
| _ -> failwith "no value match"
| _ -> failwith "no value match"

open System.Runtime.CompilerServices
type IWSAMTest<'e> =
static abstract member Test : int -> 'e

let testIWSAMTest<'e when IWSAMTest<'e>> () =
if 42 > 0 then Ok "Worlds Sane"
else Error ('e.Test 42)

type Awaiter<'Awaiter, 'TResult
when 'Awaiter :> ICriticalNotifyCompletion
and 'Awaiter: (member get_IsCompleted: unit -> bool)
and 'Awaiter: (member GetResult: unit -> 'TResult)> = 'Awaiter

type Awaitable<'Awaitable, 'Awaiter, 'TResult
when 'Awaitable: (member GetAwaiter: unit -> Awaiter<'Awaiter, 'TResult>)> = 'Awaitable

type Awaitable =
static member inline GetAwaiter<'Awaitable, 'Awaiter, 'TResult
when Awaitable<'Awaitable, 'Awaiter, 'TResult>>
(awaitable: 'Awaitable)
=
awaitable.GetAwaiter()

0 comments on commit d2b0e84

Please sign in to comment.