jbevain / cecil

Cecil is a library to inspect, modify and create .NET programs and libraries.
MIT License
2.74k stars 624 forks source link

Analyzing F# code quotations with mono.cecil #822

Closed nicolasprevot closed 2 years ago

nicolasprevot commented 2 years ago

I am working on a program which, among other things, lists the method calls done within the body of a method.

Given the C# program:

    class Program
    {
        static void Main(string[] args)
        {
            var a = A.Fake<IList<string>>();
            A.CallTo(() => a.Count).Returns(4);
        }
    }

The instructions (listed by mono cecil) of the body of the Main method include: 'IL_0031: ldtoken System.Int32 System.Collections.Generic.ICollection`1::get_Count() which is what I want

However, given the equivalent F# program:

[<EntryPoint>]
let main argv =
    let a = A.Fake<IList<int>>()
    A.CallTo(fun () -> a.Count).Returns(3)  |> ignore

The instructions (listed by mono cecil) of the body of the main method do not include the get_Count() method They include things like:

Is there any way to get mono cecil to list the get_Count() method in this case?

SimonCropp commented 2 years ago

it is most likely that F# has compiled the delegate into another class/method. use ILSpy to have a look at what the f# compiles to. u can use the IL option

image
jbevain commented 2 years ago

Hello,

As you can read from the instructions, the F# compiler encodes the AST as a byte[] that is deserialized at runtime.

There's not much Cecil can do here, you can read the byte[] InitialValue property from the field that is loaded, but that's going to be on you to decode what the byte[] array means.

Thanks!