phmonte / Buildalyzer

A utility to perform design-time builds of .NET projects without having to think too hard about it.
MIT License
593 stars 94 forks source link

Automatically load ProjectReferences #159

Closed slang25 closed 3 years ago

slang25 commented 3 years ago

Hi, I love Buildalyzer.

It would be great if I could point it at a project file and have it analyze all of the project references too.

At the moment I am running this:

var workspace = analyzerManager.GetProject(testProj).GetWorkspace(true);
var solution = workspace.CurrentSolution;

However solution only has 1 project in it. To work around this, I can scan for all csproj files in the repo and call:

var projectFiles = Directory.EnumerateFiles("<path to my repo>/", "*.csproj", SearchOption.AllDirectories);

var analyzerManager = new AnalyzerManager();
foreach (var project in projectFiles)
{
    analyzerManager.GetProject(project);
}

I would love for this not to be required and for GetWorkspace(true) to automatically add the project to the analyzer.

daveaglick commented 3 years ago

I think I get the request, but let me be sure. The problem here is that you've got a project (a.csproj) and it exists in a solution (a.sln) that only contains a.csproj. However, a.csproj also references ../foo/b.csproj and so without that project reference being added to the workspace automatically, you end up with an incomplete workspace?

The title of this issue mentions PackageReference but based on the description I'm guessing that probably should have been ProjectReference? Just want to make sure I've got before I start brainstorming :)

slang25 commented 3 years ago

Thanks @daveaglick, yes the title was wrong 🤦

To give some context, I have no .sln, well technically I do (sometimes more than 1) but I want to ignore it/them. Just as I can do a dotnet build against a .csproj and it compiles it's dependencies, I want to process that group of projects in the same way, with the entrypoint csproj as the starting point.

daveaglick commented 3 years ago

As discussed in the PR, I've still got a little confusion over whether it's now doing what you need after the PR merge. I think the request is to make sure transitive project references get added, and it appears that's happening from my testing.

I added a new test project with the following project file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\SdkNetCoreProjectWithReference\SdkNetCoreProjectWithReference.csproj" />
  </ItemGroup>

</Project>

SdkNetCoreProjectWithReference.csproj looks like this (so it has two project references):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\SdkNetStandardProjectWithPackageReference\SdkNetStandardProjectWithPackageReference.csproj" />
    <ProjectReference Include="..\SdkNetStandardProject\SdkNetStandardProject.csproj" />
  </ItemGroup>

</Project>

If I run a test like:

// Given
StringWriter log = new StringWriter();
IProjectAnalyzer analyzer = GetProjectAnalyzer(@"projects\TransitiveProjectReference\TransitiveProjectReference.csproj", log);

// When
Workspace workspace = analyzer.GetWorkspace(addProjectReferences: true);

// Then
workspace.CurrentSolution.Projects.Count().ShouldBe(totalProjects, log.ToString());

I get the expected 4 projects in the workspace (the original, it's reference, and the two transitive references). That's because inside the code where we build and add a referenced project to the solution:

return analyzer.Build().FirstOrDefault().AddToWorkspace(workspace, addProjectReferences);

...we call the same AddToWorkspace() method we came from, which should recursively expand, build, and add additional project references (similar to the queue in the Codalyzer code you linked to except we're doing it recursively instead of with a queue).

So given the comment

When I use this PR alone, doesn't give the right results from a clean build, because I've not built the projects in the right order.

I feel like I'm still missing something (it's me, not you I'm sure!)

slang25 commented 3 years ago

Sorry the very slow reply. Yes you are right, it's building the projects in the right order and getting the right result.

I now have a better understanding of what was going wrong, I'm going to create a new issue, because it's a bit interesting.

slang25 commented 3 years ago

Closing this issue, as we are agreed it working. Raised a new issue here: https://github.com/daveaglick/Buildalyzer/issues/181