Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: type constraint should not be generated when the type is a "return type" #157

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 54 additions & 42 deletions src/Glutinum.Converter/Printer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -163,68 +163,74 @@ let private printAttributes
printer.NewLine
)

let rec private tryTransformTypeParametersToText
let rec printTypeParametersDeclaration
(printer: Printer)
(typeParameters: FSharpTypeParameter list)
=
let printer = new Printer()
let innterPrinter = new Printer()

if not typeParameters.IsEmpty then
printer.WriteInline("<")
innterPrinter.WriteInline("<")

typeParameters
|> List.iteri (fun index typeParameter ->
if index <> 0 then
printer.WriteInline(", ")
innterPrinter.WriteInline(", ")

printer.WriteInline($"'{typeParameter.Name}")
innterPrinter.WriteInline($"'{typeParameter.Name}")
)

// Print the constraints only if we are in the initial declaration.
// We want to avoid situations like the following:
// static member User<'T when 'T :> A> () : User<'T when 'T :> A> = nativeOnly
// Which should be:
// static member User<'T when 'T :> A> () : User<'T> = nativeOnly
typeParameters
|> List.filter _.Constraint.IsSome
|> List.iteri (fun index typeParameter ->
match typeParameter.Constraint with
| Some constraint_ ->
if index = 0 then
printer.WriteInline(" when ")
innterPrinter.WriteInline(" when ")
else
printer.WriteInline(" and ")
innterPrinter.WriteInline(" and ")

printer.WriteInline($"'{typeParameter.Name}")
printer.WriteInline(" :> ")
printer.WriteInline(printType constraint_)
innterPrinter.WriteInline($"'{typeParameter.Name}")
innterPrinter.WriteInline(" :> ")
innterPrinter.WriteInline(printType constraint_)
| None -> ()
)

printer.WriteInline(">")

printer.ToStringWithoutTrailNewLine() |> Some
innterPrinter.WriteInline(">")

else
None
innterPrinter.ToStringWithoutTrailNewLine() |> printer.WriteInline

and printTypeParameters
(printer: Printer)
and printTypeNameWithTypeParameters
(name: string)
(typeParameters: FSharpTypeParameter list)
=
match tryTransformTypeParametersToText typeParameters with
| Some typeParameters -> printer.WriteInline(typeParameters)
| None -> ()
let printer = new Printer()

and printType (fsharpType: FSharpType) =
let printTypeNameWithTypeParemeters
(name: string)
(typeParameters: FSharpTypeParameter list)
=
match tryTransformTypeParametersToText typeParameters with
| Some typeParameters -> $"{name}{typeParameters}"
| None -> name
if not typeParameters.IsEmpty then
printer.WriteInline("<")

typeParameters
|> List.iteri (fun index typeParameter ->
if index <> 0 then
printer.WriteInline(", ")

printer.WriteInline($"'{typeParameter.Name}")
)

printer.WriteInline(">")

$"{name}{printer.ToStringWithoutTrailNewLine()}"

and printType (fsharpType: FSharpType) =
match fsharpType with
| FSharpType.Object -> "obj"
| FSharpType.Mapped info ->
match tryTransformTypeParametersToText info.TypeParameters with
| Some typeParameters -> $"{info.Name}{typeParameters}"
| None -> info.Name
printTypeNameWithTypeParameters info.Name info.TypeParameters

| FSharpType.SingleErasedCaseUnion info -> info.Name

Expand All @@ -247,7 +253,7 @@ and printType (fsharpType: FSharpType) =
$"{info.Name}<{cases}>{option}"

| FSharpType.ThisType thisTypeInfo ->
printTypeNameWithTypeParemeters
printTypeNameWithTypeParameters
thisTypeInfo.Name
thisTypeInfo.TypeParameters

Expand Down Expand Up @@ -309,14 +315,14 @@ and printType (fsharpType: FSharpType) =
match apiInfo with
| FSharpJSApi.ReadonlyArray typ -> $"ReadonlyArray<{printType typ}>"
| FSharpType.Interface interfaceInfo ->
printTypeNameWithTypeParemeters
printTypeNameWithTypeParameters
interfaceInfo.Name
interfaceInfo.TypeParameters
| FSharpType.Class classInfo -> classInfo.Name
| FSharpType.TypeAlias aliasInfo ->
printTypeNameWithTypeParemeters aliasInfo.Name aliasInfo.TypeParameters
printTypeNameWithTypeParameters aliasInfo.Name aliasInfo.TypeParameters
| FSharpType.Delegate delegateInfo ->
printTypeNameWithTypeParemeters
printTypeNameWithTypeParameters
delegateInfo.Name
delegateInfo.TypeParameters
| FSharpType.Module _
Expand Down Expand Up @@ -503,7 +509,7 @@ let private printInterface (printer: Printer) (interfaceInfo: FSharpInterface) =
printAttributes printer interfaceInfo.Attributes

printer.Write($"type {interfaceInfo.Name}")
printTypeParameters printer interfaceInfo.TypeParameters
printTypeParametersDeclaration printer interfaceInfo.TypeParameters
printer.WriteInline(" =")
printer.NewLine

Expand Down Expand Up @@ -532,7 +538,7 @@ let private printInterface (printer: Printer) (interfaceInfo: FSharpInterface) =

printer.WriteInline($"member {methodInfo.Name}")

printTypeParameters printer methodInfo.TypeParameters
printTypeParametersDeclaration printer methodInfo.TypeParameters

if methodInfo.IsStatic then
printer.WriteInline(" ")
Expand Down Expand Up @@ -704,7 +710,9 @@ import {{ %s{interfaceInfo.OriginalName} }} from \"{Naming.MODULE_PLACEHOLDER}\"

printer.Write($"static member inline {staticMemberInfo.Name} ")

printTypeParameters printer staticMemberInfo.TypeParameters
printTypeParametersDeclaration
printer
staticMemberInfo.TypeParameters

if staticMemberInfo.Parameters.IsEmpty then
printer.WriteInline("() : ")
Expand Down Expand Up @@ -811,7 +819,7 @@ let private printClass (printer: Printer) (classInfo: FSharpClass) =
printAttributes printer classInfo.Attributes

printer.Write($"type {classInfo.Name}")
printTypeParameters printer classInfo.TypeParameters
printTypeParametersDeclaration printer classInfo.TypeParameters
printer.NewLine
printer.Indent
printPrimaryConstructor printer classInfo.PrimaryConstructor
Expand Down Expand Up @@ -897,7 +905,7 @@ let private printTypeAlias (printer: Printer) (aliasInfo: FSharpTypeAlias) =
printAttributes printer aliasInfo.Attributes

printer.Write($"type {aliasInfo.Name}")
printTypeParameters printer aliasInfo.TypeParameters
printTypeParametersDeclaration printer aliasInfo.TypeParameters
printer.WriteInline(" =")

printer.NewLine
Expand All @@ -908,7 +916,7 @@ let private printTypeAlias (printer: Printer) (aliasInfo: FSharpTypeAlias) =

let private printDelegate (printer: Printer) (delegateInfo: FSharpDelegate) =
printer.Write($"type {delegateInfo.Name}")
printTypeParameters printer delegateInfo.TypeParameters
printTypeParametersDeclaration printer delegateInfo.TypeParameters
printer.WriteInline(" =")

printer.NewLine
Expand Down Expand Up @@ -992,7 +1000,11 @@ let rec private print (printer: Printer) (fsharpTypes: FSharpType list) =
(FSharpAttribute.Erase :: erasedCaseUnionInfo.Attributes)

printer.Write($"type {erasedCaseUnionInfo.Name}")
printTypeParameters printer [ erasedCaseUnionInfo.TypeParameter ]

printTypeParametersDeclaration
printer
[ erasedCaseUnionInfo.TypeParameter ]

printer.WriteInline(" =")

printer.NewLine
Expand Down
3 changes: 3 additions & 0 deletions tests/specs/references/class/generics/oneWithConstraint.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class A {}

class User<T extends A = A> {}
28 changes: 28 additions & 0 deletions tests/specs/references/class/generics/oneWithConstraint.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module rec Glutinum

open Fable.Core
open Fable.Core.JsInterop
open System

[<AbstractClass>]
[<Erase>]
type Exports =
[<Import("A", "REPLACE_ME_WITH_MODULE_NAME"); EmitConstructor>]
static member A () : A = nativeOnly
[<Import("User", "REPLACE_ME_WITH_MODULE_NAME"); EmitConstructor>]
static member User<'T when 'T :> A> () : User<'T> = nativeOnly

[<AllowNullLiteral>]
[<Interface>]
type A =
interface end

[<AllowNullLiteral>]
[<Interface>]
type User<'T when 'T :> A> =
interface end

(***)
#r "nuget: Fable.Core"
#r "nuget: Glutinum.Types"
(***)