Skip to content

Commit

Permalink
explain motivation for things and reshuffle
Browse files Browse the repository at this point in the history
  • Loading branch information
dawedawe committed Oct 27, 2023
1 parent 06b8c4a commit 8c787a8
Showing 1 changed file with 40 additions and 30 deletions.
70 changes: 40 additions & 30 deletions docs/content/Getting Started Using.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ We assume the analyzers you want to use are distributed as a nuget package.
## Using analyzers in a single project
First, we need to add the [fsharp-analyzers](https://www.nuget.org/packages/fsharp-analyzers) dotnet tool to the tool-manifest.
A dotnet CLI tool, called [fsharp-analyzers](https://www.nuget.org/packages/fsharp-analyzers), is used to run analyzers outside the context of an IDE.
Add it to your tool-manifest with:
```shell
dotnet tool install fsharp-analyzers
```
Expand All @@ -28,7 +29,15 @@ Next, add the `PackageReference` pointing to your favorite analyzers to the `.fs
```
At the time of writing, the [G-Research analyzers](https://github.com/g-research/fsharp-analyzers) [package](https://www.nuget.org/packages/G-Research.FSharp.Analyzers) contains the only analyzers compatible with the latest CLI tool.
Finally, add a custom MSBuild target to the `.fsproj` file for easy invocation of the analyzer:
With the package downloaded, we can run the CLI tool:
```shell
dotnet fsharp-analyzers --project ./YourProject.fsproj --analyzers-path C:\Users\yourusername\.nuget\packages\g-research.fsharp.analyzers\0.1.6\analyzers\dotnet\fs\ --verbose
```
As you can see, the path to the analyzer DLL files could be tricky to get right across a wide range of setups.
Luckily, we can use an MSBuild custom target to take care of the path construction.
Add the following target to the `.fsproj` file for easy invocation of the analyzer:
```xml
<Target Name="AnalyzeProject">
Expand All @@ -44,6 +53,7 @@ Finally, add a custom MSBuild target to the `.fsproj` file for easy invocation o
```
You may need to adjust the `Command` to be compatible with your specific analyzer. Think about how you want warnings to be treated.
To locate the analyzer DLLs in the filesystem, we use the variable `$(PkgG-Research_FSharp_Analyzers)`. It's produced by NuGet and normalized to be usable by [MSBuild](https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#generatepathproperty).
In general, a `Pkg` prefix is added and dots in the package ID are replaced by underscores. But make sure to look at the [nuget.g.props](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#restore-outputs) file in the `obj` folder for the exact string.
The `\analyzers\dotnet\fs` subpath is a convention analyzer authors should follow when creating their packages.
Expand All @@ -56,12 +66,11 @@ dotnet msbuild /t:AnalyzeProject
## Using analyzers in a solution
First, we need to add the [fsharp-analyzers](https://www.nuget.org/packages/fsharp-analyzers) dotnet tool to the tool-manifest.
```shell
dotnet tool install fsharp-analyzers
```
Adding the custom target from above to all `.fsproj` files of a solution doesn't scale very well.
So we use the MSBuild infrastructure to add the needed package reference and the MSBuild target to all projects in one go.
Next, add the `PackageReference` pointing to your favorite analyzers to the [Directory.Build.props](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file:
We start with adding the `PackageReference` pointing to your favorite analyzers to the [Directory.Build.props](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file.
This adds the package reference to all `.fsproj` files that are in a subfolder of the file location of `Directory.Build.props`:
```xml
<ItemGroup>
Expand All @@ -72,26 +81,8 @@ Next, add the `PackageReference` pointing to your favorite analyzers to the [Dir
</ItemGroup>
```
Add the following custom target to the [Directory.Solution.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-solution-build?view=vs-2022) file to be able to invoke analysis of the whole solution:
```xml
<Project>
<ItemGroup>
<ProjectsToAnalyze Include="src\**\*.fsproj" />
</ItemGroup>
<Target Name="AnalyzeSolution">
<MSBuild
Projects="@(ProjectsToAnalyze)"
Targets="AnalyzeProject" />
</Target>
</Project>
```
Finally, add the following custom target to the [Directory.Build.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file.
This takes care of invoking analysis of single projects:
Likewise we add the following custom target to the [Directory.Build.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file.
This is effectively the same as adding a target to each `*proj` file which exists in a subfolder.
```xml
<Project>
Expand All @@ -102,7 +93,7 @@ Finally, add the following custom target to the [Directory.Build.targets](https:
<Message Importance="High" Text="Analyzing $(MSBuildProjectFile)"/>
<Exec
ContinueOnError="true"
Command="dotnet fsharp-analyzers --project &quot;$(MSBuildProjectFile)&quot; --analyzers-path &quot;$(PkgG-Research_FSharp_Analyzers)\analyzers\dotnet\fs&quot; --exclude-analyzer PartialAppAnalyzer --fail-on-warnings GRA-STRING-001 GRA-STRING-002 GRA-STRING-003 GRA-UNIONCASE-001 --verbose --report &quot;$(MSBuildProjectName)-analysis.sarif&quot;">
Command="dotnet fsharp-analyzers --project &quot;$(MSBuildProjectFile)&quot; --analyzers-path &quot;$(PkgG-Research_FSharp_Analyzers)\analyzers\dotnet\fs&quot; --exclude-analyzer PartialAppAnalyzer --fail-on-warnings GRA-STRING-001 --verbose --report &quot;$(MSBuildProjectName)-analysis.sarif&quot;">
<Output TaskParameter="ExitCode" PropertyName="LastExitCode" />
</Exec>
<Error Condition="'$(LastExitCode)' == '-2'" Text="Problems were found $(MSBuildProjectFile)" />
Expand All @@ -112,9 +103,27 @@ Finally, add the following custom target to the [Directory.Build.targets](https:
</Project>
```
This is effectively the same as adding a target to each `*.proj` file which exist in subfolders.
You may need to adjust the `Command` to be compatible with your specific analyzer. Think about how you want warnings to be treated.
As we don't want to list all projects of the solution explicitly when analyzing the solution, we create a second cutom MSBuild target that calls the project-specific target for all projects.
Add the following custom target to the [Directory.Solution.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-solution-build?view=vs-2022) file to be able to invoke analysis of the whole solution in one simple command:
```xml
<Project>
<ItemGroup>
<ProjectsToAnalyze Include="src\**\*.fsproj" />
</ItemGroup>
<Target Name="AnalyzeSolution">
<MSBuild
Projects="@(ProjectsToAnalyze)"
Targets="AnalyzeProject" />
</Target>
</Project>
```
At last, you can run the analyzer from the solution folder:
```shell
Expand All @@ -124,8 +133,9 @@ dotnet msbuild /t:AnalyzeSolution
## Project Cracking
If all this seems a bit complex to you, let us explain some inner details to give you a better understanding:
The way the analyzers work is that we will programmatically type-check a project and process the results with our analyzers. In order to do this programmatically we need to construct the [FSharpProjectOptions](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-codeanalysis-fsharpprojectoptions.html).
This is essentially a type that represents all the fsharp compiler arguments. When using --project, we will use [ProjInfo](https://github.com/ionide/proj-info) to invoke a set of MSBuild targets in the project to perform a design-time build.
This is essentially a type that represents all the fsharp compiler arguments. When using `--project`, we will use [ProjInfo](https://github.com/ionide/proj-info) to invoke a set of MSBuild targets in the project to perform a design-time build.
A design-time build is basically an empty invocation of a build. It won't produce assemblies but will have constructed the correct arguments to theoretically invoke the compiler.
There's an alternative way to do this. Instead of using the `--project` argument, it's possible to use the `--fsc-args` argument to let the CLI tool construct the needed `FSharpProjectOptions`.
Expand Down

0 comments on commit 8c787a8

Please sign in to comment.