Skip to content

Commit 2392c79

Browse files
CopilotbaronfelCopilot
authored
Fix terminal logger quiet mode to show project context for warnings/errors (#12930)
### Context In quiet mode (`-v:q`), warnings and errors were rendered immediately without project context. Users saw diagnostic messages but couldn't identify which project they came from. ``` CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization ``` ### Changes Made **Modified diagnostic accumulation logic** - `WarningRaised` and `ErrorRaised` now accumulate diagnostics in the project's `BuildMessages` collection regardless of verbosity - Removed verbosity check that caused immediate rendering in quiet mode - Preserved immediate rendering for auth provider warnings and immediate warnings (MSB3026) **Modified project summary rendering** - `ProjectFinished` now displays project summaries in quiet mode when `HasErrorsOrWarnings` is true - Projects without diagnostics remain hidden in quiet mode as expected - Simplified quiet mode detection logic: `Verbosity < LoggerVerbosity.Quiet || (Verbosity == LoggerVerbosity.Quiet && !project.HasErrorsOrWarnings)` - Skip `DisplayNodes()` call in quiet mode to avoid writing unnecessary cursor hide/show ANSI codes since there's no dynamic refresh **Result in quiet mode:** ``` project failed with 1 error(s) and 2 warning(s) (0.2s) directory/file(1,2,3,4): warning AA0000: Warning message directory/file(1,2,3,4): error AA0000: Error message ``` ### Testing - Updated snapshot files for `PrintBuildSummaryQuietVerbosity_FailedWithErrors` across Linux/OSX/Windows - All 69 TerminalLogger tests pass - Verified successful projects still produce no output in quiet mode - Verified no cursor control codes are written in quiet mode output ### Notes Uses the same project-grouping primitives as higher verbosity levels, toggled by runtime state per maintainer guidance. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Terminal logger quiet mode hides projects</issue_title> > <issue_description>This was reported by @gao-artur in microsoft/testfx#7051 > > > Here is a new project created from the MSTest template without `MSTestSettings.cs` file + the binlog. Built with > > > > `dotnet build -bl -v q` > > [TestProject11.zip](https://github.com/user-attachments/files/23968849/TestProject11.zip) > > In that thread we determined that `-tl` status affects the usefulness of the output for messages that do not have a specific file associated with them: > > ```sh-session > ❯ dotnet build > Restore complete (4.0s) > TestProject11 net9.0 succeeded with 1 warning(s) (2.3s) → bin\Debug\net9.0\TestProject11.dll > CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization (https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0001) > > Build succeeded with 1 warning(s) in 7.2s > > ❯ rm -r .\obj\ > > ❯ dotnet build -v:q > CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization (https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0001) > ``` > > The associated project `TestProject11` is not mentioned anywhere in the latter. I think that's unreasonable even when the user has requested "quiet".</issue_description> > > <agent_instructions>Try to update the diagnostic/warning/error message rendering in quiet mode so that it doesn't use the 'immediate' mode formatting, the final output should only show the diagnostics for projects that failed or had warnings.</agent_instructions> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > <comment_new><author>@baronfel</author><body> > A few approaches to consider: > > * in quiet mode appending/prepending the project if it exists to the 'message formatting' part of the line > * in quiet mode using the same project-based grouping as we do in non-quiet mode, instead of assuming that quiet mode should trigger some kind of flat-list-only output</body></comment_new> > <comment_new><author>@rainersigwald</author><body> > Yeah I waffled between the two myself, I think I lean to the latter right now though.</body></comment_new> > <comment_new><author>@baronfel</author><body> > I do too - it feels more like a 'modular' approach - use the same 'primitives' that can be toggled on/off based on run-time state, etc.</body></comment_new> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #12929 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: baronfel <[email protected]> Co-authored-by: Chet Husk <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent fb77584 commit 2392c79

4 files changed

+45
-38
lines changed
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet`
2-
directory/file(1,2,3,4): warning AA0000: Warning!
3-
directory/file(1,2,3,4): warning AA0000:
4-
A
5-
Multi
6-
Line
7-
Warning!
8-
directory/file(1,2,3,4): error AA0000: Error!
2+
project failed with 1 error(s) and 2 warning(s) (0.2s)
3+
directory/file(1,2,3,4): warning AA0000: Warning!
4+
directory/file(1,2,3,4): warning AA0000:
5+
A
6+
Multi
7+
Line
8+
Warning!
9+
directory/file(1,2,3,4): error AA0000: Error!
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet`
2-
directory/file(1,2,3,4): warning AA0000: Warning!
3-
directory/file(1,2,3,4): warning AA0000:
4-
A
5-
Multi
6-
Line
7-
Warning!
8-
directory/file(1,2,3,4): error AA0000: Error!
2+
project failed with 1 error(s) and 2 warning(s) (0.2s)
3+
directory/file(1,2,3,4): warning AA0000: Warning!
4+
directory/file(1,2,3,4): warning AA0000:
5+
A
6+
Multi
7+
Line
8+
Warning!
9+
directory/file(1,2,3,4): error AA0000: Error!
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet`
2-
directory/file(1,2,3,4): warning AA0000: Warning!
3-
directory/file(1,2,3,4): warning AA0000:
4-
A
5-
Multi
6-
Line
7-
Warning!
8-
directory/file(1,2,3,4): error AA0000: Error!
2+
project failed with 1 error(s) and 2 warning(s) (0.2s)
3+
directory/file(1,2,3,4): warning AA0000: Warning!
4+
directory/file(1,2,3,4): warning AA0000:
5+
A
6+
Multi
7+
Line
8+
Warning!
9+
directory/file(1,2,3,4): error AA0000: Error!

src/Build/Logging/TerminalLogger/TerminalLogger.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -754,18 +754,23 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e)
754754
UpdateNodeStatus(buildEventContext, null);
755755
}
756756

757-
// Continue execution and add project summary to the static part of the Console only if verbosity is higher than Quiet.
758-
if (Verbosity <= LoggerVerbosity.Quiet)
759-
{
760-
return;
761-
}
762-
763757
ProjectContext c = new(buildEventContext);
764758

765759
if (_projects.TryGetValue(c, out TerminalProjectInfo? project))
766760
{
767761
project.Succeeded = e.Succeeded;
768762
project.Stopwatch.Stop();
763+
764+
// In quiet mode, only show projects with errors or warnings.
765+
// In higher verbosity modes, show projects based on other criteria.
766+
if (Verbosity == LoggerVerbosity.Quiet && !project.HasErrorsOrWarnings)
767+
{
768+
// Still need to update counts even if not displaying
769+
_buildErrorsCount += project.ErrorCount;
770+
_buildWarningsCount += project.WarningCount;
771+
return;
772+
}
773+
769774
lock (_lock)
770775
{
771776
Terminal.BeginUpdate();
@@ -809,6 +814,7 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e)
809814
// If this was a notable project build, we print it as completed only if it's produced an output or warnings/error.
810815
// If this is a test project, print it always, so user can see either a success or failure, otherwise success is hidden
811816
// and it is hard to see if project finished, or did not run at all.
817+
// In quiet mode, we show the project header if there are errors/warnings (already checked above).
812818
else if (project.OutputPath is not null || project.BuildMessages is not null || project.IsTestProject)
813819
{
814820
// Show project build complete and its output
@@ -839,7 +845,7 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e)
839845
_buildErrorsCount += project.ErrorCount;
840846
_buildWarningsCount += project.WarningCount;
841847

842-
if (_showNodesDisplay)
848+
if (_showNodesDisplay && Verbosity > LoggerVerbosity.Quiet)
843849
{
844850
DisplayNodes();
845851
}
@@ -1300,27 +1306,24 @@ private void WarningRaised(object sender, BuildWarningEventArgs e)
13001306
}
13011307

13021308
if (buildEventContext is not null
1303-
&& _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project)
1304-
&& Verbosity > LoggerVerbosity.Quiet)
1309+
&& _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project))
13051310
{
13061311
// If the warning is not a 'global' auth provider message, but is immediate, we render it immediately
13071312
// but we don't early return so that the project also tracks it.
1308-
if (IsImmediateWarning(e.Code))
1313+
if (IsImmediateWarning(e.Code) && Verbosity > LoggerVerbosity.Quiet)
13091314
{
13101315
RenderImmediateMessage(FormatWarningMessage(e, Indentation));
13111316
}
13121317

13131318
// This is the general case - _most_ warnings are not immediate, so we add them to the project summary
13141319
// and display them in the per-project and final summary.
1320+
// In quiet mode, we still accumulate so they can be shown in project-grouped form later.
13151321
project.AddBuildMessage(TerminalMessageSeverity.Warning, FormatWarningMessage(e, TripleIndentation));
13161322
}
13171323
else
13181324
{
13191325
// It is necessary to display warning messages reported by MSBuild,
1320-
// even if it's not tracked in _projects collection or the verbosity is Quiet.
1321-
// The idea here (similar to the implementation in ErrorRaised) is that
1322-
// even in Quiet scenarios we need to show warnings/errors, even if not in
1323-
// full project-tree view
1326+
// even if it's not tracked in _projects collection.
13241327
RenderImmediateMessage(FormatWarningMessage(e, Indentation));
13251328
_buildWarningsCount++;
13261329
}
@@ -1385,14 +1388,15 @@ private void ErrorRaised(object sender, BuildErrorEventArgs e)
13851388
BuildEventContext? buildEventContext = e.BuildEventContext;
13861389

13871390
if (buildEventContext is not null
1388-
&& _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project)
1389-
&& Verbosity > LoggerVerbosity.Quiet)
1391+
&& _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project))
13901392
{
1393+
// Always accumulate errors in the project, even in quiet mode, so they can be shown
1394+
// in project-grouped form later.
13911395
project.AddBuildMessage(TerminalMessageSeverity.Error, FormatErrorMessage(e, TripleIndentation));
13921396
}
13931397
else
13941398
{
1395-
// It is necessary to display error messages reported by MSBuild, even if it's not tracked in _projects collection or the verbosity is Quiet.
1399+
// It is necessary to display error messages reported by MSBuild, even if it's not tracked in _projects collection.
13961400
// For nicer formatting, any messages from the engine we strip the file portion from.
13971401
bool hasMSBuildPlaceholderLocation = e.File.Equals("MSBUILD", StringComparison.Ordinal);
13981402
RenderImmediateMessage(FormatErrorMessage(e, Indentation, requireFileAndLinePortion: !hasMSBuildPlaceholderLocation));

0 commit comments

Comments
 (0)