Skip to content

Conversation

@jjonescz
Copy link
Member

@jjonescz jjonescz commented Aug 16, 2025

Fixes missing source generated code. For example, go to AliasAndExternAliasDirective and observe missing link to ExternAliasDirectiveSyntax because that class is entirely source-generated, etc. See also https://source.dot.net/Microsoft.CodeAnalysis.CSharp/diagnostics.txt for a sample list of errors caused by source generated files missing.

Outdated info about commit 1

This fix includes the source generator DLLs to be packed in stage1output via BinLogToSln. That means they are loaded in the second stage. I guess that might cause errors (shouldn't be blocking, like no errors are during source indexing) when the Roslyn referenced by a source generator is newer (e.g., 5.0.0) than the Roslyn referenced by source indexer (e.g., 4.14.0). An alternative might be to just emit the source-generated files during the first stage (via something like complog generated) but that seems more complicated and probably wouldn't prevent the same errors happening in stage1 (which runs as a separate job in official builds). (We should probably just replace BinLogToSln with complog anyway, but that's larger work.)

This fix includes the source generated files in the BinLogToSln stage by extracting them from the PDB.

@jjonescz
Copy link
Member Author

@jaredpar @ericstj for reviews, thanks

Copy link
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

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

Comment about analyzer tearing

@ericstj ericstj requested a review from joperezr August 18, 2025 23:28
}

#nullable enable
// From https://github.com/jaredpar/complog/blob/a629fb3c05e40ebe673410144e8911bd5f86bdf2/src/Basic.CompilerLog.Util/RoslynUtil.cs#L440.
Copy link
Member Author

@jjonescz jjonescz Aug 19, 2025

Choose a reason for hiding this comment

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

📝 I've also considered using Basic.CompilerLog.Util directly here, but currently BinLogToSln is using more information (properties of the MSBuild evaluated project) than the complog library makes available.

Copy link
Member

Choose a reason for hiding this comment

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

What all properties are being used here?

Also should we just make that method in CompilerLog public?

Copy link
Member Author

@jjonescz jjonescz Aug 21, 2025

Choose a reason for hiding this comment

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

What all properties are being used here?

UseForSourceIndex, IsPlatformNotSupportedAssembly, TargetFramework. But I guess it doesn't matter which specific properties are being used, it would be best to have the complog util expose all project properties like the BinLogParser utility in this repo does:

ProjectProperties = project?.GetEvaluation(build)?.GetProperties() ?? new Dictionary<string, string>(),

Also should we just make that method in CompilerLog public?

Good idea. Here's a PR: jaredpar/complog#261

Copy link
Member

Choose a reason for hiding this comment

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

I had to add two implementations of this, one for the in-memory model and a different one for the replay. Replay was a bit trickier, but necessary since we use that to be able to handle large binlogs.

I added open-ended support for project properties because a) I wanted to learn b) I thought it might be useful in the future. Probably the information we need could be deduced from other things (like attributes on the assembly).

I see that the complog tool is already doing it's own sort of Replay implementation and already capturing some properties -- https://github.com/jaredpar/complog/blob/a629fb3c05e40ebe673410144e8911bd5f86bdf2/src/Basic.CompilerLog.Util/BinaryLogUtil.cs#L164

So probably you'd want to port logic similar to what I added here. We could capture all the properties, if small enough, or just those that the caller wants to preserve. I bet all the properties is small enough compared to the overall size of these.

Copy link
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

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

Feedback

@jjonescz jjonescz requested a review from jaredpar August 20, 2025 08:18
}

#nullable enable
// From https://github.com/jaredpar/complog/blob/a629fb3c05e40ebe673410144e8911bd5f86bdf2/src/Basic.CompilerLog.Util/RoslynUtil.cs#L440.
Copy link
Member

Choose a reason for hiding this comment

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

What all properties are being used here?

Also should we just make that method in CompilerLog public?

string refPath = DedupeReference(output, path);
project.WriteLine($" <ReferencePath Include=\"{Path.Join(projToOutputPath, refPath)}\"/>");
includeFile(filePath, out string projectRelativePath, out string link);
project.WriteLine($" <Compile Include=\"{projectRelativePath}\"{(link != null ? $" Link=\"{link}\"" : "")}/>");
Copy link
Member

Choose a reason for hiding this comment

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

Do all callers to includeFile need to write the item? If so, maybe we can move that into the function like it is for includeReference?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, only this one. All the other callers work with existing files.

Copy link
Member

Choose a reason for hiding this comment

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

Probably we're looking at different things. I saw the same write for Compile item on line 287 - I guess you still have KeyOriginatorFile. Consider adding includeCompile to be consistent with includeReference.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, I've misunderstood, thanks.

@jjonescz
Copy link
Member Author

@ericstj can you merge this if it looks good to you? Thanks!

project.WriteLine(" <GenerateAssemblyInfo>false</GenerateAssemblyInfo>");
project.WriteLine(" <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>");
project.WriteLine(" <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>");
project.WriteLine(" <_SkipAnalyzers>true</_SkipAnalyzers>"); // we only need source generators
Copy link
Member

Choose a reason for hiding this comment

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

is this comment still correct? Is it skipping built in analyzers? Maybe we could use some public property to do that?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think there is a public property for this, and yes, I believe we should still set this to avoid running analyzers unnecessarily, but you're right the comment is outdated - we don't need even source generators now (but there is no simple property to set to exclude them).

<PackageVersion Include="Shouldly" Version="4.3.0" />

<!-- other dependencies -->
<PackageVersion Include="Basic.CompilerLog.Util" Version="0.9.17" />
Copy link
Member

Choose a reason for hiding this comment

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

Can you please follow up and make sure https://www.nuget.org/packages/Basic.CompilerLog.Util/ gets a license and source repository added to it's NuGet package? You might even get a component governance alert from this after merging into official build.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm, I can, but I believe this is already used in other repos, e.g., in sdk (although perhaps only in tests there).

Copy link
Member

Choose a reason for hiding this comment

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

Most repos don't build tests during official builds - official builds are what require CG to pass.

You can check out https://aka.ms/opensource to see what requirements we have for using new dependencies in OSS. I don't object to this dependency, but it would be good to make sure we're checking all the right boxes when taking such a dependency for tools which run in official builds.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it fine to follow up separately or is this blocking merge of the PR?

@jjonescz jjonescz merged commit c4876a5 into dotnet:main Sep 5, 2025
2 checks passed
@jjonescz jjonescz deleted the sg branch September 5, 2025 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants