phmonte / Buildalyzer

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

[Discussion] Calling `GetCompilationAsync` on ASP.NET Framework project returns empty compilation #237

Closed michaelhthomas closed 5 months ago

michaelhthomas commented 9 months ago

I'm using the following to attempt to obtain the Compilation results for each of the projects in a solution:

AnalyzerManager manager = new AnalyzerManager(@"..\..\..\..\Solution.sln");
AdhocWorkspace workspace = new AdhocWorkspace();
var projects = manager.Projects.Values.ToList()
    .Select(x => x.AddToWorkspace(workspace));

foreach (var project in projects)
{
    var compilation = await project.GetCompilationAsync();
    var count = 0;

    foreach (var tree in compilation.SyntaxTrees)
    {
        count +=
            tree.GetRoot()
                .DescendantNodes()
                .OfType<ClassDeclarationSyntax>()
                .Count();
    }

    Console.WriteLine($"Project: {project.Name} Class Count: {count}");
}

The class count for each of the .NET (framework) class library projects in the solution is non-zero, but for the one ASP.NET Framework project, it is consistently zero. Any thoughts?

daveaglick commented 6 months ago

Sorry for the delay - been swamped at the actual day job recently.

We've seen issues with some project types that use a custom SDK because they essentially bypass a lot of the work that MSBuild does and that Buildalyzer is configured to find. Can you share an example project file for a project that you're seeing this problem for?

michaelhthomas commented 5 months ago

All good! This ended up being due to the project not building due to compilation errors. It was an ASP.NET framework project, and several of the custom MSBuild targets weren't working in Buildalyzer. I was able to get it working by debugging and looking at the diagnostics on the compilation object. Would be nice if MSBuild errors / warnings could be automatically proxied to sdout or something to make things like this a bit easier to diagnose.

daveaglick commented 5 months ago

The choice not to write directly to stdout or stderr was intentional - I didn't know how consumers would be using the library, and I didn't want a bunch of stuff that wasn't intended to be surfaced bubbling up. That said, you can hook the captured output streams with either a ILoggerFactory or a TextWriter and forward them to your application's output:

StringWriter log = new StringWriter();
IProjectAnalyzer analyzer = new AnalyzerManager(
    new AnalyzerManagerOptions
    {
        LogWriter = log
    })
    .GetProject(projectFile);