Skip to content

Commit

Permalink
Fixed attached indexers
Browse files Browse the repository at this point in the history
  • Loading branch information
ncave committed Oct 28, 2023
1 parent aa9eef5 commit 81a2796
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
23 changes: 12 additions & 11 deletions src/Fable.Transforms/FSharp2Fable.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,17 @@ type FsAbstractSignature(s: FSharpAbstractSignature) =
member _.DeclaringType = TypeHelpers.makeType Map.empty s.DeclaringType

type FsMemberFunctionOrValue(m: FSharpMemberOrFunctionOrValue) =
static member CompiledName(m: FSharpMemberOrFunctionOrValue) =
if FsMemberFunctionOrValue.IsGetter(m) ||
FsMemberFunctionOrValue.IsSetter(m)
then Naming.removeGetSetPrefix m.CompiledName
else m.CompiledName

static member DisplayName(m: FSharpMemberOrFunctionOrValue) =
Naming.removeGetSetPrefix m.DisplayNameCore
if FsMemberFunctionOrValue.IsGetter(m) ||
FsMemberFunctionOrValue.IsSetter(m)
then Naming.removeGetSetPrefix m.DisplayNameCore
else m.DisplayNameCore

// We don't consider indexer properties as getters/setters so they're always compiled as methods
static member IsGetter(m: FSharpMemberOrFunctionOrValue) =
Expand Down Expand Up @@ -692,7 +701,7 @@ module Helpers =
|> Option.defaultValue false

v.IsModuleValueOrMember && not v.HasSignatureFile && parentHasSignatureFile ()

let isNotPrivate (memb: FSharpMemberOrFunctionOrValue) =
if memb.IsCompilerGenerated then false
elif topLevelBindingHiddenBySignatureFile memb then false
Expand Down Expand Up @@ -1842,19 +1851,11 @@ module Util =
let arg = callInfo.Args |> List.tryHead |> Option.defaultWith makeNull
Fable.Set(callee, Fable.FieldSet(info.name), membType, arg, r)
else
// If the entity is decorated with AttachMembers, we need to remove the get/set prefix
// See https://github.com/fable-compiler/Fable/issues/3494
let membName =
if isAttachMembersEntity com entity then
Naming.removeGetSetPrefix info.name
else
info.name

let entityGenParamsCount = entity.GenericParameters.Count
let callInfo =
if callInfo.GenericArgs.Length < entityGenParamsCount then callInfo
else { callInfo with GenericArgs = List.skip entityGenParamsCount callInfo.GenericArgs }
getField callee membName |> makeCall r typ callInfo
getField callee info.name |> makeCall r typ callInfo

let failReplace (com: IFableCompiler) ctx r (info: Fable.ReplaceCallInfo) (thisArg: Fable.Expr option) =
let msg =
Expand Down
2 changes: 1 addition & 1 deletion src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ let private transformExplicitlyAttachedMember (com: FableCompiler) (ctx: Context
let name, isMangled =
match Compiler.Language with
| Rust -> getMemberDeclarationName com memb |> fst, true
| _ -> Naming.removeGetSetPrefix memb.CompiledName, false
| _ -> FsMemberFunctionOrValue.CompiledName(memb), false
com.AddAttachedMember(entFullName, isMangled=false, memb =
{ Name = name
Body = body
Expand Down
25 changes: 25 additions & 0 deletions tests/Js/Main/TypeTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ type TestType7(a1, a2, a3) =
let arr = [|a1; a2; a3|]
member _.Value with get(i) = arr.[i] and set(i) (v) = arr.[i] <- v

[<Fable.Core.AttachMembers>]
type TestTypeAttached(a1, a2, a3) =
let arr = [| a1; a2; a3 |]
member _.Value1
with get () = arr.[1]
and set (v) = arr.[1] <- v
member _.Value
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v
member _.Item
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v

type A = { thing: int } with
member x.show() = string x.thing
static member show (x: A) = "Static: " + (string x.thing)
Expand Down Expand Up @@ -633,6 +646,18 @@ let tests =
t.Value(1) |> equal 5
t.Value(2) |> equal 3

testCase "Attached Getters Setters and Indexers work" <| fun () ->
let t = TestTypeAttached(1, 2, 3)
t.Value1 |> equal 2
t.Value1 <- 22
t.Value1 |> equal 22
t.Value(0) |> equal 1
t.Value(0) <- 11
t.Value(0) |> equal 11
t[2] |> equal 3
t[2] <- 33
t[2] |> equal 33

testCase "Statically resolved instance calls work" <| fun () ->
let a = { thing = 5 }
let b = { label = "five" }
Expand Down
26 changes: 26 additions & 0 deletions tests/Python/TestType.fs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ type Type7Test(a1, a2, a3) =
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v

[<Fable.Core.AttachMembers>]
type TypeAttachedTest(a1, a2, a3) =
let arr = [| a1; a2; a3 |]
member _.Value1
with get () = arr.[1]
and set (v) = arr.[1] <- v
member _.Value
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v
member _.Item
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v

type A =
{ thing: int }
member x.show() = string x.thing
Expand Down Expand Up @@ -698,6 +711,19 @@ let ``test Getter and Setter with indexer work`` () =
t.Value(1) |> equal 5
t.Value(2) |> equal 3

[<Fact>]
let ``test Attached Getters Setters and Indexers work`` () =
let t = TypeAttachedTest(1, 2, 3)
t.Value1 |> equal 2
t.Value1 <- 22
t.Value1 |> equal 22
t.Value(0) |> equal 1
t.Value(0) <- 11
t.Value(0) |> equal 11
t.[2] |> equal 3
t.[2] <- 33
t.[2] |> equal 33

[<Fact>]
let ``test Statically resolved instance calls work`` () =
let a = { thing = 5 }
Expand Down
26 changes: 26 additions & 0 deletions tests/Rust/tests/src/TypeTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ type TestType7(a1, a2, a3) =
let arr = [|a1; a2; a3|]
member _.Value with get(i) = arr[i] and set(i) (v) = arr[i] <- v

[<Fable.Core.AttachMembers>]
type TestTypeAttached(a1, a2, a3) =
let arr = [| a1; a2; a3 |]
member _.Value1
with get () = arr.[1]
and set (v) = arr.[1] <- v
member _.Value
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v
member _.Item
with get (i) = arr.[i]
and set (i) (v) = arr.[i] <- v

type A = { thing: int } with
member x.show() = string x.thing
static member show (x: A) = "Static: " + (string x.thing)
Expand Down Expand Up @@ -632,6 +645,19 @@ let ``Getter and Setter with indexer work`` () =
t.Value(1) |> equal 5
t.Value(2) |> equal 3

[<Fact>]
let ``Attached Getters Setters and Indexers work`` () =
let t = TestTypeAttached(1, 2, 3)
t.Value1 |> equal 2
t.Value1 <- 22
t.Value1 |> equal 22
t.Value(0) |> equal 1
t.Value(0) <- 11
t.Value(0) |> equal 11
t[2] |> equal 3
t[2] <- 33
t[2] |> equal 33

[<Fact>]
let ``Statically resolved instance calls work`` () =
let a = { thing = 5 }
Expand Down

0 comments on commit 81a2796

Please sign in to comment.