Repository: dotnet/roslyn
File: src/Workspaces/MSBuild/Core/MSBuild/MSBuildProjectLoader.cs (C#)

Code before:

        var worker = new Worker(
            _solutionServices,
            _diagnosticReporter,
            _pathResolver,
            _projectFileExtensionRegistry,
            buildHostProcessManager,
            requestedProjectPaths: [projectFilePath],
            baseDirectory: Directory.GetCurrentDirectory(),
            projectMap,
            progress,
            requestedProjectOptions,
            discoveredProjectOptions,
            this.LoadMetadataForReferencedProjects);

        return await worker.LoadAsync(cancellationToken).ConfigureAwait(false);
    }

    private static bool IsBinaryLogger([NotNullWhen(returnValue: true)] ILogger? logger)
    {
        return logger?.GetType().FullName == "Microsoft.Build.Logging.BinaryLogger";
    }

    private sealed class DefaultBinLogPathProvider(string? logFilePath) : IBinLogPathProvider
    {
        public string? GetNewLogPath() => logFilePath;
    }
}


Review comment (suggestion):
This needs to have a bit more logic here dealing with the fact this can be called more than once if we have to launch more than one build host process. I don't have a better idea than simply incrementing a suffix on the file name (msbuild.binlog, msbuild-1.binlog, etc.), but that's at least not going to cause us to potentially overwrite things. It's not great that tools using MSBuildWorkspace might not expect those extra files, but I'd say that's better than losing half the logs if we have to launch more than once process. And naturally if we only do launch one process, then it'll all still work as before.

Code after:

        var worker = new Worker(
            _solutionServices,
            _diagnosticReporter,
            _pathResolver,
            _projectFileExtensionRegistry,
            buildHostProcessManager,
            requestedProjectPaths: [projectFilePath],
            baseDirectory: Directory.GetCurrentDirectory(),
            projectMap,
            progress,
            requestedProjectOptions,
            discoveredProjectOptions,
            this.LoadMetadataForReferencedProjects);

        return await worker.LoadAsync(cancellationToken).ConfigureAwait(false);
    }

    private static bool IsBinaryLogger([NotNullWhen(returnValue: true)] ILogger? logger, out string? fileName)
    {
        // We validate the type name to avoid taking a dependency on the Microsoft.Build package
        // because it brings along additional dependencies and servicing requirements.
        if (logger?.GetType().FullName != "Microsoft.Build.Logging.BinaryLogger")
        {
            fileName = null;
            return false;
        }

        // The logger.Parameters could contain more than just the filename, such as "ProjectImports" or "OmitInitialInfo".
        // Attempt to get the parsed filname directly from the logger if possible.
        var fileNameProperty = logger.GetType().GetProperty("FileName");
        fileName = fileNameProperty?.GetValue(logger) as string ?? logger.Parameters;
        return true;
    }

    internal sealed class BinLogPathProvider : IBinLogPathProvider
    {
        private const string DefaultFileName = "msbuild";
        private const string DefaultExtension = ".binlog";

        private readonly string _directory;
        private readonly string _filename;
        private readonly string _extension;
        private int _suffix = -1;

        public BinLogPathProvider(string? logFilePath)
        {
            logFilePath ??= DefaultFileName + DefaultExtension;

            _directory = Path.GetDirectoryName(logFilePath) ?? ".";
            _filename = Path.GetFileNameWithoutExtension(logFilePath) is { Length: > 0 } fileName