Skip to content
Closed
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
5 changes: 2 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
<PackageVersion Include="Microsoft.Build.Framework" Version="" PrivateAssets="all" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="" PrivateAssets="all" />
<PackageVersion Include="Microsoft.Build.Tasks.Core" Version="" PrivateAssets="all" />
<PackageVersion Include="Ionide.ProjInfo" Version="0.62.0" />
<PackageVersion Include="Ionide.ProjInfo.Sln" Version="0.62.0" />
<PackageVersion Include="Ionide.ProjInfo" Version="0.74.2" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Suave" Version="2.6.2" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
Expand All @@ -29,4 +28,4 @@
<PackageVersion Include="G-Research.FSharp.Analyzers" Version="0.21.0" />
<PackageVersion Include="Ionide.Analyzers" Version="0.14.11" />
</ItemGroup>
</Project>
</Project>
22 changes: 15 additions & 7 deletions src/fsdocs-tool/ProjectCracker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,15 @@ module Crack =


let result =
// Needs to be done before anything else
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude moved this to earlier in the flow (i.e. the start of crackProjects).

let cwd = System.Environment.CurrentDirectory |> System.IO.DirectoryInfo
let dotnetExe = getDotnetHostPath () |> Option.map System.IO.FileInfo
let _toolsPath = Init.init cwd dotnetExe
ProjectLoader.getProjectInfo projectFile extraMsbuildProperties BinaryLogGeneration.Off customProperties
//file |> Inspect.getProjectInfos loggedMessages.Enqueue msbuildExec [gp] []
let projectCollection = new Microsoft.Build.Evaluation.ProjectCollection(dict extraMsbuildProperties)
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProjectCollection implements IDisposable, but it’s currently created without being disposed/unloaded. When cracking multiple projects this can retain evaluated projects, hold file handles, and increase memory usage. Use a use binding (or try/finally) to dispose the ProjectCollection after loadProject/getLoadedProjectInfo completes.

Suggested change
let projectCollection = new Microsoft.Build.Evaluation.ProjectCollection(dict extraMsbuildProperties)
use projectCollection = new Microsoft.Build.Evaluation.ProjectCollection(dict extraMsbuildProperties)

Copilot uses AI. Check for mistakes.

match ProjectLoader.loadProject projectFile BinaryLogGeneration.Off projectCollection with
| Ok loadedProject ->
match ProjectLoader.getLoadedProjectInfo projectFile customProperties loadedProject with
| Ok(ProjectLoader.LoadedProjectInfo.StandardProjectInfo projOptions) -> Ok projOptions
| Ok _ -> Error $"project '%s{projectFile}' is not a standard project"
Copy link
Author

@Smaug123 Smaug123 Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other cases would have failed anyway, says Claude; we should just be moving the error earlier. Claude is confident of that statement, but I haven't completely tracked everything down. Here's a partial analysis, with additional comments inline in code snippets from Claude.

The type definition is https://github.com/ionide/proj-info/blob/35d34d3e2181e476d3c008c291670253eee35afc/src/Ionide.ProjInfo/Library.fs#L997 .

  type LoadedProjectInfo =
      | StandardProjectInfo of ProjectOptions   // Normal .fsproj/.csproj with design-time build
      | TraversalProjectInfo of ProjectReference list  // IsTraversal=true (e.g., dirs.proj aggregators)
      | OtherProjectInfo of ProjectInstance     // No design-time targets (e.g., .shproj)

proj-info classifies them at https://github.com/ionide/proj-info/blob/35d34d3e2181e476d3c008c291670253eee35afc/src/Ionide.ProjInfo/Library.fs#L661

  match pi with
  | IsTraversal -> Ok(TraversalProject pi)           // Has IsTraversal=true property
  | DesignTimeCapable designTimeTargets -> doDesignTimeBuild ()  // Has all design-time build targets
  | _ -> Ok(Other pi)                                // Lacks design-time targets

On main which uses v0.62.0 of proj-info, loadProject runs design-time build unconditionally: https://github.com/ionide/proj-info/blob/v0.62.0/src/Ionide.ProjInfo/Library.fs#L542

Claude claims that a traversal project or a shared project wouldn't have ResolveAssemblyReferencesDesignTime, so the Build call would error on main; we're just making the error more explicit. It's not clear to me that this is actually true.

| Error e -> Error e
| Error e -> Error e

let msgs = (loggedMessages.ToArray() |> Array.toList)

Expand Down Expand Up @@ -428,7 +431,7 @@ module Crack =

let getProjectsFromSlnFile (slnPath: string) =
match InspectSln.tryParseSln slnPath with
| Ok(_, slnData) -> InspectSln.loadingBuildOrder slnData
| Ok slnData -> InspectSln.loadingBuildOrder slnData

//this.LoadProjects(projs, crosstargetingStrategy, useBinaryLogger, numberOfThreads)
| Error e -> raise (exn ("cannot load the sln", e))
Expand All @@ -438,6 +441,11 @@ module Crack =
=
let slnDir = Path.GetFullPath "."

// Initialize the MSBuild integration - must be done before any ProjectCollection is created
let cwd = System.Environment.CurrentDirectory |> System.IO.DirectoryInfo
let dotnetExe = getDotnetHostPath () |> Option.map System.IO.FileInfo
let _toolsPath = Init.init cwd dotnetExe

//printfn "x.projects = %A" x.projects
let collectionName, projectFiles =
match projects, ignoreProjects with
Expand Down
2 changes: 1 addition & 1 deletion src/fsdocs-tool/fsdocs-tool.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<PackageReference Include="FSharp.Core" />
<PackageReference Include="CommandLineParser" />
<PackageReference Include="Ionide.ProjInfo" />
<PackageReference Include="Ionide.ProjInfo.Sln" />
<PackageReference Include="Microsoft.Build" IncludeAssets="compile" ExcludeAssets="runtime" PrivateAssets="all" />
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<PackageReference Include="Suave" />
</ItemGroup>
</Project>