From aa6ff15237c7a3598a7070400e82602eea00d933 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:23:17 +0100 Subject: [PATCH 1/7] Add agent instructions for MSBuild repository Added comprehensive instructions for GitHub Copilot and AI agents, covering repository overview, performance considerations, code review instructions, formatting guidelines, testing procedures, and development workflow. --- AGENTS.md | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..a0f1609612a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,293 @@ +# Agent Instructions + +Instructions for GitHub Copilot and other AI coding agents working with the MSBuild repository. + +## Repository Overview + +**MSBuild** is the Microsoft Build Engine - performance-critical infrastructure for .NET and Visual Studio builds. This repository contains the code for the MSBuild build engine, including its public C# API, its internal implementation of the MSBuild programming language, and core targets and tasks used for builds. + +### Key Components +- **Microsoft.Build**: Core MSBuild engine and public API +- **Microsoft.Build.Framework**: Framework interfaces and base types +- **Microsoft.Build.Tasks**: Built-in MSBuild tasks +- **Microsoft.Build.Utilities**: Utility classes for task authors +- **MSBuild CLI**: Command-line tool for invoking builds + +### Technology Stack +- .NET 10.0 +- C# 13 features (especially collection expressions) +- xUnit with Shouldly for testing +- Microsoft.DotNet.Arcade.Sdk for build infrastructure +- Multi-platform support (Windows, Linux, macOS) + +## General + +* Performance is the top priority - minimize allocations, avoid LINQ in hot paths, use efficient algorithms. +* Always use the latest C# features, currently C# 13, especially collection expressions (`[]` over `new Type[]`). +* Never change `global.json` unless explicitly asked to. +* Never change `NuGet.config` files unless explicitly asked to. +* Match the style of surrounding code when making edits, but modernize aggressively for substantial changes. + +## Code Review Instructions + +### Performance Considerations + +When reviewing pull requests: + +* **Flag any unnecessary allocations** in hot paths +* **Flag LINQ usage** in performance-critical code paths +* **Verify switch expressions** are used instead of if-else chains for dispatch logic +* **Check for proper use of `Span`** and `ReadOnlySpan` for string parsing +* **Ensure immutable collections** use the correct type (`ImmutableArray` and `FrozenDictionary` for read-heavy, `ImmutableList` for incremental building) + +### NuGet Feed Configuration + +When reviewing pull requests: + +* **Flag any changes to NuGet.config** that add external package sources without justification +* Package sources should use approved internal feeds when possible + +## Formatting + +* Apply code-formatting style defined in `.editorconfig`. +* Prefer file-scoped namespace declarations and single-line using directives. +* Insert a newline before the opening curly brace of any code block. +* Use pattern matching and switch expressions wherever possible. +* Use `nameof` instead of string literals when referring to member names. + +### Nullable Reference Types + +* **New files**: Always use nullable reference types (do NOT add `#nullable disable`) +* **Existing files with `#nullable disable`**: Match the existing style; don't add nullable annotations (`?`) to types +* **Existing files with nullable enabled**: Use proper nullable annotations +* **Shared files** (in `src/Shared/`): Be careful - may be compiled into multiple assemblies with different nullable contexts +* Always use `is null` or `is not null` instead of `== null` or `!= null` + +## Performance Best Practices + +### Switch Expressions for Dispatch Logic + +```csharp +// GOOD: Clean, O(1) dispatch +return (c0, c1) switch +{ + ('C', 'S') => Category.CSharp, + ('F', 'S') => Category.FSharp, + ('V', 'B') when value.Length >= 3 && value[2] == 'C' => Category.VB, + _ => Category.Other +}; + +// AVOID: Verbose if-else chains +if (c0 == 'C' && c1 == 'S') return Category.CSharp; +else if (c0 == 'F' && c1 == 'S') return Category.FSharp; +``` + +### Range Pattern Matching + +```csharp +// GOOD: Clear and efficient +return errorNumber switch +{ + >= 3001 and <= 3999 => Category.Tasks, + >= 4001 and <= 4099 => Category.General, + >= 4100 and <= 4199 => Category.Evaluation, + _ => Category.Other +}; +``` + +### String Handling + +* Use `StringComparer.OrdinalIgnoreCase` for case-insensitive HashSets/Dictionaries +* Use `char.ToUpperInvariant()` for single-character comparisons +* Use `ReadOnlySpan` and `Slice()` to avoid string allocations +* Use `int.TryParse(span, out var result)` on .NET Core+ for allocation-free parsing + +### Inlining Hot Paths + +```csharp +[MethodImpl(MethodImplOptions.AggressiveInlining)] +private static bool IsCompilerPrefix(string value) => ... +``` + +### Immutable Collections + +**Build once, read many times** (most common in MSBuild): +```csharp +ImmutableArray items = source.Select(x => x.Name).ToImmutableArray(); +FrozenDictionary lookup = pairs.ToFrozenDictionary(x => x.Key, x => x.Value); +``` + +**Build incrementally over time**: +```csharp +ImmutableList items = ...; // Use when adding items one by one +ImmutableDictionary lookup = ...; +``` + +### Conditional Compilation + +```csharp +#if NET + return int.TryParse(span, out errorNumber); +#else + return int.TryParse(span.ToString(), out errorNumber); +#endif +``` + +## Building + +**CRITICAL**: Never build with just `dotnet build MSBuild.slnx` or `dotnet build src/.../Project.csproj`. Always use the build scripts. + +### Build Commands - NEVER CANCEL + +| Platform | Command | Timeout | +|----------|---------|---------| +| Windows | `.\build.cmd -v quiet` | 300+ seconds (~2-3 minutes) | +| macOS/Linux | `./build.sh -v quiet` | 300+ seconds (~2-3 minutes) | + +### Bootstrap Environment Setup + +After building, activate the bootstrap environment before any `dotnet` commands: + +**Windows:** +```cmd +artifacts\msbuild-build-env.bat +``` + +**macOS/Linux:** +```bash +source artifacts/sdk-build-env.sh +``` + +### Verify Environment + +```bash +dotnet --version +# Should show something like: 10.0.100-preview.7.25372.107 +``` + +### Build Troubleshooting + +* If build fails with "Could not resolve SDK", run the bootstrap environment script +* Verify `dotnet --version` shows the preview/internal version +* Use repository sample projects for testing, not external projects +* Build artifacts go to `./artifacts/` directory + +## Testing + +* We use xUnit with Shouldly assertions +* Use Shouldly assertions for all assertions in modified code +* Do not emit "Act", "Arrange" or "Assert" comments +* Copy existing style in nearby files for test method names + +### Running Tests + +**Windows:** +```cmd +# Full test suite (~9 minutes, some failures expected) - NEVER CANCEL +.\build.cmd -test + +# Individual test project (recommended): +artifacts\msbuild-build-env.bat +dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj +``` + +**macOS/Linux:** +```bash +# Full test suite (~9 minutes, some failures expected) - NEVER CANCEL +./build.sh --test + +# Individual test project (recommended): +source artifacts/sdk-build-env.sh +dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj +``` + +**CRITICAL**: Some unit tests fail in the full test suite due to environment/CI dependencies. This is EXPECTED and normal in development environments. Run individual test projects for validation. + +### Test Verification + +* **Individual Test Project**: ~10-60 seconds per project +* **Full Test Suite**: ~9 minutes with some expected failures + +## Project Layout and Architecture + +### Directory Structure + +``` +src/ +├── Build/ # Core MSBuild engine (Microsoft.Build) +├── Build.UnitTests/ # Unit tests for core engine +├── MSBuild/ # MSBuild command-line tool +├── Framework/ # MSBuild Framework (Microsoft.Build.Framework) +├── Framework.UnitTests/ # Unit tests for framework +├── Tasks/ # Built-in MSBuild tasks (Microsoft.Build.Tasks) +├── Tasks.UnitTests/ # Unit tests for tasks +├── Utilities/ # MSBuild utilities (Microsoft.Build.Utilities) +├── Utilities.UnitTests/ # Unit tests for utilities +├── Shared/ # Shared code across assemblies +└── Samples/ # Sample projects and extensions + +artifacts/ +├── bin/ # Built binaries +│ └── bootstrap/ +│ └── core/ +│ └── MSBuild.dll # Built MSBuild executable +├── sdk-build-env.sh # Bootstrap script (Linux/macOS) +├── msbuild-build-env.bat # Bootstrap script (Windows) +└── packages/ # Built NuGet packages + +documentation/ +├── wiki/ # Developer documentation +├── specs/ # Technical specifications +└── *.md # Various documentation files +``` + +### Key Configuration Files + +* **`global.json`**: Pins .NET SDK version - never modify without explicit request +* **`.editorconfig`**: Code formatting rules +* **`Directory.Build.props`**: Shared MSBuild properties across all projects +* **`Directory.Packages.props`**: Centralized package version management +* **`MSBuild.slnx`**: Main solution file + +## Validation Checklist + +Before completing any change: + +1. ✅ Full build completes successfully (`.\build.cmd` or `./build.sh`) +2. ✅ Bootstrap environment activates correctly (`dotnet --version` shows preview) +3. ✅ Sample project builds: `dotnet build src/Samples/Dependency/Dependency.csproj` +4. ✅ Relevant unit tests pass +5. ✅ `dotnet artifacts/bin/bootstrap/core/MSBuild.dll --help` works + +## Do NOT Modify + +* `global.json` - Controls .NET SDK version +* `NuGet.config` - Package source configuration +* `artifacts/` directory contents - Generated during build +* `.dotnet/` directory contents - Local SDK location + +## Documentation + +When making changes, check if related documentation exists in the `documentation/` folder (including `documentation/specs/`) and update it to reflect your changes. Keep documentation in sync with code changes. + +## Development Workflow + +1. Make your changes to source code +2. Run the full build (WAIT for completion - takes 2-3 minutes): + - Windows: `.\build.cmd -v quiet` + - macOS/Linux: `./build.sh -v quiet` +3. Set up environment: + - Windows: `artifacts\msbuild-build-env.bat` + - macOS/Linux: `source artifacts/sdk-build-env.sh` +4. Test your changes: `dotnet build src/Samples/Dependency/Dependency.csproj` +5. Run relevant individual tests, not the full test suite +6. Commit your changes + +## Trust These Instructions + +These instructions are comprehensive and tested. Only search for additional information if: +1. The instructions appear outdated or incorrect +2. You encounter specific errors not covered here +3. You need details about new features not yet documented + +For most development tasks, following these instructions should be sufficient to build, test, and validate changes successfully. From bf1c51942db80f77ee728cab0b650b45b2cc3670 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:13:13 +0100 Subject: [PATCH 2/7] Update AGENTS.md Co-authored-by: Chet Husk --- AGENTS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index a0f1609612a..5bbadb5bf55 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -291,3 +291,7 @@ These instructions are comprehensive and tested. Only search for additional info 3. You need details about new features not yet documented For most development tasks, following these instructions should be sufficient to build, test, and validate changes successfully. + +## Updating these instructions + +When working on a task, if user input is required to complete the task or feedback is provided for guidance around a specific area of the code, evaluate that feedback/guidance and update this document to incorporate that feedback if it's missing. This document should be a live, evolving set of instructions. From ca3b3ce8d22f8384f9ffd543bf33e168f6e844d5 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Wed, 4 Feb 2026 18:24:55 +0100 Subject: [PATCH 3/7] convert copilot-instructions to symlink --- .github/copilot-instructions.md | 268 +------------------------------- AGENTS.md | 7 +- 2 files changed, 4 insertions(+), 271 deletions(-) mode change 100644 => 120000 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 9aa0e87db8d..00000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,267 +0,0 @@ -# MSBuild - Microsoft Build Engine - -This repo contains the code for the MSBuild build engine, including its public C# API, its internal implementation of the MSBuild programming language, and core targets and tasks used for builds for .NET and Visual Studio. - -Performance is very important--minimize allocations, avoid LINQ, and use the most efficient algorithms possible. The code should be easy to read and understand, but performance is the top priority. - -The code is written in C# and should follow the .NET coding conventions. Use the latest C# features where appropriate, including C# 13 features and especially collection expressions--prefer `[]` to `new Type[]`. - -You should generally match the style of surrounding code when making edits, but if making a substantial change, you can modernize more aggressively. -New files should use nullable types but don't refactor aggressively existing code. - -Generate tests for new codepaths, and add tests for any bugs you fix. Use the existing test framework, which is xUnit with Shouldly assertions. Use Shouldly assertions for all assertions in modified code, even if the file is predominantly using xUnit assertions. - -When making changes, check if related documentation exists in the `documentation/` folder (including `documentation/specs/`) and update it to reflect your changes. Keep documentation in sync with code changes, especially for telemetry, APIs, and architectural decisions. - -Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. - -## Performance Best Practices - -MSBuild is performance-critical infrastructure. Follow these patterns: - -### Switch Expressions for Dispatch Logic -Use tuple switch expressions for multi-condition dispatch instead of if-else chains: -```csharp -// GOOD: Clean, O(1) dispatch -return (c0, c1) switch -{ - ('C', 'S') => Category.CSharp, - ('F', 'S') => Category.FSharp, - ('V', 'B') when value.Length >= 3 && value[2] == 'C' => Category.VB, - _ => Category.Other -}; - -// AVOID: Verbose if-else chains -if (c0 == 'C' && c1 == 'S') return Category.CSharp; -else if (c0 == 'F' && c1 == 'S') return Category.FSharp; -// ... -``` - -### Range Pattern Matching -Use range patterns for numeric categorization: -```csharp -// GOOD: Clear and efficient -return errorNumber switch -{ - >= 3001 and <= 3999 => Category.Tasks, - >= 4001 and <= 4099 => Category.General, - >= 4100 and <= 4199 => Category.Evaluation, - _ => Category.Other -}; -``` - -### String Comparisons -- Use `StringComparer.OrdinalIgnoreCase` for case-insensitive HashSets/Dictionaries when the source data may vary in casing -- Use `char.ToUpperInvariant()` for single-character comparisons -- Use `ReadOnlySpan` and `Slice()` to avoid string allocations when parsing substrings -- Use `int.TryParse(span, out var result)` on .NET Core+ for allocation-free parsing - -### Inlining -Mark small, hot-path methods with `[MethodImpl(MethodImplOptions.AggressiveInlining)]`: -```csharp -[MethodImpl(MethodImplOptions.AggressiveInlining)] -private static bool IsCompilerPrefix(string value) => ... -``` - -### Conditional Compilation for Framework Differences -Use `#if NET` for APIs that differ between .NET Framework and .NET Core: -```csharp -#if NET - return int.TryParse(span, out errorNumber); -#else - return int.TryParse(span.ToString(), out errorNumber); -#endif -``` - -### Immutable Collections -Choose the right immutable collection type based on usage pattern: - -**Build once, read many times** (most common in MSBuild): -- Use `ImmutableArray` instead of `ImmutableList` - significantly faster for read access -- Use `FrozenDictionary` instead of `ImmutableDictionary` - optimized for read-heavy scenarios - -**Build incrementally over time** (adding items one by one): -- Use `ImmutableList` and `ImmutableDictionary` - designed for efficient `Add` operations returning new collections - -```csharp -// GOOD: Build once from LINQ, then read many times -ImmutableArray items = source.Select(x => x.Name).ToImmutableArray(); -FrozenDictionary lookup = pairs.ToFrozenDictionary(x => x.Key, x => x.Value); - -// AVOID for read-heavy scenarios: -ImmutableList items = source.Select(x => x.Name).ToImmutableList(); -ImmutableDictionary lookup = pairs.ToImmutableDictionary(x => x.Key, x => x.Value); -``` - -Note: `ImmutableArray` is a value type. Use `IsDefault` property to check for uninitialized arrays, or use nullable `ImmutableArray?` with `.Value` to unwrap. - -## Working Effectively - -#### Bootstrap and Build the Repository -NEVER build the repository with just `dotnet build MSBuild.slnx` or `dotnet build src/.../Project.csproj`. -Run these commands in sequence to set up a complete development environment: - -**Windows:** -```cmd -# Full build with restore - NEVER CANCEL: Takes ~2-3 minutes. Set timeout to 300+ seconds. -.\build.cmd -v quiet - -# Set up bootstrap environment for using built MSBuild -artifacts\msbuild-build-env.bat -``` - -**macOS/Linux:** -```bash -# Full build with restore - NEVER CANCEL: Takes ~2-3 minutes. Set timeout to 300+ seconds. -./build.sh -v quiet - -# Set up bootstrap environment for using built MSBuild -source artifacts/sdk-build-env.sh -``` - -### Test the Repository -**Windows:** -```cmd -# Run all tests - NEVER CANCEL: Takes ~9 minutes but some tests may fail (this is expected). Set timeout to 900+ seconds. -.\build.cmd -test - -# Run individual test project (recommended for validation): -artifacts\msbuild-build-env.bat -dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj -``` - -**macOS/Linux:** -```bash -# Run all tests - NEVER CANCEL: Takes ~9 minutes but some tests may fail (this is expected). Set timeout to 900+ seconds. -./build.sh --test - -# Run individual test project (recommended for validation): -source artifacts/sdk-build-env.sh -dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj -``` - -**CRITICAL**: Some unit tests fail in the full test suite due to environment/CI dependencies. This is EXPECTED and normal in development environments. Individual test projects typically work correctly. - -### Using the Built MSBuild - -After building, use the bootstrap environment to work with the locally built MSBuild: - -**Windows:** -```cmd -# Set up environment (run after every new shell session) -artifacts\msbuild-build-env.bat - -# Verify environment is working -dotnet --version -# Should show something like: 10.0.100-preview.7.25372.107 - -# Build a project using the built MSBuild -dotnet build src/Samples/Dependency/Dependency.csproj - -# Run MSBuild directly -dotnet artifacts/bin/bootstrap/core/MSBuild.dll --help -``` - -**macOS/Linux:** -```bash -# Set up environment (run after every new shell session) -source artifacts/sdk-build-env.sh - -# Verify environment is working -dotnet --version -# Should show something like: 10.0.100-preview.7.25372.107 - -# Build a project using the built MSBuild -dotnet build src/Samples/Dependency/Dependency.csproj - -# Run MSBuild directly -dotnet artifacts/bin/bootstrap/core/MSBuild.dll --help -``` - -## Validation - -### Always Test These Scenarios After Making Changes: -1. **Full build validation**: - - Windows: `.\build.cmd` must complete successfully - - macOS/Linux: `./build.sh` must complete successfully -2. **Bootstrap environment**: - - Windows: `artifacts\msbuild-build-env.bat && dotnet --version` shows correct preview version - - macOS/Linux: `source artifacts/sdk-build-env.sh && dotnet --version` shows correct preview version -3. **Sample build**: `dotnet build src/Samples/Dependency/Dependency.csproj` succeeds -4. **Individual tests**: Choose a relevant test project and run `dotnet test [project.csproj]` -5. **MSBuild help**: `dotnet artifacts/bin/bootstrap/core/MSBuild.dll --help` shows usage - -### Manual Testing Requirements: -- ALWAYS test the full build after code changes -- Verify the bootstrap environment works correctly with `dotnet --version` -- Test MSBuild executable can display help and basic functionality -- Build at least one sample project to verify core functionality - -## Common Tasks - -### Build Commands and Timing -**Windows:** -- **`.\build.cmd`** - Full build: ~2-3 minutes. NEVER CANCEL. Use 300+ second timeout. -- **`.\build.cmd -test`** - Run all tests: ~9 minutes with some failures expected. NEVER CANCEL. Use 900+ second timeout. -- **`.\build.cmd -clean`** - Clean build artifacts: ~30 seconds. - -**macOS/Linux:** -- **`./build.sh`** - Full build: ~2-3 minutes. NEVER CANCEL. Use 300+ second timeout. -- **`./build.sh -test`** - Run all tests: ~9 minutes with some failures expected. NEVER CANCEL. Use 900+ second timeout. -- **`./build.sh -clean`** - Clean build artifacts: ~30 seconds. - -### Development Workflow -1. Make your changes to source code -2. Run the full build to compile (WAIT for completion - takes 2-3 minutes): - - Windows: `.\build.cmd -v quiet` - - macOS/Linux: `./build.sh -v quiet` -3. Set up environment: - - Windows: `artifacts\msbuild-build-env.bat` - - macOS/Linux: `source artifacts/sdk-build-env.sh` -4. Test your changes: `dotnet build src/Samples/Dependency/Dependency.csproj` -5. Run relevant individual tests, not the full test suite -6. Commit your changes - -### Key Project Structure -``` -src/ -├── Build/ # Core MSBuild engine (Microsoft.Build) -├── MSBuild/ # MSBuild command-line tool -├── Framework/ # MSBuild Framework (Microsoft.Build.Framework) -├── Tasks/ # Built-in MSBuild tasks (Microsoft.Build.Tasks) -├── Utilities/ # MSBuild utilities (Microsoft.Build.Utilities) -├── Samples/ # Sample projects and extensions -└── [Component].UnitTests/ # Unit tests for each component - -artifacts/ -├── bin/ # Built binaries and tools -├── sdk-build-env.sh # Bootstrap environment script (Linux/macOS) -├── msbuild-build-env.bat # Bootstrap environment script (Windows) -└── packages/ # Built NuGet packages - -documentation/ -├── wiki/ # Developer documentation -├── specs/ # Technical specifications -└── *.md # Various documentation files -``` - -## Troubleshooting - -### Common Issues and Solutions - -**Build fails with "Could not resolve SDK":** -- Ensure you run `source artifacts/sdk-build-env.sh` after building -- Verify `dotnet --version` shows the preview/RC/internal version (e.g. 10.0.100-preview.7.25372.107) - -**Tests fail:** -- Run individual test projects instead: `dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj` - -**Certificate errors with external projects:** -- Use the repository's sample projects for testing instead of creating new external projects -- The bootstrap environment is designed for building the MSBuild repository itself - -### Files You Should NOT Modify -- `global.json` - Controls .NET SDK version -- `NuGet.config` - Package source configuration -- `artifacts/` directory contents - Generated during build -- `.dotnet/` directory contents - Local SDK location used to build diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 120000 index 00000000000..be77ac83a18 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1 @@ +../AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 5bbadb5bf55..be6ce4be76b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,8 +24,6 @@ Instructions for GitHub Copilot and other AI coding agents working with the MSBu * Performance is the top priority - minimize allocations, avoid LINQ in hot paths, use efficient algorithms. * Always use the latest C# features, currently C# 13, especially collection expressions (`[]` over `new Type[]`). -* Never change `global.json` unless explicitly asked to. -* Never change `NuGet.config` files unless explicitly asked to. * Match the style of surrounding code when making edits, but modernize aggressively for substantial changes. ## Code Review Instructions @@ -244,6 +242,7 @@ documentation/ ### Key Configuration Files * **`global.json`**: Pins .NET SDK version - never modify without explicit request +* **`NuGet.config`**: Package source configuration - never modify without explicit request * **`.editorconfig`**: Code formatting rules * **`Directory.Build.props`**: Shared MSBuild properties across all projects * **`Directory.Packages.props`**: Centralized package version management @@ -261,11 +260,11 @@ Before completing any change: ## Do NOT Modify -* `global.json` - Controls .NET SDK version -* `NuGet.config` - Package source configuration * `artifacts/` directory contents - Generated during build * `.dotnet/` directory contents - Local SDK location +See **Key Configuration Files** section for files that should not be modified without explicit request. + ## Documentation When making changes, check if related documentation exists in the `documentation/` folder (including `documentation/specs/`) and update it to reflect your changes. Keep documentation in sync with code changes. From cd877e1857a12545bfe2545bd321642f473c3fef Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 5 Feb 2026 13:23:57 +0100 Subject: [PATCH 4/7] fix the comments --- AGENTS.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index be6ce4be76b..33974729194 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ Instructions for GitHub Copilot and other AI coding agents working with the MSBu - **MSBuild CLI**: Command-line tool for invoking builds ### Technology Stack -- .NET 10.0 +- .NET 10.0 and .NET Framework 4.7.2 - C# 13 features (especially collection expressions) - xUnit with Shouldly for testing - Microsoft.DotNet.Arcade.Sdk for build infrastructure @@ -34,9 +34,8 @@ When reviewing pull requests: * **Flag any unnecessary allocations** in hot paths * **Flag LINQ usage** in performance-critical code paths -* **Verify switch expressions** are used instead of if-else chains for dispatch logic * **Check for proper use of `Span`** and `ReadOnlySpan` for string parsing -* **Ensure immutable collections** use the correct type (`ImmutableArray` and `FrozenDictionary` for read-heavy, `ImmutableList` for incremental building) +* **Ensure immutable collections** use the correct type (`ImmutableArray` and `FrozenDictionary` for read-heavy, `ImmutableList` for incremental building) ### NuGet Feed Configuration @@ -58,7 +57,6 @@ When reviewing pull requests: * **New files**: Always use nullable reference types (do NOT add `#nullable disable`) * **Existing files with `#nullable disable`**: Match the existing style; don't add nullable annotations (`?`) to types * **Existing files with nullable enabled**: Use proper nullable annotations -* **Shared files** (in `src/Shared/`): Be careful - may be compiled into multiple assemblies with different nullable contexts * Always use `is null` or `is not null` instead of `== null` or `!= null` ## Performance Best Practices @@ -66,7 +64,7 @@ When reviewing pull requests: ### Switch Expressions for Dispatch Logic ```csharp -// GOOD: Clean, O(1) dispatch +// GOOD: Clean, readable dispatch return (c0, c1) switch { ('C', 'S') => Category.CSharp, @@ -95,7 +93,7 @@ return errorNumber switch ### String Handling -* Use `StringComparer.OrdinalIgnoreCase` for case-insensitive HashSets/Dictionaries +* Use `MSBuildNameIgnoreCaseComparer` for case-insensitive comparisons of MSBuild names; use `StringComparer.OrdinalIgnoreCase` only for non-MSBuild string comparisons * Use `char.ToUpperInvariant()` for single-character comparisons * Use `ReadOnlySpan` and `Slice()` to avoid string allocations * Use `int.TryParse(span, out var result)` on .NET Core+ for allocation-free parsing @@ -181,7 +179,7 @@ dotnet --version **Windows:** ```cmd -# Full test suite (~9 minutes, some failures expected) - NEVER CANCEL +# Full test suite (~9 minutes) - NEVER CANCEL .\build.cmd -test # Individual test project (recommended): @@ -191,7 +189,7 @@ dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj **macOS/Linux:** ```bash -# Full test suite (~9 minutes, some failures expected) - NEVER CANCEL +# Full test suite (~9 minutes) - NEVER CANCEL ./build.sh --test # Individual test project (recommended): @@ -199,12 +197,10 @@ source artifacts/sdk-build-env.sh dotnet test src/Framework.UnitTests/Microsoft.Build.Framework.UnitTests.csproj ``` -**CRITICAL**: Some unit tests fail in the full test suite due to environment/CI dependencies. This is EXPECTED and normal in development environments. Run individual test projects for validation. - ### Test Verification * **Individual Test Project**: ~10-60 seconds per project -* **Full Test Suite**: ~9 minutes with some expected failures +* **Full Test Suite**: ~9 minutes ## Project Layout and Architecture From cea0dd9580b7f18f4b35eeb47cfee8498938e37f Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 5 Feb 2026 13:26:09 +0100 Subject: [PATCH 5/7] remove Switch Expressions for Dispatch Logic section --- AGENTS.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 33974729194..40d9261ae43 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -61,23 +61,6 @@ When reviewing pull requests: ## Performance Best Practices -### Switch Expressions for Dispatch Logic - -```csharp -// GOOD: Clean, readable dispatch -return (c0, c1) switch -{ - ('C', 'S') => Category.CSharp, - ('F', 'S') => Category.FSharp, - ('V', 'B') when value.Length >= 3 && value[2] == 'C' => Category.VB, - _ => Category.Other -}; - -// AVOID: Verbose if-else chains -if (c0 == 'C' && c1 == 'S') return Category.CSharp; -else if (c0 == 'F' && c1 == 'S') return Category.FSharp; -``` - ### Range Pattern Matching ```csharp From e1e4b4914ae5a9cc0779949e54dfe72ed90a14e5 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 5 Feb 2026 13:29:08 +0100 Subject: [PATCH 6/7] more cleanup --- AGENTS.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 40d9261ae43..7288808efb2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,6 @@ Instructions for GitHub Copilot and other AI coding agents working with the MSBu - .NET 10.0 and .NET Framework 4.7.2 - C# 13 features (especially collection expressions) - xUnit with Shouldly for testing -- Microsoft.DotNet.Arcade.Sdk for build infrastructure - Multi-platform support (Windows, Linux, macOS) ## General @@ -102,16 +101,6 @@ ImmutableList items = ...; // Use when adding items one by one ImmutableDictionary lookup = ...; ``` -### Conditional Compilation - -```csharp -#if NET - return int.TryParse(span, out errorNumber); -#else - return int.TryParse(span.ToString(), out errorNumber); -#endif -``` - ## Building **CRITICAL**: Never build with just `dotnet build MSBuild.slnx` or `dotnet build src/.../Project.csproj`. Always use the build scripts. From 4d13b19be5eaa5d1b8c3247aff4cabc8ed2a6bf5 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 5 Feb 2026 13:33:36 +0100 Subject: [PATCH 7/7] merge --- AGENTS.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 7288808efb2..4df58c6aaea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -237,6 +237,14 @@ See **Key Configuration Files** section for files that should not be modified wi When making changes, check if related documentation exists in the `documentation/` folder (including `documentation/specs/`) and update it to reflect your changes. Keep documentation in sync with code changes. +## Breaking Changes + +Because MSBuild is a critical part of the build process for a huge number of customers, we avoid breaking changes. Adding new errors or warnings, even when well-intentioned and pointing out things that are very likely to be wrong, is an unacceptable breaking change. Adding warnings is a breaking change because many production builds use `/WarnAsError`. + +The exception to this policy is in new, opt-in behavior. In new, opt-in functionality, liberally emit warnings and errors--they can always be removed later. + +When reviewing PRs, always consider whether the behavior change could be experienced as a break in existing builds and flag any new warnings or errors. + ## Development Workflow 1. Make your changes to source code