Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 1 addition & 2 deletions src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ private MSBuildArgs(ReadOnlyDictionary<string, string>? properties, ReadOnlyDict
/// processing of the SDK and returns a structured set of MSBuild arguments grouped by purpose.
/// </summary>
/// <param name="forwardedAndUserFacingArgs">the complete set of forwarded MSBuild arguments and un-parsed, potentially MSBuild-relevant arguments</param>
/// <returns></returns>
public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedAndUserFacingArgs, params Option[] options)
{
var fakeCommand = new System.CommandLine.Command("dotnet");
foreach (var option in options)
{
fakeCommand.Options.Add(option);
}
;

var parseResult = fakeCommand.Parse([.. forwardedAndUserFacingArgs], _analysisParsingConfiguration);
var globalProperties = parseResult.GetResult("--property") is OptionResult propResult ? propResult.GetValueOrDefault<ReadOnlyDictionary<string, string>?>() : null;
var restoreProperties = parseResult.GetResult("--restoreProperty") is OptionResult restoreResult ? restoreResult.GetValueOrDefault<ReadOnlyDictionary<string, string>?>() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@

using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils.Extensions;
using Microsoft.DotNet.Cli;

namespace Microsoft.DotNet.Cli.Utils;

internal class MSBuildForwardingAppWithoutLogging
internal sealed class MSBuildForwardingAppWithoutLogging
{
private static readonly bool AlwaysExecuteMSBuildOutOfProc = Env.GetEnvironmentVariableAsBool("DOTNET_CLI_RUN_MSBUILD_OUTOFPROC");
private static readonly bool UseMSBuildServer = Env.GetEnvironmentVariableAsBool("DOTNET_CLI_USE_MSBUILD_SERVER", false);
Expand Down Expand Up @@ -41,7 +40,9 @@ public static string MSBuildVersion

private readonly Dictionary<string, string?> _msbuildRequiredEnvironmentVariables = GetMSBuildRequiredEnvironmentVariables();

private readonly List<string> _msbuildRequiredParameters = [ "-maxcpucount", "--verbosity:m" ];
private readonly List<string> _msbuildRequiredParameters = ["-maxcpucount", $"--verbosity:{DefaultVerbosity}"];

internal const VerbosityOptions DefaultVerbosity = VerbosityOptions.m;
Copy link
Member

Choose a reason for hiding this comment

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

nit: It might be good to put this const with the other consts above. In particular seeing it used in an initializer just before its definition causes me to do a double take, until I realize it is a const it feels like something may be wrong.


public MSBuildForwardingAppWithoutLogging(MSBuildArgs msbuildArgs, string? msbuildPath = null, bool includeLogo = false, bool isRestoring = true)
{
Expand Down Expand Up @@ -93,7 +94,7 @@ public ProcessStartInfo GetProcessStartInfo()

public string[] GetAllArguments()
{
return [.. _msbuildRequiredParameters, ..EmitMSBuildArgs(_msbuildArgs) ];
return [.. _msbuildRequiredParameters, .. EmitMSBuildArgs(_msbuildArgs)];
}

private string[] EmitMSBuildArgs(MSBuildArgs msbuildArgs) => [
Expand Down
4 changes: 2 additions & 2 deletions src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public VirtualProjectBuildingCommand(
Debug.Assert(Path.IsPathFullyQualified(entryPointFileFullPath));

EntryPointFileFullPath = entryPointFileFullPath;
MSBuildArgs = msbuildArgs.CloneWithAdditionalProperties(new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
MSBuildArgs = msbuildArgs.CloneWithAdditionalProperties(new Dictionary<string, string>(2, StringComparer.OrdinalIgnoreCase)
{
// See https://github.com/dotnet/msbuild/blob/main/documentation/specs/build-nonexistent-projects-by-default.md.
{ "_BuildNonexistentProjectsByDefault", bool.TrueString },
Expand Down Expand Up @@ -157,7 +157,7 @@ public ImmutableArray<CSharpDirective> Directives
public override int Execute()
{
Debug.Assert(!(NoRestore && NoBuild));
var verbosity = MSBuildArgs.Verbosity ?? VerbosityOptions.quiet;
var verbosity = MSBuildArgs.Verbosity ?? MSBuildForwardingAppWithoutLogging.DefaultVerbosity;
var consoleLogger = TerminalLogger.CreateTerminalOrConsoleLogger([$"--verbosity:{verbosity}", .. MSBuildArgs.OtherMSBuildArgs]);
var binaryLogger = GetBinaryLogger(MSBuildArgs.OtherMSBuildArgs);

Expand Down
62 changes: 62 additions & 0 deletions test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,68 @@ public void TerminalLogger(bool on)
}
}

[Fact]
public void Verbosity_Run()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var programFile = Path.Join(testInstance.Path, "Program.cs");
File.WriteAllText(programFile, s_program);

new DotnetCommand(Log, "run", "Program.cs", "--no-cache")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
// no additional build messages
Copy link
Member

Choose a reason for hiding this comment

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

It feels like if no build message is expected then it would be good to verify that, for example, the stdout does not contain Program.dll.

Copy link
Member Author

Choose a reason for hiding this comment

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

HaveStdOut verifies the stdout is exactly as written (nothing more), plus there is NotHaveStdErr to check stderr as well, but I can add .And.NotHaveStdOutContaining("Program.dll") to be even more specific.

.And.HaveStdOut("Hello from Program")
.And.NotHaveStdErr();
}

[Fact] // https://github.com/dotnet/sdk/issues/50227
public void Verbosity_Build()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var programFile = Path.Join(testInstance.Path, "Program.cs");
File.WriteAllText(programFile, s_program);

new DotnetCommand(Log, "build", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
// should print path to the built DLL
.And.HaveStdOutContaining("Program.dll");
}

[Fact]
public void Verbosity_CompilationDiagnostics()
{
var testInstance = _testAssetsManager.CreateTestDirectory();

File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
string x = null;
Console.WriteLine("ran" + x);
""");

new DotnetCommand(Log, "run", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
// warning CS8600: Converting null literal or possible null value to non-nullable type.
.And.HaveStdOutContaining("warning CS8600")
.And.HaveStdOutContaining("ran");

File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
Console.Write
""");

new DotnetCommand(Log, "run", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Fail()
// error CS1002: ; expected
.And.HaveStdOutContaining("error CS1002")
.And.HaveStdErrContaining(CliCommandStrings.RunCommandException);
}

/// <summary>
/// Default projects include embedded resources by default.
/// </summary>
Expand Down