Skip to content

fix(dotnet): consume all MSBuild BuildEventArgsFieldFlags in binlog reader - #4620

Open
viniciusdsandrade wants to merge 4 commits into
rtk-ai:developfrom
viniciusdsandrade:fix/dotnet-binlog-event-field-flags
Open

viniciusdsandrade wants to merge 4 commits into
rtk-ai:developfrom
viniciusdsandrade:fix/dotnet-binlog-event-field-flags

Conversation

@viniciusdsandrade

@viniciusdsandrade viniciusdsandrade commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Consume all MSBuild BuildEventArgsFieldFlags in read_event_fields in MSBuild's serialization order so structured RECORD_WARNING and RECORD_ERROR events preserve their diagnostic code, file path, line, and column.

Closes #4587

Context & Problem

In MSBuild's binary log format (BuildEventArgsWriter.WriteBaseFields), base event fields are written in this order when their BuildEventArgsFieldFlags bits are set:

  1. Message (1 << 2): deduplicated string
  2. BuildEventContext (1 << 0): 7 x 7-bit ints (6 in v1)
  3. ThreadId (1 << 4): 7-bit int
  4. HelpKeyword (1 << 1): deduplicated string
  5. SenderName (1 << 3): deduplicated string (set whenever SenderName != null && SenderName != "MSBuild", such as "Csc" for compiler warnings and errors)
  6. Timestamp (1 << 5): i64 ticks (8 bytes LE) + DateTimeKind (7-bit int)
  7. Extended (1 << 16): extended type, dictionary, and extended comment

Followed by optional message diagnostic/location flags (Subcategory, Code, File, ProjectFile, LineNumber, ColumnNumber, EndLineNumber, EndColumnNumber), Arguments, and Importance.

src/cmds/dotnet/binlog.rs only handled Message, BuildEventContext, Timestamp, Extended, Arguments, and Importance. When a task such as Csc logged a warning or error with SenderName = "Csc", read_event_fields did not read the 1-byte SenderName string index before Timestamp. As a result, Timestamp's read_i64_le() + read_7bit_i32() consumed SenderName + the 8-byte Ticks (whose high byte is < 0x80), leaving Timestamp.Kind unread in the stream.

Subsequent reads in RECORD_ERROR | RECORD_WARNING were shifted by one field:

  • _subcategory read Timestamp.Kind
  • code read Subcategory ("")
  • file read Code (for example "CS0168")
  • _project_file read File (for example "Beta.cs")
  • line read the ProjectFile string index (for example 53)
  • column read LineNumber (for example 7)

This produced corrupted warning output such as CS0168(53,7): The variable 'unused' is declared... with the source file path lost.

Solution

  • Define the remaining FLAG_* constants from MSBuild's BuildEventArgsFieldFlags in src/cmds/dotnet/binlog.rs.
  • Read ThreadId, HelpKeyword, SenderName, and optional message diagnostic/location fields in read_event_fields in MSBuild's exact serialization order.
  • Add a unit test (test_parse_build_reads_events_with_sender_name_and_optional_flags) verifying that RECORD_WARNING and RECORD_ERROR events with BuildEventContext, ThreadId, HelpKeyword, SenderName, and Timestamp retain their code, file, line, column, and message.

How to Test

Verified by static code inspection against MSBuild's BuildEventArgsFieldFlags / BuildEventArgsWriter / BuildEventArgsReader and src/cmds/dotnet/binlog.rs; execution is delegated to the PR CI matrix:

cargo test --lib cmds::dotnet::binlog::tests

Checklist

  • cargo test passes (pending CI execution; not run locally)
  • cargo clippy --all-targets clean (pending CI execution; not run locally)
  • cargo fmt --check clean (pending CI execution; not run locally)
  • Single-line format adds [\u{26a1} N tokens] badge (via format_badge()) (N/A: binlog parser bug fix)
  • Multi-line format ends with summary_footer() line (N/A: binlog parser bug fix)
  • Saved tokens > 0 on realistic fixture (no negative savings) (N/A: binlog parser bug fix)

…eader

MSBuild's BuildEventArgsWriter serializes ThreadId, HelpKeyword, and SenderName between BuildEventContext and Timestamp when their flags are set, and serializes optional diagnostic location fields for message records before Arguments and Importance. When compiler tasks such as Csc emit warnings or errors with SenderName set, skipping those flags shifts subsequent stream reads by one field, causing RECORD_WARNING and RECORD_ERROR to read Code into File, ProjectFile index into Line, and Line into Column.

Signed-off-by: Vinícius DS Andrade <[email protected]>
Add a unit test verifying that RECORD_WARNING and RECORD_ERROR preserve their code, file path, line, column, and message when optional base event flags (BuildEventContext, ThreadId, HelpKeyword, SenderName, Timestamp) are present.

Signed-off-by: Vinícius DS Andrade <[email protected]>
@rtk-wshm-sync-bot rtk-wshm-sync-bot Bot added area:cli bug Something isn't working effort-small Quelques heures, 1 fichier labels Oct 17, 2026
@rtk-wshm-sync-bot

Copy link
Copy Markdown

wshm · Automated triage by AI

📊 Automated PR Analysis

🐛 Type bug-fix
🟢 Risk low

Summary

Fixes the MSBuild binlog field parser in src/cmds/dotnet/binlog.rs to read all BuildEventArgsFieldFlags (ThreadId, HelpKeyword, SenderName, and diagnostic/location fields) in MSBuild's exact serialization order. Previously, events with SenderName set (e.g., from Csc) caused a byte offset that corrupted warning/error code, file, line, and column fields. Adds a unit test verifying correct parsing of such events.

Review Checklist

  • Tests present
  • Breaking change
  • Docs updated

Linked issues: #4587


Analyzed automatically by wshm · This is an automated analysis, not a human review.

cargo fmt --check failed on the aligned string-record comments in the
test, which is a gate the project requires before merge. Formatting
only, no behavior change.
read_event_fields also consumed the Subcategory..EndColumnNumber
fields when their flag bits were set. Issue rtk-ai#4587 only needs ThreadId,
HelpKeyword and SenderName read before Timestamp, and no test sets the
diagnostic bits. The warning and error record already reads those same
fields positionally right after read_event_fields, so a record that
set the bits would have them consumed twice and shift every later read.

The MSBuild writer could not be checked offline and the repository has
no real binlog fixture, so leave the diagnostic fields out until a
captured log backs them with a test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:cli bug Something isn't working effort-small Quelques heures, 1 fichier

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dotnet build: binlog warnings lose file path and column (e.g. Beta.cs(7,13) printed as CS0168(53,7))

1 participant