|
| 1 | +# Debugging a Type Provider |
| 2 | + |
| 3 | +Debugging a type provider can be difficult because it is a program run at compile-time and editing-time in host compilation tools including |
| 4 | +`fsc.exe`, `devenv.exe` and `FsAutoComplete.exe`. |
| 5 | + |
| 6 | +This articule discusses some techniques you can use to debug a type provider when it is run inside these different tools. |
| 7 | + |
| 8 | +## How do I debug execution of a type provider when using .NET SDK tools? |
| 9 | + |
| 10 | +To debug a use of a type provider inside the `dotnet` toolchain, you should first isolate a precise invocation of the `dotnet` tool used in compilation. |
| 11 | + |
| 12 | +1. Capture output of `dotnet build -v:n` in `args.txt` and trim out the rubbish leaving just the command line arguments to the F# compiler, usually starting with `-o:...` |
| 13 | + |
| 14 | +2. Run an explicit invocation of the compiler, checking that your failures still happen, then debug that invocation. |
| 15 | + |
| 16 | +For example, on Windows: |
| 17 | + |
| 18 | +```text |
| 19 | +"c:\Program Files\dotnet\dotnet.exe" "C:\Program Files\dotnet\sdk\2.1.403\FSharp\fsc.exe" @args.txt |
| 20 | +
|
| 21 | +devenv /debugexe "c:\Program Files\dotnet\dotnet.exe" "C:\Program Files\dotnet\sdk\2.1.403\FSharp\fsc.exe" @args.txt |
| 22 | +``` |
| 23 | + |
| 24 | +Be careful to make sure Visual Studio debugging type is set to ".NET Core" (right click properties on dotnet and set debug type). Set first-catch exception handling (Ctrl-Alt-E, select all CLR exceptions) and set Just My Code off. |
| 25 | + |
| 26 | +## How do I debug execution of a type provider hosted in F# Interactive? |
| 27 | + |
| 28 | +If your failures only happen in F# Interactive then use `devenv /debugexe fsi.exe MyProj.fsproj`, or a simialr .NET SDK invocation. |
| 29 | + |
| 30 | +## How do I debug execution of a type provider inside an IDE? |
| 31 | + |
| 32 | +This can be quite tricky. First try to unit-test the type-provider and debug command-line invocations thoroughly. If your failures only happen |
| 33 | +in Visual Studio, then use `devenv /debugexe devenv.exe MyProj.fsproj`, set debug type to ".NET Framework 4.0" |
| 34 | +and launch F5. |
| 35 | + |
| 36 | +## How do I debug execution of a type provider when using .NET Framework tools? |
| 37 | + |
| 38 | +To debug a use of a type provider inside the `msbuild` toolchain (.NET Framework), you should first isolate a precise invocation of the `dotnet` tool used in compilation. |
| 39 | + |
| 40 | +1. Capture output of `msbuild -v:n` in `args.txt` and trim to leave the command line arguments to the F# compiler, usually starting with `-o:...` |
| 41 | + |
| 42 | +2. Run an explicit invocation of the compiler using this, checking that your failures still happen, then debug that invocation. |
| 43 | + |
| 44 | +For example, on Windows: |
| 45 | + |
| 46 | +```text |
| 47 | +fsc.exe @args.txt |
| 48 | +
|
| 49 | +devenv /debugexe fsc.exe @args.txt |
| 50 | +``` |
| 51 | + |
| 52 | +Set first-catch exception handling (Ctrl-Alt-E, select all CLR exceptions) and set Just My Code off. |
| 53 | + |
| 54 | +## A dependency of my type provider is not loading, what do I do? |
| 55 | + |
| 56 | +For example, let's say you have this error in your test project: |
| 57 | + |
| 58 | +```text |
| 59 | +2>E:\GitHub\admin\joe-provider\test\Joe.Test\ProviderTests.fs(8,10): error FS3033: The type provider 'Joe.Provider.JoeProvider' reported an error: Could not load file or assembly 'Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. The system cannot find the file specified. [E:\GitHub\dsyme\joe-provider\test\Joe.Test\Joe.Test.fsproj] |
| 60 | +``` |
| 61 | + |
| 62 | +Here your test project is referencing your provider project, and your type provider has a dependency on `Newtonsoft.Json.dll`. To see what's going on, run |
| 63 | + |
| 64 | +```text |
| 65 | +dotnet build -v:n |
| 66 | +``` |
| 67 | + |
| 68 | +In the compilation of your test project you will see something like this: |
| 69 | + |
| 70 | +```text |
| 71 | +C:\Program Files\dotnet\dotnet.exe "C:\Program Files\dotnet\sdk\3.1.401\FSharp\fsc.exe" |
| 72 | + -o:obj\Debug\net5.0\Joe.Test.dll |
| 73 | + ... |
| 74 | + -r:E:\GitHub\admin\joe-provider\src\Joe.Provider\bin\Debug\netstandard2.0\Joe.Provider.dll |
| 75 | + ... |
| 76 | +``` |
| 77 | + |
| 78 | +1. The tool `fsc.exe` is trying to load the type provider but a dependency is not found. As mentioned above, all dependencies must be packaged |
| 79 | + alongside your design time component. For example, adding |
| 80 | + |
| 81 | + ```text |
| 82 | + <Content Include="..\..\packages\Newtonsoft.Json\lib\netstandard2.0\Newtonsoft.Json.dll" CopyToOutputDirectory="PreserveNewest" /> |
| 83 | + ``` |
| 84 | + |
| 85 | + will include the component and unblock you. However, you will need to be careful to make sure this component is laid down in the right place in your nuget |
| 86 | + package, see the instructions above for what the final layout of the nuget package should be. |
| 87 | + |
| 88 | +2. When making type providers whose design-time components have dependencies, you should always use a "split" type provider that separates the design-time and runtime components. |
| 89 | + |
| 90 | +TODO: give exact .fsproj/nuget instructions to get the dependency into the `typeproviders\fsharp41\netstandard2.0` directory alongside the design-time component. |
| 91 | + |
0 commit comments