From bd06b7087fb620e2be1a0e49e38c8136c1a1e4b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 07:08:01 +0200 Subject: [PATCH 01/32] Bump actions/setup-dotnet from 4 to 5 (#3555) Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-frontends.yml | 2 +- .github/workflows/build-ilspy.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-frontends.yml b/.github/workflows/build-frontends.yml index 82f3173ea..8df68ff06 100644 --- a/.github/workflows/build-frontends.yml +++ b/.github/workflows/build-frontends.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' dotnet-quality: 'preview' diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index 8e6ab3d3c..0cbc2d4bc 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 persist-credentials: false - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' dotnet-quality: 'preview' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2e46a6c91..da921e613 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: with: languages: ${{ matrix.language }} - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: '10.0.x' dotnet-quality: 'preview' From b4d33af238d664b1c057b7a71941f905c1e631e3 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 9 Sep 2025 16:14:00 +0200 Subject: [PATCH 02/32] Update packages to .NET 10 RC1 --- .github/workflows/build-ilspy.yml | 2 +- BuildTools/pre-commit | 2 +- Directory.Packages.props | 34 +- ICSharpCode.BamlDecompiler/packages.lock.json | 16 +- ICSharpCode.ILSpyCmd/packages.lock.json | 344 +++++++++--------- ICSharpCode.ILSpyX/packages.lock.json | 26 +- .../CorTables/TypeDefTableTreeNode.cs | 6 +- 7 files changed, 215 insertions(+), 215 deletions(-) diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index 0cbc2d4bc..e9d1fe4cc 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -45,7 +45,7 @@ jobs: - name: Install dotnet-format env: - DOTNET_FORMAT_VERSION: 10.0.100-preview.7.25380.108 + DOTNET_FORMAT_VERSION: 10.0.100-rc.1.25451.107 DOTNET_FORMAT_SOURCE: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json run: dotnet tool install -g dotnet-format --version "${{env.DOTNET_FORMAT_VERSION}}" --add-source "${{env.DOTNET_FORMAT_SOURCE}}" diff --git a/BuildTools/pre-commit b/BuildTools/pre-commit index 7bf9aca1f..92afda16e 100644 --- a/BuildTools/pre-commit +++ b/BuildTools/pre-commit @@ -5,7 +5,7 @@ set -eu -DOTNET_FORMAT_VERSION=10.0.100-preview.7.25380.108 +DOTNET_FORMAT_VERSION=10.0.100-rc.1.25451.107 DOTNET_FORMAT_SOURCE="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" DOTNET_PATH="$LOCALAPPDATA/ICSharpCode/ILSpy/dotnet-format-$DOTNET_FORMAT_VERSION" if [ ! -d "$DOTNET_PATH" ]; then diff --git a/Directory.Packages.props b/Directory.Packages.props index 5766bdb92..00040abfc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,10 +6,10 @@ - + - + @@ -19,17 +19,17 @@ - - - - + + + + - - - + + + - - + + @@ -39,13 +39,13 @@ - - + + - - + + - + @@ -56,6 +56,6 @@ - + \ No newline at end of file diff --git a/ICSharpCode.BamlDecompiler/packages.lock.json b/ICSharpCode.BamlDecompiler/packages.lock.json index fca5e3de1..084b92690 100644 --- a/ICSharpCode.BamlDecompiler/packages.lock.json +++ b/ICSharpCode.BamlDecompiler/packages.lock.json @@ -4,15 +4,15 @@ "net10.0": { "Microsoft.Sbom.Targets": { "type": "Direct", - "requested": "[4.1.0, )", - "resolved": "4.1.0", - "contentHash": "GidfeSVHFtNwZSbD2wmwWiUiGkVdND8QR1z21WpFa+/47Mi3YiDkAzsWF02wXrMx2Xd8j3QSfKOUY1JtnF+7uw==" + "requested": "[4.1.2, )", + "resolved": "4.1.2", + "contentHash": "AmGCBhWtWu1d1PCit6WTdmpq48nPmmnJz9zZFBsxoCjYZjjZ0Gjm+wuAzHzVMF8VmTo/NeDGi2C73969QXiryw==" }, "TomsToolbox.Composition.Analyzer": { "type": "Direct", - "requested": "[2.22.1, )", - "resolved": "2.22.1", - "contentHash": "bKcte9zaz+xH1k6C1YIYpheQ9mPNRSmd0dHQIEIq31KxAKMTLfiAo80aROKDJMYJ7ZomlUjjSMo/QCIikMMWTg==" + "requested": "[2.22.2, )", + "resolved": "2.22.2", + "contentHash": "7gYo8ZR2eq3XkrilvUpLbTypeZy6IlD5FB8jah0YPhMOmDGhya4jJ3kfDMTTRt5m258Ou78P69mHMkG6DKZXsg==" }, "icsharpcode.decompiler": { "type": "Project", @@ -23,13 +23,13 @@ }, "System.Collections.Immutable": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", + "requested": "[10.0.0-rc.1.25451.107, )", "resolved": "9.0.0", "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==" }, "System.Reflection.Metadata": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", + "requested": "[10.0.0-rc.1.25451.107, )", "resolved": "9.0.0", "contentHash": "ANiqLu3DxW9kol/hMmTWbt3414t9ftdIuiIU7j80okq2YzAueo120M442xk1kDJWtmZTqWQn7wHDvMRipVOEOQ==" } diff --git a/ICSharpCode.ILSpyCmd/packages.lock.json b/ICSharpCode.ILSpyCmd/packages.lock.json index c33074443..85d1cb9a2 100644 --- a/ICSharpCode.ILSpyCmd/packages.lock.json +++ b/ICSharpCode.ILSpyCmd/packages.lock.json @@ -15,32 +15,32 @@ }, "Microsoft.Extensions.Hosting": { "type": "Direct", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "VcqnTGY8bMnFxZQb3cjcXnXy4x7dJgp85UlujErNh34xh4ZislQ2XhX7ak0gUnRh8c9ZTI3xj4groyqBl/DNHA==", - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Binder": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.CommandLine": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Json": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.UserSecrets": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.DependencyInjection": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Diagnostics": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Physical": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Hosting.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Console": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Debug": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.EventLog": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.EventSource": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "MSxUXg8ZrySaprKTWT/nPXHo1JW9TcLuTb0E3DtQ0DRK8KJKkYJhvvbLWKHUZ/vyvMcL4Msp0jbnZQ4ywTdWdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Binder": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.CommandLine": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Json": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.UserSecrets": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.DependencyInjection": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Diagnostics": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Physical": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Console": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Debug": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.EventLog": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.EventSource": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107" } }, "NuGet.Protocol": { @@ -54,240 +54,240 @@ }, "System.Security.Cryptography.Pkcs": { "type": "Direct", - "requested": "[9.0.8, )", - "resolved": "9.0.8", - "contentHash": "+mtc8dZnrP9N1HZICncBzLUrX4YBP+WvAWb817auAA5mKOJzHZShuGpCtQiekgV/7N0uS/x0LkdBAezBcSBwVA==" + "requested": "[9.0.9, )", + "resolved": "9.0.9", + "contentHash": "Y7/wY5lqrzJOu53yLFLPGaeKBcdWNw193udOFRB2joFDVpXLkmfPpfgks7dEIJYPIrW4k3onwR+4nQz6vIaaqA==" }, "TomsToolbox.Composition.Analyzer": { "type": "Direct", - "requested": "[2.22.1, )", - "resolved": "2.22.1", - "contentHash": "bKcte9zaz+xH1k6C1YIYpheQ9mPNRSmd0dHQIEIq31KxAKMTLfiAo80aROKDJMYJ7ZomlUjjSMo/QCIikMMWTg==" + "requested": "[2.22.2, )", + "resolved": "2.22.2", + "contentHash": "7gYo8ZR2eq3XkrilvUpLbTypeZy6IlD5FB8jah0YPhMOmDGhya4jJ3kfDMTTRt5m258Ou78P69mHMkG6DKZXsg==" }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "Tos2R09p02UbSg97w7QNr+dNTKuBtmsWKy4+awTnn2d34CXDpsKkAdDis6gLmhuCjz4c0HyB5S0l2ahaqu+u7A==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "NOCQeNLsBMq0rdmZAWMWMEepO+/4iV6zBO2iyOBAzwtR1kZCVjrm/p4Z2Vda7IycOLEJKkcXfjN+oeqXH8mcFw==", "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "BAcZtIevY+MgiTX9t9iuz8CoYmGPoL1QeAlhNav8EVJmNlhKR/H7nESjxJifejcCRuwQ+dcXlFtHo1xrCMaZWA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "leKQmXsApCae6Mp65B29INCh3IFEALvpvKNAmcNV1GcwgAxZaDFVS6WbOQegkYLvTAX2G3DT5KE0skI8jy1kig==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.CommandLine": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "wrRFfwx7avg204vRHD1C7//zo9axtSLqNydbPXVN6r1tpQUsTz2Mbd6QsYMo+zoNUSvFD7fPFZPsG8pkmbX50A==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "oIrzvbO70HUqC4rkzoc44Qt/sRr+RGECOHH1ju5iNDVfLLZS/GVNyKf9dqcrLhuqotmasIsqyjWktzVkJdYbWQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.EnvironmentVariables": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "bIh84M0Clp94aGE827+cw3Ld3E+LN68Goqk1oyHTAkOMftp3YbkGB/yEHGdydsNEi3kfiLw5lZdu3Nh1Agt9gg==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "uWgOErLi+EWXVFPFklgJ3NO4wgG6K5XxahCP248jktCOR4pgDymW8bLIIPZAyQXEX7tJ0qUoh/+SXudml56ecw==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.FileExtensions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "eGgKM6UgrXTTGNDkPsXE4gofRMK+LPv2PIzMRUOVFLB2iAjoVhSgTTDBiQgVSXZW279FCaoILD8wC7zz5+sZBA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "gZO0j5JQjHy+CoBO7XRz4m5DhB16FOJsZIMj328xA/xSHhU6qK0xC2iboeC11W4MDKTukfnaj+yCtAtfHTcHkA==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Physical": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Physical": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.UserSecrets": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "X6M5ARSre9pHhQcrdIoPGCrGe2Xh6iM4AYwJGXRrgG6+blFTc04Iau7tvnjOhCDaEFr2g2cxMJI1wiLlJFOECg==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "wHLjtFft+I8raeZ+ZEVMlWNlh67IIfbNKd+mdQ5D38crV9b7m3QgK3DwK2YAgYOGLgP44qrYweuoi6zSvUEklw==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Json": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Physical": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Json": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Physical": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "UVMEx1ZOOugXCNxXARPsmtu7B3RzYShFoeGvmO4wA1OmcW8cOSXr7QNTiCTp3uXNrx14daefmDX/BlsExlZyVg==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "LyE1mwZNT30J/6ygkZZm6QlDRaKpwQf5dHkREGAlJQr75kz1VGx0RI/cxa6kevnuYaLNE5UtgtGT2Amp+dFT1Q==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Diagnostics": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "hbUpAah1f1gSx7NT7GKnmnzdQiP6POB7Mo8HNGZQ5qdcsZm6c3e6toK92u4kMkgJ9Cp0mRgL2wIyDfT6ixS/qw==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "tuZIsk+xd+/jdBOhfjtJMnjnl6qNitUrx6WO7qUUCyJ5vMZiEaDW0XXdVWtvefUs08inp6fdYoL0+PBlHCtrAQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Diagnostics.Abstractions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "4KCRTDM1TUA1+zwUBefsM9vjCRzAjkhLOsITu5X/z8GxdwxvhVRQL3svELII4AwcWG2PUvAqWHIGnjmKlYJmIQ==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "rskaFEs+RNVX8AXFeC3QqjS9O5cMjYsyHLGt/3SV5IYXIJdIA+iy3W8/fVsJED0ydkssEkftewhiTCOqh1DM3w==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "lvXcu7o7ETZ0SRPTOMhMuzyABFSiTwQdye1ATqdQH4u0n46s0QtTMN8u8zrHdIDtU5zv8hv3PqnOmmQt6lMzEQ==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "/Fi7B/NuEG5XMc80bHXb33ZO8SykBMcwOhZFygmNQ0SvmOUFD41M4XEtF27kmII73p1C4U84LWidkMZyvELmBw==", "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "CCWJM/f0hEldsKdB+QXJpcyELI0VRHbIuWWejCk9pNQBTuPOJHX5Lxsn4Lt8d30DGosTfkAQWLpy/wh+TGT6xA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "EdAkxAb8BQO6GI6NijKj7SYj79j7OOQlRCVJfyjw+6YvVBepery5gAUieu05ig4o4CYlpvie4xzmYoHiCN/6dQ==", "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileSystemGlobbing": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.FileSystemGlobbing": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "HsDTy1yAhOyznpgtbaUpiHojeMDrmkwAI/iW6G9PksLfhJAFXT1PffKoWMG2+fS4rWo6yoaro2cmJH0RYBKJ0Q==" + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "EgPqaVLU+duTIlONHfipkTt0xtNZlHgta54QUj5nrXb7pY4rPMwgYExwxbjM9xGJ3lIMjp5H/zkKii55aZk9Sg==" }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "J6zRebs9tVxWat6q3Z8v1fknqYhUbyUVoZYiGqhu7g+ChVYeCdp/YL2qSvC/Ap/KThXu6+C+R40gdDPCjUq5EQ==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "lfe8ZALjb5z95IUadn/NBPdqvPG1XX7UbBuRbtPu9al6RwrbQnVq5Sq+tQ7PTPxNh5WABtcnFbNnuc9MpAWypQ==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "vktcXpKfaF3TEC5OoAv2ySdImeBErcbFwUduuFIGvKOdYGw1B1N8ZpG5GLxApMXFgygdMcAFrkotDWzOF1npUA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "XKPlZZoN7eZjtpaincJm60Il2k5tBxuOfeT3w6gXcTNL5dM1tOR80hzDQaBIikyxI3uBApKtTU1Vge7In3W8Kg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "qfx62EG7wvjym/GusNX+kzqPByIVYiXyqBYaObQlIch5YukiVd4ovUJHALYt11jpcxpv9nmjgmqahIluf2j5xA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "RwlHkxMbkgvKs5m0jfguF+a6nZH1qaJVC63cSAODNLMVyX22VumSWwDBgnzFTB3oUHfOnQgLmtEK1U/eEQRLLQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "nfivpgjltKnYWCT62WtNgaRyyTv92nRYkqJabEQIvmtlQrjuYNb/kiECy74+jd4t4AQPx3hlPn9hWiLGvIEHhg==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "Pv+5gS1QQJ3/RgfoQR9qFXbExFerQfcsWWYSkZSBmq0X6FmaM/HYHeb9epAfpWYagbBCM6QwSqltMG8uJZLMdg==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Binder": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Binder": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "VfOeXETfctJamiTwovg1SmyfEboi8klawzpE6hv45f8KPajn/PPTuYRCQjaQWiP0praYdAJWrV4TjvDF0+xxeg==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "0o2U5BuYJFt6c2XwOpfSEb5knaSgKwpYi1Jm7+CU1IlTFvyA5ddjLBmUm/dJmzWiWnoFvUJvsvPvLQYWCxGiDg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.Debug": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "R1XFfHifpXKXtIGDt/QrvwnqPEOMEMdDppBMVjb5UpI3RSBKriTWdKeaJIcc1gx6e56aVO2xOT3EtfnK6Xb3Ig==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "HMpGwPNYt7M5XVSFkc8Y76CzLXvrM7AnyFgyDGfynhYvmX4MH2eT3w7c6eOb390WQcsNGkTGgZnb6QlaEwm9QA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.EventLog": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "pa6ggb9nqfU+DPLI2NXRaUDmkrw3mvmXcnh4NQrgcvzNQPB1PW8HySNm+KvzX/nK/UmPtJEa3NbOhmpDBdrbMA==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "s2k2ihzSGm2lCGvc4Az3zJoijNPZ9xrT6U+ORj9T4rocLCSxe/21MKqxcjInJvVZgTn7HWpJomFw5qcJz+HXYg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108", - "System.Diagnostics.EventLog": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107", + "System.Diagnostics.EventLog": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Logging.EventSource": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "K0Qydvu3fnotw1kynMz6kDt8FX+VnKxOjX1lVFjKKkyHroHitpz8YUOuA+TlbXQFZQyv3bO7nDimKVkcvPFcVQ==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "kQtRLj0UHV44+CVxPXwIhK2emuxjym1zqH3pAbtONYU6B8QuvFjThW0vU+SElEIfFGM8L11F84CIOJQeLGVvGQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "kG3XdCpBiMSxPsAeMCy8YhHpe3sUlSoBGuZQfTcC/VaWKrvpQ5OrbhBCfb/SOPLzWexijSsDwtgjYenRvqE91Q==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "lM7V/A39nKSh7kdTqqh8yRCEvgw1P3X0odWd5o7A94j/Ln8xT+1kV60MTP/i78jaa4FNDhFfYE7yao5T84aQZg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Options.ConfigurationExtensions": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "z05jUKh7+6FTFE+Obdg6wEQqvdxNf+ty5YUZ9VjNyzYcoN9hZMbX7RucTifl4CZCJXadlv79C7ZCSmHIK4x0pw==", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "6G5VB30lHscf+GUb/e0ZNdN8/yeLzNHWDPfdk1zDVODIlDL3Lm0zcr/h0v9gatilVlKKzLno49ftwLqyhw0sbw==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Binder": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Options": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Binder": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Options": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "0oC37fX0irgi29vN8JQdvXn1jZI6upCIs8Q8J+loetDrWrB3fwYBqbUdz/mMS41G+kkjCSaGRfZM8dBiZqqMpw==" + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "BNCfqG7CvhUQp7Sj8Qcr+HVNXkwV/nQfD6uS1HXXY2oO//QNpi4Mqy6IGeaIPIZIoQxykhLgPoSOJqRPCJRh/Q==" }, "Newtonsoft.Json": { "type": "Transitive", @@ -340,8 +340,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "kKFLata6tLJ/1+jJTbsE9YZu/zeOGO+9ZeukQ3uni5flEjcPpjqGxtmqOx/IFUecMQjNGheNEVyC1KaMl+aZMg==" + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "rwQ/QDgOb3qLSOs8UbLBFigL8ewMCETOmrQwVbksRXLt3c/kizzljOdBf+KdXKCS3XmrKqMeOLOkZZM8WQDcTw==" }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", @@ -361,8 +361,8 @@ "ICSharpCode.Decompiler": "[8.0.0-noversion, )", "K4os.Compression.LZ4": "[1.3.8, )", "Mono.Cecil": "[0.11.6, )", - "System.Composition.AttributedModel": "[10.0.0-preview.7.25380.108, )", - "System.Reflection.Metadata": "[10.0.0-preview.7.25380.108, )", + "System.Composition.AttributedModel": "[10.0.0-rc.1.25451.107, )", + "System.Reflection.Metadata": "[10.0.0-rc.1.25451.107, )", "System.Runtime.CompilerServices.Unsafe": "[6.1.2, )" } }, @@ -383,31 +383,31 @@ }, "Microsoft.Extensions.Configuration": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "bqeb/og5BMVpJ0cAfVgHhyNPfQa/uF/t6MhoQ9Z0kAUuOvk+hCfnSKlx2CZUzrkrWN6zK/jRXZW8RsbIxtzexw==", + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "pyIiy0uo0i2pM1IPTHf9X/sy1lOxRjAPuj7TAHlt+prfEvurKOXVdTrK41Xmr4e6mScWdesoOVpIoAhgP/N5BQ==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Primitives": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Primitives": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.Configuration.Json": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "vMUtXxczM+wt2rZT3AtDHRG4m0Wzn4R+cTFSr4RDq3VPy1z+qeX+xa+a9Ft73R5ODy/T0N5F1fXxYN6h1fvh6w==", + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "vvKbTkuv/v4D/DQ65nKz4V55eN/JL23Mvm31GNvxvY9rpOsy4MtOu68+WE/fX62r0MVByGYULd1GLmQPAgJ3wQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-preview.7.25380.108", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-preview.7.25380.108" + "Microsoft.Extensions.Configuration": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-rc.1.25451.107", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.1.25451.107" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "0oSQ8o2O8eMxaInqR1GykEzzlerBTN3xQMsEtaWA4zbf1LmrqV7H9ctTTjK4oMeWMCTb9mfYoN9fsVWbAhkTXA==" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "Wm2HfC0GlWExQmJajq85FHM9iHEOm61Z1c2YLivbzI6R5eT+TTSyfk3RHUra4oBU+oj1XhOIQ5hLW6Kg2r85tg==" }, "Mono.Cecil": { "type": "CentralTransitive", @@ -417,21 +417,21 @@ }, "System.Collections.Immutable": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", + "requested": "[10.0.0-rc.1.25451.107, )", "resolved": "9.0.0", "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==" }, "System.Composition.AttributedModel": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "BgKfmK5BAjJPj3DvCh7Qv2v/91FQfY2HwYchSurW1JajkVNhpSCCciZgk5tNOr815yUUpcAG8gY/CUUdYYdXcw==" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "0zroRtuBzQdbwuCRklmRY9NXin4DYNVcZOkZ8zqgZFuKNb66GrxeWw3kfnymfyZ0Ib9J8J3kXlYfxKRXIzb+2g==" }, "System.Reflection.Metadata": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "8oQpCMmBOI24XT+xwG1dec/gOv+1uUqAasXYu2vq0NWpXsg/TYw563jD9wMSbQ/lIjnKJmPRvjLFyG8xaX9uww==" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "ixP5rSQVGhwbYomPUL7XDRQpoh6YVXXomjfJGn0WasADk+ykq9C4pPN3as8F2KktDQ434vGz55NWU+vfZSt2EQ==" }, "System.Runtime.CompilerServices.Unsafe": { "type": "CentralTransitive", diff --git a/ICSharpCode.ILSpyX/packages.lock.json b/ICSharpCode.ILSpyX/packages.lock.json index 33c23514d..73dfcd0a3 100644 --- a/ICSharpCode.ILSpyX/packages.lock.json +++ b/ICSharpCode.ILSpyX/packages.lock.json @@ -10,9 +10,9 @@ }, "Microsoft.Sbom.Targets": { "type": "Direct", - "requested": "[4.1.0, )", - "resolved": "4.1.0", - "contentHash": "GidfeSVHFtNwZSbD2wmwWiUiGkVdND8QR1z21WpFa+/47Mi3YiDkAzsWF02wXrMx2Xd8j3QSfKOUY1JtnF+7uw==" + "requested": "[4.1.2, )", + "resolved": "4.1.2", + "contentHash": "AmGCBhWtWu1d1PCit6WTdmpq48nPmmnJz9zZFBsxoCjYZjjZ0Gjm+wuAzHzVMF8VmTo/NeDGi2C73969QXiryw==" }, "Microsoft.SourceLink.GitHub": { "type": "Direct", @@ -32,15 +32,15 @@ }, "System.Composition.AttributedModel": { "type": "Direct", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "BgKfmK5BAjJPj3DvCh7Qv2v/91FQfY2HwYchSurW1JajkVNhpSCCciZgk5tNOr815yUUpcAG8gY/CUUdYYdXcw==" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "0zroRtuBzQdbwuCRklmRY9NXin4DYNVcZOkZ8zqgZFuKNb66GrxeWw3kfnymfyZ0Ib9J8J3kXlYfxKRXIzb+2g==" }, "System.Reflection.Metadata": { "type": "Direct", - "requested": "[10.0.0-preview.7.25380.108, )", - "resolved": "10.0.0-preview.7.25380.108", - "contentHash": "8oQpCMmBOI24XT+xwG1dec/gOv+1uUqAasXYu2vq0NWpXsg/TYw563jD9wMSbQ/lIjnKJmPRvjLFyG8xaX9uww==" + "requested": "[10.0.0-rc.1.25451.107, )", + "resolved": "10.0.0-rc.1.25451.107", + "contentHash": "ixP5rSQVGhwbYomPUL7XDRQpoh6YVXXomjfJGn0WasADk+ykq9C4pPN3as8F2KktDQ434vGz55NWU+vfZSt2EQ==" }, "System.Runtime.CompilerServices.Unsafe": { "type": "Direct", @@ -50,9 +50,9 @@ }, "TomsToolbox.Composition.Analyzer": { "type": "Direct", - "requested": "[2.22.1, )", - "resolved": "2.22.1", - "contentHash": "bKcte9zaz+xH1k6C1YIYpheQ9mPNRSmd0dHQIEIq31KxAKMTLfiAo80aROKDJMYJ7ZomlUjjSMo/QCIikMMWTg==" + "requested": "[2.22.2, )", + "resolved": "2.22.2", + "contentHash": "7gYo8ZR2eq3XkrilvUpLbTypeZy6IlD5FB8jah0YPhMOmDGhya4jJ3kfDMTTRt5m258Ou78P69mHMkG6DKZXsg==" }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", @@ -73,7 +73,7 @@ }, "System.Collections.Immutable": { "type": "CentralTransitive", - "requested": "[10.0.0-preview.7.25380.108, )", + "requested": "[10.0.0-rc.1.25451.107, )", "resolved": "9.0.0", "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==" } diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs index ce39bf989..9a472ca37 100644 --- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs @@ -125,10 +125,10 @@ namespace ICSharpCode.ILSpy.Metadata string fieldListTooltip; public string FieldListTooltip { get { - var field = typeDef.GetFields().FirstOrDefault(); - if (field.IsNil) + var @field = typeDef.GetFields().FirstOrDefault(); + if (@field.IsNil) return null; - return GenerateTooltip(ref fieldListTooltip, metadataFile, field); + return GenerateTooltip(ref fieldListTooltip, metadataFile, @field); } } From 732f285c41d4e9b010f4adcb648f6698d613886e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 9 Sep 2025 21:39:44 +0200 Subject: [PATCH 03/32] Rename KnownAttributes.RequiredAttribute to KnownAttributes.Required --- ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs | 6 +++--- .../TypeSystem/Implementation/KnownAttributes.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index ad66cc40b..2fdba305e 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1436,7 +1436,7 @@ namespace ICSharpCode.Decompiler.CSharp } if (settings.RequiredMembers) { - RemoveAttribute(typeDecl, KnownAttribute.RequiredAttribute); + RemoveAttribute(typeDecl, KnownAttribute.Required); } if (typeDecl.ClassType == ClassType.Enum) { @@ -2016,7 +2016,7 @@ namespace ICSharpCode.Decompiler.CSharp typeSystemAstBuilder.UseSpecialConstants = !(field.DeclaringType.Equals(field.ReturnType) || isMathPIOrE); var fieldDecl = typeSystemAstBuilder.ConvertEntity(field); SetNewModifier(fieldDecl); - if (settings.RequiredMembers && RemoveAttribute(fieldDecl, KnownAttribute.RequiredAttribute)) + if (settings.RequiredMembers && RemoveAttribute(fieldDecl, KnownAttribute.Required)) { fieldDecl.Modifiers |= Modifiers.Required; } @@ -2132,7 +2132,7 @@ namespace ICSharpCode.Decompiler.CSharp propertyDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual); propertyDecl.Modifiers |= Modifiers.Override; } - if (settings.RequiredMembers && RemoveAttribute(propertyDecl, KnownAttribute.RequiredAttribute)) + if (settings.RequiredMembers && RemoveAttribute(propertyDecl, KnownAttribute.Required)) { propertyDecl.Modifiers |= Modifiers.Required; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index 7b17c3b13..dab95f0f4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.TypeSystem PreserveBaseOverrides, // C# 11 attributes: - RequiredAttribute, + Required, // C# 12 attributes: InlineArray, From 17a533647bd5e657e5471a331e3a59fec22741b5 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 9 Sep 2025 21:41:25 +0200 Subject: [PATCH 04/32] Add C# 14 ExtensionMarkerAttribute --- .../TypeSystem/Implementation/KnownAttributes.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index dab95f0f4..065864daf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -116,11 +116,14 @@ namespace ICSharpCode.Decompiler.TypeSystem // C# 12 attributes: InlineArray, + + // C# 14 attributes: + ExtensionMarker, } public static class KnownAttributes { - internal const int Count = (int)KnownAttribute.InlineArray + 1; + internal const int Count = (int)KnownAttribute.ExtensionMarker + 1; static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{ default, @@ -193,6 +196,8 @@ namespace ICSharpCode.Decompiler.TypeSystem new TopLevelTypeName("System.Runtime.CompilerServices", "RequiredMemberAttribute"), // C# 12 attributes: new TopLevelTypeName("System.Runtime.CompilerServices", "InlineArrayAttribute"), + // C# 14 attributes: + new TopLevelTypeName("System.Runtime.CompilerServices", "ExtensionMarkerAttribute"), }; public static ref readonly TopLevelTypeName GetTypeName(this KnownAttribute attr) From d1dc7b258afb6b9d0edc053e471d916da19e6cdf Mon Sep 17 00:00:00 2001 From: Jeremy Pritts <49847914+ds5678@users.noreply.github.com> Date: Tue, 9 Sep 2025 23:18:17 -0700 Subject: [PATCH 05/32] Copy-propagate the stack slot for collection initializers (#3554) * Copy-propagate the stack slot for collection initializers * Use pattern matching --- .../ICSharpCode.Decompiler.Tests.csproj | 2 + .../ILPrettyTestRunner.cs | 6 + .../TestCases/ILPretty/Issue3552.cs | 66 ++++++ .../TestCases/ILPretty/Issue3552.il | 198 ++++++++++++++++++ ...ransformCollectionAndObjectInitializers.cs | 5 + 5 files changed, 277 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.il diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index c43c7db0d..971979b70 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -105,6 +105,7 @@ + @@ -150,6 +151,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs index 693592692..50fdeb3d9 100644 --- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs @@ -249,6 +249,12 @@ namespace ICSharpCode.Decompiler.Tests await Run(); } + [Test] + public async Task Issue3552() + { + await Run(); + } + [Test] public async Task Issue2260SwitchString() { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.cs new file mode 100644 index 000000000..10995337f --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty +{ + public static class Issue3552 + { + public static Issue3552_IntegerPair MakePair1(int x, int y) + { + Issue3552_IntegerPairBuilder issue3552_IntegerPairBuilder = new Issue3552_IntegerPairBuilder { x, y }; + return issue3552_IntegerPairBuilder.ToPair(); + } + public static Issue3552_IntegerPair MakePair2(int x, int y) + { + Issue3552_IntegerPairBuilder issue3552_IntegerPairBuilder = new Issue3552_IntegerPairBuilder { x, y }; + return issue3552_IntegerPairBuilder.ToPair(); + } + public static Issue3552_IntegerPair MakePair3(int x, int y) + { + Issue3552_IntegerPairBuilder issue3552_IntegerPairBuilder = new Issue3552_IntegerPairBuilder { x, y }; + return issue3552_IntegerPairBuilder.ToPair(); + } + } + public struct Issue3552_IntegerPair + { + public int X; + public int Y; + } + public struct Issue3552_IntegerPairBuilder : IEnumerable, IEnumerable + { + private int index; + private Issue3552_IntegerPair pair; + + public readonly Issue3552_IntegerPair ToPair() + { + return pair; + } + + public void Add(int value) + { + switch (index) + { + case 0: + pair.X = value; + break; + case 1: + pair.Y = value; + break; + default: + throw new IndexOutOfRangeException(); + } + index++; + } + + public IEnumerator GetEnumerator() + { + return null; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.il new file mode 100644 index 000000000..1bdce8e20 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3552.il @@ -0,0 +1,198 @@ +.class public auto ansi abstract sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552 + extends [System.Runtime]System.Object +{ + // Methods + .method public hidebysig static + valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair MakePair1 ( + int32 x, + int32 y + ) cil managed + { + // Method begins at RVA 0x2050 + // Header size: 12 + // Code size: 34 (0x22) + .maxstack 2 + .locals init ( + [0] valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + ) + + IL_0000: ldloca.s 0 + IL_0002: initobj ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + IL_0008: ldloca.s 0 + IL_000a: ldarg.0 + IL_000b: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_0010: ldloca.s 0 + IL_0012: ldarg.1 + IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_0015: ldloca.s 0 + IL_001c: call instance valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::ToPair() + IL_0021: ret + } // end of method Issue3552::MakePair1 + + .method public hidebysig static + valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair MakePair2 ( + int32 x, + int32 y + ) cil managed + { + // Method begins at RVA 0x2050 + // Header size: 12 + // Code size: 34 (0x22) + .maxstack 2 + .locals init ( + [0] valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + ) + + IL_0000: ldloca.s 0 + IL_0001: dup + IL_0002: initobj ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + IL_0008: dup + IL_000a: ldarg.0 + IL_000b: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_0012: ldarg.1 + IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_0015: ldloca.s 0 + IL_001c: call instance valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::ToPair() + IL_0021: ret + } // end of method Issue3552::MakePair2 + + .method public hidebysig static + valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair MakePair3 ( + int32 x, + int32 y + ) cil managed + { + // Method begins at RVA 0x2050 + // Header size: 12 + // Code size: 34 (0x22) + .maxstack 2 + .locals init ( + [0] valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + ) + + IL_0000: ldloca.s 0 + IL_0001: dup + IL_0002: initobj ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + IL_0008: dup + IL_000a: ldarg.0 + IL_000b: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_0010: dup + IL_0012: ldarg.1 + IL_0013: call instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::Add(int32) + IL_001c: call instance valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::ToPair() + IL_0021: ret + } // end of method Issue3552::MakePair3 + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552 + +.class public sequential ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair + extends [System.Runtime]System.ValueType +{ + // Fields + .field public int32 X + .field public int32 Y + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair + +.class public sequential ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder + extends [System.Runtime]System.ValueType + implements class [System.Runtime]System.Collections.Generic.IEnumerable`1, + [System.Runtime]System.Collections.IEnumerable +{ + // Fields + .field private int32 index + .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair pair + + // Methods + .method public hidebysig + instance valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ToPair () cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x207e + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::pair + IL_0006: ret + } // end of method Issue3552_IntegerPairBuilder::ToPair + + .method public hidebysig + instance void Add ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x2088 + // Header size: 12 + // Code size: 65 (0x41) + .maxstack 3 + .locals init ( + [0] int32 + ) + + IL_0000: ldarg.0 + IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::index + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0010 + + IL_000a: ldloc.0 + IL_000b: ldc.i4.1 + IL_000c: beq.s IL_001e + + IL_000e: br.s IL_002c + + IL_0010: ldarg.0 + IL_0011: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::pair + IL_0016: ldarg.1 + IL_0017: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair::X + IL_001c: br.s IL_0032 + + IL_001e: ldarg.0 + IL_001f: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::pair + IL_0024: ldarg.1 + IL_0025: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPair::Y + IL_002a: br.s IL_0032 + + IL_002c: newobj instance void [System.Runtime]System.IndexOutOfRangeException::.ctor() + IL_0031: throw + + IL_0032: ldarg.0 + IL_0033: ldarg.0 + IL_0034: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::index + IL_0039: ldc.i4.1 + IL_003a: add + IL_003b: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::index + IL_0040: ret + } // end of method Issue3552_IntegerPairBuilder::Add + + .method public final hidebysig newslot virtual + instance class [System.Runtime]System.Collections.Generic.IEnumerator`1 GetEnumerator () cil managed + { + // Method begins at RVA 0x20d5 + // Header size: 1 + // Code size: 2 (0x2) + .maxstack 8 + + IL_0000: ldnull + IL_0001: ret + } // end of method Issue3552_IntegerPairBuilder::GetEnumerator + + .method private final hidebysig newslot virtual + instance class [System.Runtime]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed + { + .override method instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() + // Method begins at RVA 0x20d8 + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance class [System.Runtime]System.Collections.Generic.IEnumerator`1 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder::GetEnumerator() + IL_0006: ret + } // end of method Issue3552_IntegerPairBuilder::System.Collections.IEnumerable.GetEnumerator + +} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3552_IntegerPairBuilder diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 7aa27687a..5fd87451d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -97,6 +97,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return; } + // Copy-propagate stack slot holding an 'ldloca' of the variable + if (pos < block.Instructions.Count && block.Instructions[pos + 1] is StLoc { Variable: { Kind: VariableKind.StackSlot, IsSingleDefinition: true }, Value: LdLoca ldLoca } stLocStack && ldLoca.Variable == v) + { + CopyPropagation.Propagate(stLocStack, context); + } int initializerItemsCount = 0; bool initializerContainsInitOnlyItems = false; possibleIndexVariables.Clear(); From 7f84d2416739c039ae6a46c59982731e6f5fc04d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 9 Sep 2025 21:42:29 +0200 Subject: [PATCH 06/32] Add support for new extension everything encoding. --- .../TypeSystem/ExtensionInfo.cs | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs b/ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs index 2339f150c..dfe82d774 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs @@ -18,6 +18,7 @@ #nullable enable +using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; @@ -37,11 +38,21 @@ namespace ICSharpCode.Decompiler.TypeSystem var metadata = module.MetadataFile.Metadata; foreach (var extGroup in extensionContainer.NestedTypes) + { + if (TryEncodingV1(extGroup)) + { + continue; + } + + TryEncodingV2(extGroup); + } + + bool TryEncodingV1(ITypeDefinition extGroup) { if (!(extGroup is { Kind: TypeKind.Class, IsSealed: true } && extGroup.Name.StartsWith("<>E__", System.StringComparison.Ordinal))) { - continue; + return false; } TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extGroup.MetadataToken); @@ -69,8 +80,53 @@ namespace ICSharpCode.Decompiler.TypeSystem } if (marker == null || hasMultipleMarkers) - continue; + return false; + + CollectImplementationMethods(extGroup, marker, extensionMethods); + return true; + } + + bool TryEncodingV2(ITypeDefinition extGroup) + { + if (!(extGroup is { Kind: TypeKind.Class, IsSealed: true } + && extGroup.Name.StartsWith("$", StringComparison.Ordinal))) + { + return false; + } + + var markerType = extGroup.NestedTypes.SingleOrDefault(t => t.Name.StartsWith("$", StringComparison.Ordinal) && t.IsStatic); + var marker = markerType?.Methods.SingleOrDefault(m => m.Name == "$" && m.IsStatic && m.Parameters.Count == 1); + + if (markerType == null || marker == null) + return false; + + TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extGroup.MetadataToken); + List extensionMethods = []; + + // For easier access to accessors we use SRM + foreach (var h in td.GetMethods()) + { + var method = module.GetDefinition(h); + + if (method.SymbolKind is SymbolKind.Constructor) + continue; + + var attribute = method.GetAttribute(KnownAttribute.ExtensionMarker); + if (attribute == null) + continue; + + if (attribute.FixedArguments[0].Value?.ToString() != markerType.Name) + continue; + + extensionMethods.Add(method); + } + + CollectImplementationMethods(extGroup, marker, extensionMethods); + return true; + } + void CollectImplementationMethods(ITypeDefinition extGroup, IMethod marker, List extensionMethods) + { foreach (var extension in extensionMethods) { int expectedTypeParameterCount = extension.TypeParameters.Count + extGroup.TypeParameterCount; @@ -119,7 +175,6 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } - } public ExtensionMemberInfo? InfoOfExtensionMember(IMethod method) From 1d964bce8ed6f56e1e27cf279cff4c4fca61e33a Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Thu, 11 Sep 2025 09:35:53 -0700 Subject: [PATCH 07/32] Fix regression in decompiling local functions with default parameters --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs | 14 ++++++++++++++ .../TestCases/Pretty/Issue3541.cs | 15 +++++++++++++++ .../IL/Transforms/LocalFunctionDecompiler.cs | 7 ++++++- .../TypeSystem/TypeSystemExtensions.cs | 4 ++++ 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 971979b70..d34cd96d3 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -154,6 +154,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index f34b96b5b..562beb8f2 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -133,6 +133,14 @@ namespace ICSharpCode.Decompiler.Tests CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, }; + static readonly CompilerOptions[] roslyn4OrNewerWithNet40Options = + { + CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, + CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40, + CompilerOptions.UseRoslynLatest, + CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest, + }; + static readonly CompilerOptions[] roslyn4OrNewerOptions = { CompilerOptions.UseRoslynLatest, @@ -664,6 +672,12 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions | CompilerOptions.CheckForOverflowUnderflow, configureDecompiler: settings => settings.CheckForOverflowUnderflow = true); } + [Test] + public async Task Issue3541([ValueSource(nameof(roslyn4OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs new file mode 100644 index 000000000..c1df03b60 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3541.cs @@ -0,0 +1,15 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal class Issue3541 + { + private void Test(string format) + { + TestLocal(); + + void TestLocal(int a = 0) + { + a.ToString(format); + } + } + } +} diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index a5d01d8f0..1d93b677a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -566,13 +566,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms } internal static bool IsClosureParameter(IParameter parameter, ITypeResolveContext context) + { + return IsClosureParameter(parameter, context.CurrentTypeDefinition); + } + + internal static bool IsClosureParameter(IParameter parameter, ITypeDefinition currentTypeDefinition) { if (parameter.Type is not ByReferenceType brt) return false; var type = brt.ElementType.GetDefinition(); return type != null && type.Kind == TypeKind.Struct - && TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type); + && TransformDisplayClassUsage.IsPotentialClosure(currentTypeDefinition, type); } LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove) diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 1a4b11501..b89e2d10b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; +using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -681,6 +682,9 @@ namespace ICSharpCode.Decompiler.TypeSystem if (otherParameter == parameter) break; + if (LocalFunctionDecompiler.IsClosureParameter(otherParameter, otherParameter.Owner.DeclaringTypeDefinition)) + continue; + if (DefaultValueAssignmentAllowedIndividual(otherParameter) || otherParameter.IsParams) continue; From 9b0e3a16052f0fa21a5560ee243901b7e8769b6c Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 20 Sep 2025 20:54:39 +0200 Subject: [PATCH 08/32] Fix folding of local functions, if "Fold all braces" is disabled. --- ICSharpCode.Decompiler/Output/TextTokenWriter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs index 4429a103b..b65dc95f4 100644 --- a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs @@ -22,12 +22,12 @@ using System.Linq; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; -using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler { @@ -255,7 +255,7 @@ namespace ICSharpCode.Decompiler } if (braceLevelWithinType >= 0 || nodeStack.Peek() is TypeDeclaration) braceLevelWithinType++; - if (nodeStack.OfType().Count() <= 1 || settings.FoldBraces) + if (nodeStack.PeekOrDefault() is TypeDeclaration or BlockStatement { Parent: EntityDeclaration or LocalFunctionDeclarationStatement or AnonymousMethodExpression or LambdaExpression } || settings.FoldBraces) { output.MarkFoldStart(defaultCollapsed: !settings.ExpandMemberDefinitions && braceLevelWithinType == 1, isDefinition: braceLevelWithinType == 1); } @@ -265,7 +265,7 @@ namespace ICSharpCode.Decompiler output.Write('}'); if (role != Roles.RBrace) break; - if (nodeStack.OfType().Count() <= 1 || settings.FoldBraces) + if (nodeStack.PeekOrDefault() is TypeDeclaration or BlockStatement { Parent: EntityDeclaration or LocalFunctionDeclarationStatement or AnonymousMethodExpression or LambdaExpression } || settings.FoldBraces) output.MarkFoldEnd(); if (braceLevelWithinType >= 0) braceLevelWithinType--; From 0e1478ffcec838890155ffc0bbd38439bfa81ced Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 21 Sep 2025 18:22:17 +0200 Subject: [PATCH 09/32] Fix #3564: extend TransformDisplayClassUsage.IsPotentialClosure to support sibling DisplayClasses calling each other. --- .../Transforms/TransformDisplayClassUsage.cs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index 103c77d79..7c0c7171f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -716,13 +716,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; } - while (potentialDisplayClass != decompiledTypeDefinition) + // Make sure that potentialDisplayCLass and decompiledTypeDefinition are part of the same type tree + // Either decompiledTypeDefinition is an ancestor type of potentialDisplayClass or both have + // at least one common ancestor. + var potentialDisplayClassAncestors = new HashSet(); + var potentialDisplayClassParent = potentialDisplayClass.DeclaringTypeDefinition; + while (potentialDisplayClassParent != null) { - potentialDisplayClass = potentialDisplayClass.DeclaringTypeDefinition; - if (potentialDisplayClass == null) - return false; + potentialDisplayClassAncestors.Add(potentialDisplayClassParent); + potentialDisplayClassParent = potentialDisplayClassParent.DeclaringTypeDefinition; } - return true; + + var decompiledTypeDefinitionOrAncestor = decompiledTypeDefinition; + + while (decompiledTypeDefinitionOrAncestor != null) + { + if (potentialDisplayClassAncestors.Contains(decompiledTypeDefinitionOrAncestor)) + return true; + decompiledTypeDefinitionOrAncestor = decompiledTypeDefinitionOrAncestor.DeclaringTypeDefinition; + } + return false; } readonly Stack currentFunctions = new Stack(); From a79a58715450c07b688e58795b02ce9f24a4f5aa Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 21 Sep 2025 18:26:15 +0200 Subject: [PATCH 10/32] Fix SaveToDisk default filename suggestion to use the text of the tree node instead. The ToString() implementation returns the tree node path, which always starts with the full path of the loaded assembly. So in my case the suggested file name was always "C" when the assembly was located on the C: drive. --- ILSpy/TextView/DecompilerTextView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index a4b39b8de..55c97088d 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -1091,7 +1091,7 @@ namespace ICSharpCode.ILSpy.TextView SaveFileDialog dlg = new SaveFileDialog(); dlg.DefaultExt = language.FileExtension; dlg.Filter = language.Name + "|*" + language.FileExtension + Properties.Resources.AllFiles; - dlg.FileName = WholeProjectDecompiler.CleanUpFileName(treeNodes.First().ToString(), language.FileExtension); + dlg.FileName = WholeProjectDecompiler.CleanUpFileName(treeNodes.First().Text.ToString(), language.FileExtension); if (dlg.ShowDialog() == true) { SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), dlg.FileName); From 61f82d0c2dd9b77a4b5d76767637e24eaa4ee73f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 21 Sep 2025 19:46:46 +0200 Subject: [PATCH 11/32] Fix #3563: Add support for ildasm /caverbal format --- .../Disassembler/ReflectionDisassembler.cs | 148 ++++++++++++++---- .../Metadata/MetadataExtensions.cs | 19 --- ILSpy/Languages/CSharpILMixedLanguage.cs | 3 +- ILSpy/Languages/ILLanguage.cs | 3 +- ILSpy/Options/DisplaySettings.cs | 8 + ILSpy/Options/DisplaySettingsPanel.xaml | 1 + ILSpy/Properties/Resources.Designer.cs | 11 +- ILSpy/Properties/Resources.resx | 3 + 8 files changed, 145 insertions(+), 51 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 16bb69a13..47230c2b6 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -74,6 +74,12 @@ namespace ICSharpCode.Decompiler.Disassembler public bool ExpandMemberDefinitions { get; set; } + /// + /// Gets or sets whether custom attribute blobs should be decoded or dumped as raw bytes. Default is . + /// Setting this value to (roughly) corresponds to the /CAVERBAL switch of ildasm. + /// + public bool DecodeCustomAttributeBlobs { get; set; } + public IAssemblyResolver AssemblyResolver { get; set; } public IEntityProcessor EntityProcessor { get; set; } @@ -476,7 +482,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - class SecurityDeclarationDecoder : ICustomAttributeTypeProvider<(PrimitiveTypeCode, string)> + class SecurityDeclarationDecoder : ICustomAttributeTypeProvider<(PrimitiveTypeCode Code, string Name)> { readonly ITextOutput output; readonly IAssemblyResolver resolver; @@ -506,12 +512,54 @@ namespace ICSharpCode.Decompiler.Disassembler public (PrimitiveTypeCode, string) GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) { - throw new NotImplementedException(); + string fullTypeName = handle.GetFullTypeName(reader).FullName; + if (handle.IsEnum(reader, out var typeCode)) + return (typeCode, "enum " + fullTypeName); + return (0, fullTypeName); } public (PrimitiveTypeCode, string) GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) { - throw new NotImplementedException(); + string fullTypeName = handle.GetFullTypeName(reader).FullName; + var containingModule = GetDeclaringModule(handle); + + string assemblyQualifiedTypeName = containingModule != null + ? fullTypeName + ", " + containingModule + : fullTypeName; + + PrimitiveTypeCode typeCode = 0; + var (targetModule, resolvedType) = ResolveType(assemblyQualifiedTypeName, module); + if (targetModule != null) + { + if (!resolvedType.IsEnum(targetModule.Metadata, out typeCode)) + { + typeCode = 0; + } + else + { + assemblyQualifiedTypeName = "enum " + assemblyQualifiedTypeName; + } + } + + return (typeCode, assemblyQualifiedTypeName); + + string GetDeclaringModule(TypeReferenceHandle handle) + { + var tr = reader.GetTypeReference(handle); + switch (tr.ResolutionScope.Kind) + { + case HandleKind.TypeReference: + return GetDeclaringModule((TypeReferenceHandle)tr.ResolutionScope); + case HandleKind.AssemblyReference: + var asmRef = reader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope); + return asmRef.TryGetFullAssemblyName(reader, out var assemblyName) ? assemblyName : null; + case HandleKind.ModuleReference: + var modRef = reader.GetModuleReference((ModuleReferenceHandle)tr.ResolutionScope); + return reader.GetString(modRef.Name); + default: + return null; + } + } } public (PrimitiveTypeCode, string) GetTypeFromSerializedName(string name) @@ -608,17 +656,6 @@ namespace ICSharpCode.Decompiler.Disassembler } } - PrimitiveTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module) - { - if (typeName.StartsWith("enum ", StringComparison.Ordinal)) - typeName = typeName.Substring(5); - var (containingModule, typeDefHandle) = ResolveType(typeName, module); - - if (typeDefHandle.IsNil || !typeDefHandle.IsEnum(containingModule.Metadata, out var typeCode)) - throw new EnumUnderlyingTypeResolveException(); - return typeCode; - } - MetadataFile mscorlib; bool TryResolveMscorlib(out MetadataFile mscorlib) @@ -704,7 +741,7 @@ namespace ICSharpCode.Decompiler.Disassembler } output.Write(argument.Type.Name ?? PrimitiveTypeCodeToString(argument.Type.Code)); - output.Write(" " + argument.Name + " = "); + output.Write(" " + DisassemblerHelpers.Escape(argument.Name) + " = "); WriteValue(output, argument.Type, argument.Value); output.WriteLine(); @@ -1824,12 +1861,62 @@ namespace ICSharpCode.Decompiler.Disassembler if (!attr.Value.IsNil) { output.Write(" = "); - WriteBlob(attr.Value, metadata); + if (DecodeCustomAttributeBlobs) + WriteDecodedCustomAttributeBlob(attr, module); + else + WriteBlob(attr.Value, metadata); } output.WriteLine(); } } + void WriteDecodedCustomAttributeBlob(CustomAttribute attr, MetadataFile module) + { + CustomAttributeValue<(PrimitiveTypeCode Code, string Name)> value; + try + { + var provider = new SecurityDeclarationDecoder(output, AssemblyResolver, module); + value = attr.DecodeValue(provider); + } + catch (BadImageFormatException) + { + output.Write("/* Could not decode attribute value */ "); + WriteBlob(attr.Value, module.Metadata); + return; + } + + output.Write("{"); + output.Indent(); + + foreach (var arg in value.FixedArguments) + { + output.WriteLine(); + WriteValue(output, arg.Type, arg.Value); + } + + foreach (var arg in value.NamedArguments) + { + output.WriteLine(); + switch (arg.Kind) + { + case CustomAttributeNamedArgumentKind.Field: + output.Write("field "); + break; + case CustomAttributeNamedArgumentKind.Property: + output.Write("property "); + break; + } + + output.Write(arg.Type.Name ?? PrimitiveTypeCodeToString(arg.Type.Code)); + output.Write(" " + DisassemblerHelpers.Escape(arg.Name) + " = "); + WriteValue(output, arg.Type, arg.Value); + } + + output.WriteLine(); + output.Unindent(); + output.Write("}"); + } + void WriteBlob(BlobHandle blob, MetadataReader metadata) { var reader = metadata.GetBlobReader(blob); @@ -1839,23 +1926,26 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteBlob(BlobReader reader) { output.Write("("); - output.Indent(); - - for (int i = 0; i < reader.Length; i++) + if (reader.Length > 0) { - if (i % 16 == 0 && i < reader.Length - 1) - { - output.WriteLine(); - } - else + output.Indent(); + + for (int i = 0; i < reader.Length; i++) { - output.Write(' '); + if (i % 16 == 0 && i < reader.Length - 1) + { + output.WriteLine(); + } + else + { + output.Write(' '); + } + output.Write(reader.ReadByte().ToString("x2")); } - output.Write(reader.ReadByte().ToString("x2")); - } - output.WriteLine(); - output.Unindent(); + output.WriteLine(); + output.Unindent(); + } output.Write(")"); } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index b16fe4e4f..52452be12 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -210,25 +210,6 @@ namespace ICSharpCode.Decompiler.Metadata return Disassembler.DisassemblerHelpers.Escape(name); } - [Obsolete("Use MetadataModule.GetDeclaringModule() instead")] - public static IModuleReference GetDeclaringModule(this TypeReferenceHandle handle, MetadataReader reader) - { - var tr = reader.GetTypeReference(handle); - switch (tr.ResolutionScope.Kind) - { - case HandleKind.TypeReference: - return ((TypeReferenceHandle)tr.ResolutionScope).GetDeclaringModule(reader); - case HandleKind.AssemblyReference: - var asmRef = reader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope); - return new DefaultAssemblyReference(reader.GetString(asmRef.Name)); - case HandleKind.ModuleReference: - var modRef = reader.GetModuleReference((ModuleReferenceHandle)tr.ResolutionScope); - return new DefaultAssemblyReference(reader.GetString(modRef.Name)); - default: - return DefaultAssemblyReference.CurrentAssembly; - } - } - internal static readonly TypeProvider minimalCorlibTypeProvider = new TypeProvider(new SimpleCompilation(MinimalCorlib.Instance)); diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index ca349bbed..da06515fc 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -60,7 +60,8 @@ namespace ICSharpCode.ILSpy ShowMetadataTokens = displaySettings.ShowMetadataTokens, ShowMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10, ShowRawRVAOffsetAndBytes = displaySettings.ShowRawOffsetsAndBytesBeforeInstruction, - ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions + ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions, + DecodeCustomAttributeBlobs = displaySettings.DecodeCustomAttributeBlobs }; } diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs index 384728e36..748328b7e 100644 --- a/ILSpy/Languages/ILLanguage.cs +++ b/ILSpy/Languages/ILLanguage.cs @@ -67,7 +67,8 @@ namespace ICSharpCode.ILSpy ShowMetadataTokens = displaySettings.ShowMetadataTokens, ShowMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10, ShowRawRVAOffsetAndBytes = displaySettings.ShowRawOffsetsAndBytesBeforeInstruction, - ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions + ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions, + DecodeCustomAttributeBlobs = displaySettings.DecodeCustomAttributeBlobs }; } diff --git a/ILSpy/Options/DisplaySettings.cs b/ILSpy/Options/DisplaySettings.cs index b77bf501e..95c9d02d1 100644 --- a/ILSpy/Options/DisplaySettings.cs +++ b/ILSpy/Options/DisplaySettings.cs @@ -156,6 +156,12 @@ namespace ICSharpCode.ILSpy.Options set => SetProperty(ref enableSmoothScrolling, value); } + private bool decodeCustomAttributeBlobs; + public bool DecodeCustomAttributeBlobs { + get => decodeCustomAttributeBlobs; + set => SetProperty(ref decodeCustomAttributeBlobs, value); + } + public XName SectionName => "DisplaySettings"; public void LoadFromXml(XElement section) @@ -181,6 +187,7 @@ namespace ICSharpCode.ILSpy.Options ShowRawOffsetsAndBytesBeforeInstruction = (bool?)section.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false; StyleWindowTitleBar = (bool?)section.Attribute("StyleWindowTitleBar") ?? false; EnableSmoothScrolling = (bool?)section.Attribute("EnableSmoothScrolling") ?? true; + DecodeCustomAttributeBlobs = (bool?)section.Attribute("DecodeCustomAttributeBlobs") ?? false; } public XElement SaveToXml() @@ -208,6 +215,7 @@ namespace ICSharpCode.ILSpy.Options section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", ShowRawOffsetsAndBytesBeforeInstruction); section.SetAttributeValue("StyleWindowTitleBar", StyleWindowTitleBar); section.SetAttributeValue("EnableSmoothScrolling", EnableSmoothScrolling); + section.SetAttributeValue("DecodeCustomAttributeBlobs", DecodeCustomAttributeBlobs); return section; } diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml b/ILSpy/Options/DisplaySettingsPanel.xaml index 0624bd444..58c7ae316 100644 --- a/ILSpy/Options/DisplaySettingsPanel.xaml +++ b/ILSpy/Options/DisplaySettingsPanel.xaml @@ -64,6 +64,7 @@ + diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index ad46f836b..3ddca0ae2 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -648,6 +648,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// Looks up a localized string similar to Decode custom attribute blobs. + /// + public static string DecodeCustomAttributeBlobs { + get { + return ResourceManager.GetString("DecodeCustomAttributeBlobs", resourceCulture); + } + } + /// /// Looks up a localized string similar to Decompilation complete in {0:F1} seconds.. /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index bb0d12dde..ee03a4325 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -234,6 +234,9 @@ Are you sure you want to continue? Debug this step + + Decode custom attribute blobs + Decompilation complete in {0:F1} seconds. From 52b753c800f8069f39e7faa6f1120ede12d9e628 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 2 Oct 2025 20:07:32 +0200 Subject: [PATCH 12/32] Switch StackPanel with DockPanel in search panel GridViewColumns to make TextBlock.TextTrimming have an effect. --- ILSpy/Search/SearchPane.xaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ILSpy/Search/SearchPane.xaml b/ILSpy/Search/SearchPane.xaml index f99e21bf6..298d7c508 100644 --- a/ILSpy/Search/SearchPane.xaml +++ b/ILSpy/Search/SearchPane.xaml @@ -58,30 +58,30 @@ - + - + - + - + - + - + From 808b6d36db669cca8d6775c58c555ca55447a8af Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 2 Oct 2025 20:37:42 +0200 Subject: [PATCH 13/32] Fix #3574: MMB shortcut to "Decompile to new tab" doesn't work in Search tab --- ILSpy/Search/SearchPane.xaml | 2 +- ILSpy/Search/SearchPane.xaml.cs | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/ILSpy/Search/SearchPane.xaml b/ILSpy/Search/SearchPane.xaml index 298d7c508..2abe76a16 100644 --- a/ILSpy/Search/SearchPane.xaml +++ b/ILSpy/Search/SearchPane.xaml @@ -48,7 +48,7 @@ - Date: Mon, 29 Sep 2025 00:24:11 -0700 Subject: [PATCH 14/32] Fix lower case type name conflicting with variable name --- .../ICSharpCode.Decompiler.Tests.csproj | 3 ++ .../PrettyTestRunner.cs | 18 ++++++++++ .../TestCases/Pretty/Issue3571_A.cs | 33 +++++++++++++++++ .../TestCases/Pretty/Issue3571_B.cs | 33 +++++++++++++++++ .../TestCases/Pretty/Issue3571_C.cs | 36 +++++++++++++++++++ .../TestCases/Pretty/QualifierTests.cs | 4 +-- .../CSharp/StatementBuilder.cs | 10 +++--- .../CSharp/Transforms/DeclareVariables.cs | 2 +- .../IL/Transforms/AssignVariableNames.cs | 34 ++++++++++++++---- 9 files changed, 159 insertions(+), 14 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index d34cd96d3..83475a278 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -155,6 +155,9 @@ + + + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 562beb8f2..81cca7639 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -678,6 +678,24 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions); } + [Test] + public async Task Issue3571_A([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + + [Test] + public async Task Issue3571_B([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + + [Test] + public async Task Issue3571_C([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs new file mode 100644 index 000000000..27a69d844 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.InteropServices; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal static class Issue3571_A + { + [StructLayout(LayoutKind.Sequential, Size = 1)] + public readonly struct fsResult + { + public static fsResult Success => default(fsResult); + public static fsResult Failure => default(fsResult); + public bool Succeeded => true; + public bool Failed => false; + public static fsResult operator +(fsResult a, fsResult b) + { + return default(fsResult); + } + } + + public static fsResult M() + { + fsResult success = fsResult.Success; + fsResult fsResult2 = success + fsResult.Success; + if (fsResult2.Succeeded) + { + return success; + } + Console.WriteLine("Failed"); + return fsResult2 + fsResult.Failure; + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs new file mode 100644 index 000000000..a5dd91f7f --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.InteropServices; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_B +{ + [StructLayout(LayoutKind.Sequential, Size = 1)] + public readonly struct fsResult + { + public static fsResult Success => default(fsResult); + public static fsResult Failure => default(fsResult); + public bool Succeeded => true; + public bool Failed => false; + public static fsResult operator +(fsResult a, fsResult b) + { + return default(fsResult); + } + } + + internal static class Issue3571_B + { + public static fsResult M() + { + fsResult success = fsResult.Success; + fsResult fsResult2 = success + fsResult.Success; + if (fsResult2.Succeeded) + { + return success; + } + Console.WriteLine("Failed"); + return fsResult2 + fsResult.Failure; + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs new file mode 100644 index 000000000..e8da53842 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs @@ -0,0 +1,36 @@ +using System; +using System.Runtime.InteropServices; +using ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_Helper; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal static class Issue3571_C + { + public static fsResult M() + { + fsResult success = fsResult.Success; + fsResult fsResult2 = success + fsResult.Success; + if (fsResult2.Succeeded) + { + return success; + } + Console.WriteLine("Failed"); + return fsResult2 + fsResult.Failure; + } + } +} +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_Helper +{ + [StructLayout(LayoutKind.Sequential, Size = 1)] + public readonly struct fsResult + { + public static fsResult Success => default(fsResult); + public static fsResult Failure => default(fsResult); + public bool Succeeded => true; + public bool Failed => false; + public static fsResult operator +(fsResult a, fsResult b) + { + return default(fsResult); + } + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs index a44292dd2..3c11e6517 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs @@ -308,9 +308,9 @@ namespace ICSharpCode.Decompiler.Tests.Pretty private void LocalConflictsWithTypeName() { - for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j++) { - QualifierTests.i.Test(); + i.Test(); } } #if CS70 diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index aa44a0474..3c7ff756b 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -551,7 +551,7 @@ namespace ICSharpCode.Decompiler.CSharp var.Kind = VariableKind.Local; var disposeVariable = currentFunction.RegisterVariable( VariableKind.Local, disposeType, - AssignVariableNames.GenerateVariableName(currentFunction, disposeType) + AssignVariableNames.GenerateVariableName(currentFunction, disposeType, decompileRun.UsingScope) ); Expression disposeInvocation = new InvocationExpression(new MemberReferenceExpression(exprBuilder.ConvertVariable(disposeVariable).Expression, disposeTypeMethodName)); if (inst.IsAsync) @@ -712,12 +712,12 @@ namespace ICSharpCode.Decompiler.CSharp if (foreachVariable.Type.Kind != TypeKind.Dynamic) foreachVariable.Type = type; foreachVariable.Kind = VariableKind.ForeachLocal; - foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation(), foreachVariable); + foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation(), decompileRun.UsingScope, foreachVariable); break; case RequiredGetCurrentTransformation.IntroduceNewVariable: foreachVariable = currentFunction.RegisterVariable( VariableKind.ForeachLocal, type, - AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation()) + AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation(), decompileRun.UsingScope) ); instToReplace.ReplaceWith(new LdLoc(foreachVariable)); body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace)); @@ -725,11 +725,11 @@ namespace ICSharpCode.Decompiler.CSharp case RequiredGetCurrentTransformation.IntroduceNewVariableAndLocalCopy: foreachVariable = currentFunction.RegisterVariable( VariableKind.ForeachLocal, type, - AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation()) + AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation(), decompileRun.UsingScope) ); var localCopyVariable = currentFunction.RegisterVariable( VariableKind.Local, type, - AssignVariableNames.GenerateVariableName(currentFunction, type) + AssignVariableNames.GenerateVariableName(currentFunction, type, decompileRun.UsingScope) ); instToReplace.Parent.ReplaceWith(new LdLoca(localCopyVariable)); body.Instructions.Insert(0, new StLoc(localCopyVariable, new LdLoc(foreachVariable))); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 2a339fc79..fd27a9fea 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -227,7 +227,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var v = function.RegisterVariable( VariableKind.StackSlot, type, - AssignVariableNames.GenerateVariableName(function, type, + AssignVariableNames.GenerateVariableName(function, type, context.DecompileRun.UsingScope, stmt.Expression.Annotations.OfType() .Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(), mustResolveConflicts: true) diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index 5b271f994..a787ea128 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -28,6 +28,7 @@ using Humanizer.Inflections; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; +using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; @@ -110,6 +111,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms currentLowerCaseTypeOrMemberNames.Add(name); AddExistingName(reservedVariableNames, name); } + foreach (var name in CollectAllLowerCaseTypeNames(context.UsingScope)) + { + currentLowerCaseTypeOrMemberNames.Add(name); + AddExistingName(reservedVariableNames, name); + } this.currentLowerCaseTypeOrMemberNames = currentLowerCaseTypeOrMemberNames.ToImmutableHashSet(); // handle implicit parameters of set or event accessors @@ -618,6 +624,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (IsLowerCase(item.Name)) yield return item.Name; } + var current = type; + while (current != null) + { + foreach (var nested in current.NestedTypes) + { + if (IsLowerCase(nested.Name)) + yield return nested.Name; + } + current = current.DeclaringTypeDefinition; + } + } + + static IEnumerable CollectAllLowerCaseTypeNames(UsingScope usingScope) + { + return usingScope.Usings.SelectMany(n => n.Types).Select(t => t.Name).Where(IsLowerCase); } static bool IsLowerCase(string name) @@ -870,7 +891,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } static Dictionary CollectReservedVariableNames(ILFunction function, - ILVariable existingVariable, bool mustResolveConflicts) + ILVariable existingVariable, bool mustResolveConflicts, UsingScope usingScope) { var reservedVariableNames = new Dictionary(); var rootFunction = function.Ancestors.OfType().Single(f => f.Parent == null); @@ -889,14 +910,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (mustResolveConflicts) { var memberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition) - .Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition)); + .Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition)) + .Concat(CollectAllLowerCaseTypeNames(usingScope)); foreach (var name in memberNames) AddExistingName(reservedVariableNames, name); } return reservedVariableNames; } - internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, + internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, UsingScope usingScope, ILVariable existingVariable = null, bool mustResolveConflicts = false) { if (function == null) @@ -905,7 +927,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { return existingVariable.Name; } - var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts, usingScope); string baseName = GetNameFromInstruction(valueContext); if (string.IsNullOrEmpty(baseName)) @@ -955,13 +977,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - internal static string GenerateVariableName(ILFunction function, IType type, + internal static string GenerateVariableName(ILFunction function, IType type, UsingScope usingScope, ILInstruction valueContext = null, ILVariable existingVariable = null, bool mustResolveConflicts = false) { if (function == null) throw new ArgumentNullException(nameof(function)); - var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts, usingScope); string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string proposedName = "obj"; From df9cc3dfbef8852c675791c868b3ce5ffe53b8cb Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Mon, 29 Sep 2025 01:45:00 -0700 Subject: [PATCH 15/32] Null forgiveness for UsingScope --- ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index a787ea128..326ffa96e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -638,7 +638,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms static IEnumerable CollectAllLowerCaseTypeNames(UsingScope usingScope) { - return usingScope.Usings.SelectMany(n => n.Types).Select(t => t.Name).Where(IsLowerCase); + return usingScope?.Usings.SelectMany(n => n.Types).Select(t => t.Name).Where(IsLowerCase) ?? []; } static bool IsLowerCase(string name) From 6fb6b63a2cdb5e9c0824578ca6a77762908dd637 Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Mon, 29 Sep 2025 03:47:11 -0700 Subject: [PATCH 16/32] Fix ugly test --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../TestCases/Ugly/NoLocalFunctions.Expected.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 83475a278..ae0949d9d 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -158,6 +158,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs index d26d6ed93..b69f21fed 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs @@ -51,12 +51,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly private static void SimpleCaptureWithRef() { - _003C_003Ec__DisplayClass2_0 _003C_003Ec__DisplayClass2_ = new _003C_003Ec__DisplayClass2_0(); - _003C_003Ec__DisplayClass2_.x = 1; #if OPT - new Handle(new Func(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0)); + _003C_003Ec__DisplayClass2_0 obj = new _003C_003Ec__DisplayClass2_0(); + obj.x = 1; + new Handle(new Func(obj._003CSimpleCaptureWithRef_003Eg__F_007C0)); #else - Handle handle = new Handle(new Func(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0)); + _003C_003Ec__DisplayClass2_0 _003C_003Ec__DisplayClass2_1 = new _003C_003Ec__DisplayClass2_0(); + _003C_003Ec__DisplayClass2_1.x = 1; + Handle handle = new Handle(new Func(_003C_003Ec__DisplayClass2_1._003CSimpleCaptureWithRef_003Eg__F_007C0)); #endif } From d793781eea8d253be044a367ca79edec2181189d Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Thu, 2 Oct 2025 11:50:34 -0700 Subject: [PATCH 17/32] Remove obsolete tests --- ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs | 6 ------ .../TestCases/Pretty/QualifierTests.cs | 8 -------- 2 files changed, 14 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs index 8b039f1f7..47c35dfca 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs @@ -43,12 +43,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty GetOut(out var _); } - public void DiscardedOutVsLambdaParameter() - { - GetOut(out var _); - MakeValue((@_ _) => 5); - } - public void ExplicitlyTypedDiscard() { GetOutOverloaded(out string _); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs index 3c11e6517..57d0dee5f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs @@ -305,14 +305,6 @@ namespace ICSharpCode.Decompiler.Tests.Pretty { System.Array.Sort(Array); } - - private void LocalConflictsWithTypeName() - { - for (int j = 0; j < 10; j++) - { - i.Test(); - } - } #if CS70 private void LocalConflictsWithLocalFunction() { From fafc4341338b15abfa3d8186fee31d77ddd13659 Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:09:59 -0700 Subject: [PATCH 18/32] Formatting --- .github/workflows/build-ilspy.yml | 6 +++--- .../TestCases/Pretty/Issue3571_C.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index e9d1fe4cc..f071a03e6 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -65,6 +65,9 @@ jobs: - name: Build run: msbuild ILSpy.sln /p:Configuration=${{ matrix.configuration }} /p:Platform=$env:BuildPlatform /m + - name: Format check + run: dotnet-format whitespace --verify-no-changes --verbosity detailed ILSpy.sln + - name: Execute unit tests run: dotnet test --solution ilspy.sln --configuration ${{ matrix.configuration }} --no-build --report-trx --results-directory test-results/${{ matrix.configuration }} @@ -81,9 +84,6 @@ jobs: with: paths: "test-results/${{ matrix.configuration }}/*.trx" folded: true - - - name: Format check - run: dotnet-format whitespace --verify-no-changes --verbosity detailed ILSpy.sln - name: Verify package contents if: matrix.configuration == 'debug' diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs index e8da53842..8f20467df 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; + using ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_Helper; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty From 7b03606402b8779872763595f8e11d3f12c0d98a Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 4 Oct 2025 18:44:10 +0200 Subject: [PATCH 19/32] Fix #3575: Uses of compiler-generated events getting swapped with non-generated events of same type --- .../TestCases/Pretty/PropertiesAndEvents.cs | 17 ++++++++++++++ .../PropertyAndEventBackingFieldLookup.cs | 23 ++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs index 367c53855..0206dade0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs @@ -192,6 +192,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public event EventHandler Issue3575_AutoEvent; + public event EventHandler Issue3575_NonAuto; + + public event EventHandler Issue3575_Auto { + add { + } + remove { + } + } + + public event EventHandler Issue3575_NonAutoEvent { + add { + } + remove { + } + } + public int Getter(StringBuilder b) { return b.Length; diff --git a/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs b/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs index 9c05bd549..1688cd488 100644 --- a/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs +++ b/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs @@ -37,6 +37,8 @@ namespace ICSharpCode.Decompiler.Metadata var nameToFieldMap = new MultiDictionary(); + HashSet eventNames = new(); + foreach (var tdh in metadata.TypeDefinitions) { var type = metadata.GetTypeDefinition(tdh); @@ -72,6 +74,16 @@ namespace ICSharpCode.Decompiler.Metadata } } + // first get all names of events defined, so that we can make sure we don't accidentally + // associate the wrong backing field with the event, in case there is an event called "Something" + // without a backing field (i.e., custom event) as well as an auto/field event called "SomethingEvent" + // declared in the same type. + foreach (var edh in type.GetEvents()) + { + var ev = metadata.GetEventDefinition(edh); + eventNames.Add(metadata.GetString(ev.Name)); + } + foreach (var edh in type.GetEvents()) { var ev = metadata.GetEventDefinition(edh); @@ -83,15 +95,20 @@ namespace ICSharpCode.Decompiler.Metadata eventLookup[fieldHandle] = edh; } } - else if (nameToFieldMap.TryGetValues($"{name}Event", out fieldHandles)) + else { - foreach (var fieldHandle in fieldHandles) + var nameWithSuffix = $"{name}Event"; + if (!eventNames.Contains(nameWithSuffix) && nameToFieldMap.TryGetValues(nameWithSuffix, out fieldHandles)) { - eventLookup[fieldHandle] = edh; + foreach (var fieldHandle in fieldHandles) + { + eventLookup[fieldHandle] = edh; + } } } } + eventNames.Clear(); nameToFieldMap.Clear(); } } From dc3ed43dd8d84091004947a5f1bb5f46ce0539e2 Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Sun, 5 Oct 2025 00:25:47 -0700 Subject: [PATCH 20/32] Do not create object initializers for tuples --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../PrettyTestRunner.cs | 6 +++ .../TestCases/Pretty/Issue3576.cs | 39 +++++++++++++++++++ ...ransformCollectionAndObjectInitializers.cs | 3 ++ 4 files changed, 49 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3576.cs diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index ae0949d9d..de9ba4ba4 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -158,6 +158,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 81cca7639..089c7d764 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -696,6 +696,12 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions); } + [Test] + public async Task Issue3576([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3576.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3576.cs new file mode 100644 index 000000000..bd81126fe --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3576.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal static class Issue3576 + { + public static Issue3576_Camera GetOrCreate(long key, int frameCount, Dictionary cache) + { + if (!cache.TryGetValue(key, out var value)) + { + Issue3576_GameObject issue3576_GameObject = new Issue3576_GameObject(); + value = (issue3576_GameObject.AddComponent(), frameCount); + value.Item1.Property = 1; + issue3576_GameObject.SetActive(value: false); + cache[key] = value; + } + else + { + value.Item2 = frameCount; + cache[key] = value; + } + return value.Item1; + } + } + internal sealed class Issue3576_Camera + { + public int Property { get; set; } + } + internal sealed class Issue3576_GameObject + { + public T AddComponent() + { + throw null; + } + public void SetActive(bool value) + { + } + } +} diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 5fd87451d..b3d90d935 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -69,6 +69,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms // anon = new { A = 5 } { 3,4,5 } is invalid syntax. if (newObjInst.Method.DeclaringType.ContainsAnonymousType()) return; + // Tuples cannot have initializers + if (TupleTransform.MatchTupleConstruction(newObjInst, out _)) + return; instType = newObjInst.Method.DeclaringType; break; case DefaultValue defaultVal: From b50f4e1d721af2dd5843ddca260ee80cf112b7d1 Mon Sep 17 00:00:00 2001 From: Jeremy Pritts <49847914+ds5678@users.noreply.github.com> Date: Sun, 5 Oct 2025 01:06:35 -0700 Subject: [PATCH 21/32] Enable detection of .NET version without TargetFrameworkAttribute (#3580) --- .../Metadata/DotNetCorePathFinderExtensions.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index 8e7fdde57..fd620116e 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -100,16 +100,24 @@ namespace ICSharpCode.Decompiler.Metadata // 4.2.0 => .NET Core 2.0 // 4.2.1 => .NET Core 2.1 / 3.0 // 4.2.2 => .NET Core 3.1 + // 5.0.0+ => .NET 5+ if (r.Version >= new Version(4, 2, 0)) { - version = "2.0"; - if (r.Version >= new Version(4, 2, 1)) + if (r.Version.Major >= 5) { - version = "3.0"; + version = r.Version.ToString(2); } - if (r.Version >= new Version(4, 2, 2)) + else if (r.Version.Major == 4 && r.Version.Minor == 2) { - version = "3.1"; + version = r.Version.Build switch { + <= 0 => "2.0", + 1 => "3.0", + _ => "3.1" + }; + } + else + { + version = "2.0"; } return $".NETCoreApp,Version=v{version}"; } From ed36ba1d8a11c1efda5c68b8a871c90ce502d5cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 06:49:42 +0200 Subject: [PATCH 22/32] Bump ossf/scorecard-action from 2.4.2 to 2.4.3 (#3583) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/v2.4.2...v2.4.3) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1d7b66276..a8859f6ba 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@v2.4.2 # https://github.com/marketplace/actions/ossf-scorecard-action + uses: ossf/scorecard-action@v2.4.3 # https://github.com/marketplace/actions/ossf-scorecard-action with: results_file: results.sarif results_format: sarif From d13835e2cccd2a19bc83177ebe3a9ac569d15105 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 1 Aug 2025 16:18:53 +0200 Subject: [PATCH 23/32] Add test for "params scoped Span'. --- .../TestCases/Pretty/ParamsCollections.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs index 862227f87..a3abfa188 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -15,6 +16,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { } public static void ParamsSpan(params Span values) + { + // note: implicitly "scoped", "params scoped Span values" is allowed + // but "scoped" is always redundant for params. + } + public static void ParamUnscopedSpan([UnscopedRef] params Span values) { } } From b403b7bb3de02bfcf37c6269b66bdd62f9f0f58e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 9 Oct 2025 08:24:49 +0200 Subject: [PATCH 24/32] Fix #3542: Invalid explicit cast for implicit conversion to generic struct with interface type constraint --- .../Semantics/ConversionTests.cs | 11 +++++++++++ .../TypeSystem/TypeSystemTestCase.cs | 13 +++++++++++++ .../CSharp/Resolver/CSharpConversions.cs | 19 ++++++++++++++++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs index a017f02b7..80ca2165b 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs @@ -529,6 +529,17 @@ namespace ICSharpCode.Decompiler.Tests.Semantics Assert.That(c.Method.FullName, Is.EqualTo("System.DateTimeOffset.op_Implicit")); Assert.That(ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime)), Is.EqualTo(C.None)); + + ITypeDefinition classImplementingIDisposable = compilation.FindType(typeof(ClassImplementingIDisposable)).GetDefinition(); + ITypeDefinition genericStructWithIDisposableConstraintAndImplicitConversion = compilation.FindType(typeof(GenericStructWithIDisposableConstraintAndImplicitConversion<>)).GetDefinition(); + IType genericStructIDisposableInstance = new ParameterizedType(genericStructWithIDisposableConstraintAndImplicitConversion, ImmutableArray.Create(compilation.FindType(typeof(IDisposable)))); + + // C => S + Conversion c2 = conversions.ImplicitConversion(classImplementingIDisposable, genericStructIDisposableInstance); + Assert.That(c2.IsImplicit && c2.IsUserDefined); + Assert.That(c2.Method.FullName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.GenericStructWithIDisposableConstraintAndImplicitConversion.op_Implicit")); + + Assert.That(conversions.ImplicitConversion(genericStructIDisposableInstance, classImplementingIDisposable), Is.EqualTo(C.None)); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs index 1e273e21e..3c32788a9 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs @@ -559,6 +559,19 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem } } + public struct GenericStructWithIDisposableConstraintAndImplicitConversion where T : IDisposable + { + public static implicit operator GenericStructWithIDisposableConstraintAndImplicitConversion(T s) + { + return default(GenericStructWithIDisposableConstraintAndImplicitConversion); + } + } + + public class ClassImplementingIDisposable : IDisposable + { + public void Dispose() { } + } + public class ClassWithAttributeOnTypeParameter<[Double(2)] T> { } [Guid("790C6E0B-9194-4cc9-9426-A48A63185696"), InterfaceType(ComInterfaceType.InterfaceIsDual)] diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs index 31890f398..056ef2d54 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs @@ -955,13 +955,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// bool IsEncompassedBy(IType a, IType b) { - return a.Kind != TypeKind.Interface && b.Kind != TypeKind.Interface && StandardImplicitConversion(a, b).IsValid; + return StandardImplicitConversion(a, b).IsValid; } bool IsEncompassingOrEncompassedBy(IType a, IType b) { - return a.Kind != TypeKind.Interface && b.Kind != TypeKind.Interface - && (StandardImplicitConversion(a, b).IsValid || StandardImplicitConversion(b, a).IsValid); + return (StandardImplicitConversion(a, b).IsValid || StandardImplicitConversion(b, a).IsValid); } IType FindMostEncompassedType(IEnumerable candidates) @@ -1027,6 +1026,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion UserDefinedImplicitConversion(ResolveResult fromResult, IType fromType, IType toType) { // C# 4.0 spec §6.4.4 User-defined implicit conversions + + // user-defined conversions are not supported with interfaces + if (fromType.Kind == TypeKind.Interface || toType.Kind == TypeKind.Interface) + { + return Conversion.None; + } + var operators = GetApplicableConversionOperators(fromResult, fromType, toType, false); if (operators.Count > 0) @@ -1069,6 +1075,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion UserDefinedExplicitConversion(ResolveResult fromResult, IType fromType, IType toType) { // C# 4.0 spec §6.4.5 User-defined explicit conversions + + // user-defined conversions are not supported with interfaces + if (fromType.Kind == TypeKind.Interface || toType.Kind == TypeKind.Interface) + { + return Conversion.None; + } + var operators = GetApplicableConversionOperators(fromResult, fromType, toType, true); if (operators.Count > 0) { From d6ab43d839759338cfa39aa5e3f687c7537a5e97 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 30 Aug 2025 09:09:07 +0200 Subject: [PATCH 25/32] Fix #3521: Add API to set an initially highlighted entity after navigation. --- ILSpy/Analyzers/AnalyzerEntityTreeNode.cs | 13 +++++- ILSpy/Analyzers/AnalyzerSearchTreeNode.cs | 22 +++++----- ILSpy/Analyzers/AnalyzerTreeViewModel.cs | 10 ++--- .../TreeNodes/AnalyzedAccessorTreeNode.cs | 4 +- .../TreeNodes/AnalyzedEventTreeNode.cs | 11 +++-- .../TreeNodes/AnalyzedFieldTreeNode.cs | 5 ++- .../TreeNodes/AnalyzedMethodTreeNode.cs | 5 ++- .../TreeNodes/AnalyzedModuleTreeNode.cs | 5 ++- .../TreeNodes/AnalyzedPropertyTreeNode.cs | 9 ++-- .../TreeNodes/AnalyzedTypeTreeNode.cs | 5 ++- ILSpy/AssemblyTree/AssemblyTreeModel.cs | 14 ++++-- ILSpy/TextView/AvalonEditTextOutput.cs | 7 +++ ILSpy/TextView/DecompilerTextView.cs | 43 +++++++++++-------- ILSpy/Util/MessageBus.cs | 4 +- ILSpy/Views/DebugSteps.xaml.cs | 2 +- 15 files changed, 104 insertions(+), 55 deletions(-) diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index eece5e01a..039230e85 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; +using System.Diagnostics; using System.Windows; using ICSharpCode.Decompiler.TypeSystem; @@ -25,6 +26,8 @@ using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX.TreeView; using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers { /// @@ -34,6 +37,8 @@ namespace ICSharpCode.ILSpy.Analyzers { public abstract IEntity Member { get; } + public IEntity? SourceMember { get; protected set; } + public override void ActivateItem(IPlatformRoutedEventArgs e) { e.Handled = true; @@ -43,10 +48,14 @@ namespace ICSharpCode.ILSpy.Analyzers return; } - MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(this.Member.ParentModule?.MetadataFile, this.Member.MetadataToken))); + var module = this.Member.ParentModule?.MetadataFile; + + Debug.Assert(module != null); + + MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(module, this.Member.MetadataToken), this.SourceMember)); } - public override object ToolTip => Member?.ParentModule?.MetadataFile?.FileName; + public override object? ToolTip => Member?.ParentModule?.MetadataFile?.FileName; public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs index 2cbb18c87..9af81a856 100644 --- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs @@ -76,29 +76,29 @@ namespace ICSharpCode.ILSpy.Analyzers } } - AnalyzerTreeNode SymbolTreeNodeFactory(ISymbol symbol) + AnalyzerTreeNode SymbolTreeNodeFactory(ISymbol resultSymbol) { - if (symbol == null) + if (resultSymbol == null) { - throw new ArgumentNullException(nameof(symbol)); + throw new ArgumentNullException(nameof(resultSymbol)); } - switch (symbol) + switch (resultSymbol) { case IModule module: - return new AnalyzedModuleTreeNode(module) { }; + return new AnalyzedModuleTreeNode(module, (IEntity)this.symbol); case ITypeDefinition td: - return new AnalyzedTypeTreeNode(td) { }; + return new AnalyzedTypeTreeNode(td, (IEntity)this.symbol); case IField fd: - return new AnalyzedFieldTreeNode(fd) { }; + return new AnalyzedFieldTreeNode(fd, (IEntity)this.symbol); case IMethod md: - return new AnalyzedMethodTreeNode(md) { }; + return new AnalyzedMethodTreeNode(md, (IEntity)this.symbol); case IProperty pd: - return new AnalyzedPropertyTreeNode(pd) { }; + return new AnalyzedPropertyTreeNode(pd, (IEntity)this.symbol); case IEvent ed: - return new AnalyzedEventTreeNode(ed) { }; + return new AnalyzedEventTreeNode(ed, (IEntity)this.symbol); default: - throw new ArgumentOutOfRangeException(nameof(symbol), $"Symbol {symbol.GetType().FullName} is not supported."); + throw new ArgumentOutOfRangeException(nameof(resultSymbol), $"Symbol {resultSymbol.GetType().FullName} is not supported."); } } diff --git a/ILSpy/Analyzers/AnalyzerTreeViewModel.cs b/ILSpy/Analyzers/AnalyzerTreeViewModel.cs index c008c0f74..30ef87c99 100644 --- a/ILSpy/Analyzers/AnalyzerTreeViewModel.cs +++ b/ILSpy/Analyzers/AnalyzerTreeViewModel.cs @@ -109,20 +109,20 @@ namespace ICSharpCode.ILSpy.Analyzers switch (entity) { case ITypeDefinition td: - AddOrSelect(new AnalyzedTypeTreeNode(td)); + AddOrSelect(new AnalyzedTypeTreeNode(td, null)); break; case IField fd: if (!fd.IsConst) - AddOrSelect(new AnalyzedFieldTreeNode(fd)); + AddOrSelect(new AnalyzedFieldTreeNode(fd, null)); break; case IMethod md: - AddOrSelect(new AnalyzedMethodTreeNode(md)); + AddOrSelect(new AnalyzedMethodTreeNode(md, null)); break; case IProperty pd: - AddOrSelect(new AnalyzedPropertyTreeNode(pd)); + AddOrSelect(new AnalyzedPropertyTreeNode(pd, null)); break; case IEvent ed: - AddOrSelect(new AnalyzedEventTreeNode(ed)); + AddOrSelect(new AnalyzedEventTreeNode(ed, null)); break; default: throw new ArgumentOutOfRangeException(nameof(entity), $@"Entity {entity.GetType().FullName} is not supported."); diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs index 64a65633b..08b44dabe 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs @@ -24,8 +24,8 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { readonly string name; - public AnalyzedAccessorTreeNode(IMethod analyzedMethod, string name) - : base(analyzedMethod) + public AnalyzedAccessorTreeNode(IMethod analyzedMethod, IEntity source, string name) + : base(analyzedMethod, source) { if (string.IsNullOrWhiteSpace(name)) { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs index dc8ec7714..3ef317edc 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs @@ -21,6 +21,8 @@ using System; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode @@ -28,11 +30,12 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes readonly IEvent analyzedEvent; readonly string prefix; - public AnalyzedEventTreeNode(IEvent analyzedEvent, string prefix = "") + public AnalyzedEventTreeNode(IEvent analyzedEvent, IEntity? source, string prefix = "") { this.analyzedEvent = analyzedEvent ?? throw new ArgumentNullException(nameof(analyzedEvent)); this.prefix = prefix; this.LazyLoading = true; + this.SourceMember = source; } public override IEntity Member => analyzedEvent; @@ -45,11 +48,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { if (analyzedEvent.CanAdd) - this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.AddAccessor, "add")); + this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.AddAccessor, this.SourceMember, "add")); if (analyzedEvent.CanRemove) - this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.RemoveAccessor, "remove")); + this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.RemoveAccessor, this.SourceMember, "remove")); if (TryFindBackingField(analyzedEvent, out var backingField)) - this.Children.Add(new AnalyzedFieldTreeNode(backingField)); + this.Children.Add(new AnalyzedFieldTreeNode(backingField, this.SourceMember)); foreach (var lazy in Analyzers) { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs index 89858ef8c..acfe6880b 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs @@ -21,15 +21,18 @@ using System; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { class AnalyzedFieldTreeNode : AnalyzerEntityTreeNode { readonly IField analyzedField; - public AnalyzedFieldTreeNode(IField analyzedField) + public AnalyzedFieldTreeNode(IField analyzedField, IEntity? source) { this.analyzedField = analyzedField ?? throw new ArgumentNullException(nameof(analyzedField)); + this.SourceMember = source; this.LazyLoading = true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs index 2186517bf..711ffd05c 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs @@ -21,6 +21,8 @@ using System; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { internal class AnalyzedMethodTreeNode : AnalyzerEntityTreeNode @@ -28,9 +30,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes readonly IMethod analyzedMethod; readonly string prefix; - public AnalyzedMethodTreeNode(IMethod analyzedMethod, string prefix = "") + public AnalyzedMethodTreeNode(IMethod analyzedMethod, IEntity? source, string prefix = "") { this.analyzedMethod = analyzedMethod ?? throw new ArgumentNullException(nameof(analyzedMethod)); + this.SourceMember = source; this.prefix = prefix; this.LazyLoading = true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs index 8a9030d0e..cde606d36 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs @@ -25,15 +25,18 @@ using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX.TreeView; using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { internal class AnalyzedModuleTreeNode : AnalyzerEntityTreeNode { readonly IModule analyzedModule; - public AnalyzedModuleTreeNode(IModule analyzedModule) + public AnalyzedModuleTreeNode(IModule analyzedModule, IEntity? source) { this.analyzedModule = analyzedModule ?? throw new ArgumentNullException(nameof(analyzedModule)); + this.SourceMember = source; this.LazyLoading = true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs index 537a166cb..c306caf82 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs @@ -21,6 +21,8 @@ using System; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { sealed class AnalyzedPropertyTreeNode : AnalyzerEntityTreeNode @@ -28,11 +30,12 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes readonly IProperty analyzedProperty; readonly string prefix; - public AnalyzedPropertyTreeNode(IProperty analyzedProperty, string prefix = "") + public AnalyzedPropertyTreeNode(IProperty analyzedProperty, IEntity? source, string prefix = "") { this.analyzedProperty = analyzedProperty ?? throw new ArgumentNullException(nameof(analyzedProperty)); this.prefix = prefix; this.LazyLoading = true; + this.SourceMember = source; } public override object Icon => PropertyTreeNode.GetIcon(analyzedProperty); @@ -43,9 +46,9 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { if (analyzedProperty.CanGet) - this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Getter, "get")); + this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Getter, this.SourceMember, "get")); if (analyzedProperty.CanSet) - this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Setter, "set")); + this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Setter, this.SourceMember, "set")); foreach (var lazy in Analyzers) { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs index e87fb9938..7ae84a094 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs @@ -21,15 +21,18 @@ using System; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +#nullable enable + namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { internal class AnalyzedTypeTreeNode : AnalyzerEntityTreeNode { readonly ITypeDefinition analyzedType; - public AnalyzedTypeTreeNode(ITypeDefinition analyzedType) + public AnalyzedTypeTreeNode(ITypeDefinition analyzedType, IEntity? source) { this.analyzedType = analyzedType ?? throw new ArgumentNullException(nameof(analyzedType)); + this.SourceMember = source; this.LazyLoading = true; } diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs index 43a5be4d9..0e9b98f30 100644 --- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs +++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs @@ -67,6 +67,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree private readonly NavigationHistory history = new(); private NavigationState? navigatingToState; + private object? sourceOfReference; private readonly SettingsService settingsService; private readonly LanguageService languageService; private readonly IExportProvider exportProvider; @@ -262,7 +263,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree found = true; if (SelectedItem == initialSelection) { - await JumpToReferenceAsync(mr); + await JumpToReferenceAsync(mr, null); } } } @@ -642,7 +643,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree private void JumpToReference(object? sender, NavigateToReferenceEventArgs e) { - JumpToReferenceAsync(e.Reference, e.InNewTabPage).HandleExceptions(); + JumpToReferenceAsync(e.Reference, e.Source, e.InNewTabPage).HandleExceptions(); IsActive = true; } @@ -653,8 +654,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree /// Returns a task that will signal completion when the decompilation of the jump target has finished. /// The task will be marked as canceled if the decompilation is canceled. /// - private Task JumpToReferenceAsync(object? reference, bool inNewTabPage = false) + private Task JumpToReferenceAsync(object? reference, object? source, bool inNewTabPage = false) { + this.sourceOfReference = source; var decompilationTask = Task.CompletedTask; switch (reference) @@ -804,6 +806,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree public void DecompileSelectedNodes(ViewState? newState = null) { + object? source = this.sourceOfReference; + this.sourceOfReference = null; var activeTabPage = DockWorkspace.ActiveTabPage; if (activeTabPage.FrozenContent) @@ -831,7 +835,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree var options = activeTabPage.CreateDecompilationOptions(); options.TextViewState = newState as DecompilerTextViewState; - activeTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, options)); + activeTabPage.ShowTextViewAsync(textView => { + return textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, source, options); + }); } public void RefreshDecompiledView() diff --git a/ILSpy/TextView/AvalonEditTextOutput.cs b/ILSpy/TextView/AvalonEditTextOutput.cs index d3d8efbba..6882b2c8b 100644 --- a/ILSpy/TextView/AvalonEditTextOutput.cs +++ b/ILSpy/TextView/AvalonEditTextOutput.cs @@ -312,6 +312,13 @@ namespace ICSharpCode.ILSpy.TextView references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true, IsDefinition = isDefinition }); } + internal object InitialHighlightReference = null; + + public void SetInitialHighlight(object reference) + { + this.InitialHighlightReference = reference; + } + public void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false, bool isDefinition = false) { WriteIndent(); diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 55c97088d..5ad397a07 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -802,6 +802,7 @@ namespace ICSharpCode.ILSpy.TextView currentAddress = textOutput.Address; currentTitle = textOutput.Title; expandMemberDefinitions = settingsService.DisplaySettings.ExpandMemberDefinitions; + SetLocalReferenceMarks(textOutput.InitialHighlightReference); } #endregion @@ -817,7 +818,7 @@ namespace ICSharpCode.ILSpy.TextView [Obsolete("Use DecompileAsync() instead")] public void Decompile(ILSpy.Language language, IEnumerable treeNodes, DecompilationOptions options) { - DecompileAsync(language, treeNodes, options).HandleExceptions(); + DecompileAsync(language, treeNodes, null, options).HandleExceptions(); } /// @@ -826,7 +827,7 @@ namespace ICSharpCode.ILSpy.TextView /// If any errors occur, the error message is displayed in the text view, and the task returned by this method completes successfully. /// If the operation is cancelled (by starting another decompilation action); the returned task is marked as cancelled. /// - public Task DecompileAsync(ILSpy.Language language, IEnumerable treeNodes, DecompilationOptions options) + public Task DecompileAsync(ILSpy.Language language, IEnumerable treeNodes, object? source, DecompilationOptions options) { // Some actions like loading an assembly list cause several selection changes in the tree view, // and each of those will start a decompilation action. @@ -834,7 +835,7 @@ namespace ICSharpCode.ILSpy.TextView bool isDecompilationScheduled = this.nextDecompilationRun != null; if (this.nextDecompilationRun != null) this.nextDecompilationRun.TaskCompletionSource.TrySetCanceled(); - this.nextDecompilationRun = new DecompilationContext(language, treeNodes.ToArray(), options); + this.nextDecompilationRun = new DecompilationContext(language, treeNodes.ToArray(), options, source); var task = this.nextDecompilationRun.TaskCompletionSource.Task; if (!isDecompilationScheduled) { @@ -857,12 +858,14 @@ namespace ICSharpCode.ILSpy.TextView public readonly ILSpyTreeNode[] TreeNodes; public readonly DecompilationOptions Options; public readonly TaskCompletionSource TaskCompletionSource = new TaskCompletionSource(); + public readonly object? Source; - public DecompilationContext(ILSpy.Language language, ILSpyTreeNode[] treeNodes, DecompilationOptions options) + public DecompilationContext(ILSpy.Language language, ILSpyTreeNode[] treeNodes, DecompilationOptions options, object? source = null) { this.Language = language; this.TreeNodes = treeNodes; this.Options = options; + this.Source = source; } } @@ -914,6 +917,7 @@ namespace ICSharpCode.ILSpy.TextView { AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); textOutput.LengthLimit = outputLengthLimit; + textOutput.SetInitialHighlight(context.Source); DecompileNodes(context, textOutput); textOutput.PrepareDocument(); tcs.SetResult(textOutput); @@ -994,19 +998,7 @@ namespace ICSharpCode.ILSpy.TextView if (referenceSegment.IsLocal) { ClearLocalReferenceMarks(); - if (references != null) - { - foreach (var r in references) - { - if (reference.Equals(r.Reference)) - { - - var mark = textMarkerService.Create(r.StartOffset, r.Length); - mark.BackgroundColor = (Color)(r.IsDefinition ? FindResource(ResourceKeys.TextMarkerDefinitionBackgroundColor) : FindResource(ResourceKeys.TextMarkerBackgroundColor)); - localReferenceMarks.Add(mark); - } - } - } + SetLocalReferenceMarks(reference); return; } if (definitionLookup != null) @@ -1027,6 +1019,23 @@ namespace ICSharpCode.ILSpy.TextView MessageBus.Send(this, new NavigateToReferenceEventArgs(reference, openInNewTab)); } + private void SetLocalReferenceMarks(object reference) + { + if (references == null || reference == null) + { + return; + } + foreach (var r in references) + { + if (reference.Equals(r.Reference)) + { + var mark = textMarkerService.Create(r.StartOffset, r.Length); + mark.BackgroundColor = (Color)(r.IsDefinition ? FindResource(ResourceKeys.TextMarkerDefinitionBackgroundColor) : FindResource(ResourceKeys.TextMarkerBackgroundColor)); + localReferenceMarks.Add(mark); + } + } + } + Point? mouseDownPos; void TextAreaMouseDown(object sender, MouseButtonEventArgs e) diff --git a/ILSpy/Util/MessageBus.cs b/ILSpy/Util/MessageBus.cs index 871205901..c6c24b362 100644 --- a/ILSpy/Util/MessageBus.cs +++ b/ILSpy/Util/MessageBus.cs @@ -79,10 +79,10 @@ namespace ICSharpCode.ILSpy.Util public class SettingsChangedEventArgs(PropertyChangedEventArgs e) : WrappedEventArgs(e); - public class NavigateToReferenceEventArgs(object reference, bool inNewTabPage = false) : EventArgs + public class NavigateToReferenceEventArgs(object reference, object? source = null, bool inNewTabPage = false) : EventArgs { public object Reference { get; } = reference; - + public object? Source { get; } = source; public bool InNewTabPage { get; } = inNewTabPage; } diff --git a/ILSpy/Views/DebugSteps.xaml.cs b/ILSpy/Views/DebugSteps.xaml.cs index da9940c3a..87bcd0859 100644 --- a/ILSpy/Views/DebugSteps.xaml.cs +++ b/ILSpy/Views/DebugSteps.xaml.cs @@ -140,7 +140,7 @@ namespace ICSharpCode.ILSpy } var state = dockWorkspace.ActiveTabPage.GetState(); - dockWorkspace.ActiveTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(assemblyTreeModel.CurrentLanguage, assemblyTreeModel.SelectedNodes, + dockWorkspace.ActiveTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(assemblyTreeModel.CurrentLanguage, assemblyTreeModel.SelectedNodes, null, new DecompilationOptions(assemblyTreeModel.CurrentLanguageVersion, settingsService.DecompilerSettings, settingsService.DisplaySettings) { StepLimit = step, IsDebug = isDebug, From 7e8b0500cee65edc9fcc4e771c5f1dde81654b35 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 4 Sep 2025 10:53:05 +0200 Subject: [PATCH 26/32] Add nullability annotations to some tree nodes. --- ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs | 38 +++++++++---------- ILSpy/Analyzers/AnalyzerEntityTreeNode.cs | 7 ++-- .../TreeNodes/AnalyzedEventTreeNode.cs | 7 +++- .../TreeNodes/AnalyzedFieldTreeNode.cs | 2 + .../TreeNodes/AnalyzedMethodTreeNode.cs | 4 +- .../TreeNodes/AnalyzedModuleTreeNode.cs | 11 +++--- .../TreeNodes/AnalyzedPropertyTreeNode.cs | 4 +- .../TreeNodes/AnalyzedTypeTreeNode.cs | 4 +- ILSpy/AssemblyTree/AssemblyTreeModel.cs | 2 +- ILSpy/TextView/DecompilerTextView.cs | 6 ++- 10 files changed, 50 insertions(+), 35 deletions(-) diff --git a/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs b/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs index 138ecd3c1..8a8619080 100644 --- a/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs +++ b/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs @@ -21,21 +21,21 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; -#nullable disable - using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; namespace ICSharpCode.ILSpyX.TreeView { public partial class SharpTreeNode : INotifyPropertyChanged { + [AllowNull] protected static ITreeNodeImagesProvider ImagesProvider { get; private set; } public static void SetImagesProvider(ITreeNodeImagesProvider provider) => ImagesProvider = provider; - SharpTreeNodeCollection modelChildren; - internal SharpTreeNode modelParent; + SharpTreeNodeCollection? modelChildren; + internal SharpTreeNode? modelParent; bool isVisible = true; void UpdateIsVisible(bool parentIsVisible, bool updateFlattener) @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpyX.TreeView node = node.listParent; } // Remember the removed nodes: - List removedNodes = null; + List? removedNodes = null; if (updateFlattener && !newIsVisible) { removedNodes = VisibleDescendantsAndSelf().ToList(); @@ -118,19 +118,19 @@ namespace ICSharpCode.ILSpyX.TreeView } } - public SharpTreeNode Parent { + public SharpTreeNode? Parent { get { return modelParent; } } - public virtual object Text { + public virtual object? Text { get { return null; } } - public virtual object Icon { + public virtual object? Icon { get { return null; } } - public virtual object ToolTip { + public virtual object? ToolTip { get { return null; } } @@ -199,7 +199,7 @@ namespace ICSharpCode.ILSpyX.TreeView while (removeEnd.modelChildren != null && removeEnd.modelChildren.Count > 0) removeEnd = removeEnd.modelChildren.Last(); - List removedNodes = null; + List? removedNodes = null; int visibleIndexOfRemoval = 0; if (node.isVisible) { @@ -221,11 +221,11 @@ namespace ICSharpCode.ILSpyX.TreeView } if (e.NewItems != null) { - SharpTreeNode insertionPos; + SharpTreeNode? insertionPos; if (e.NewStartingIndex == 0) insertionPos = null; else - insertionPos = modelChildren[e.NewStartingIndex - 1]; + insertionPos = modelChildren?[e.NewStartingIndex - 1]; foreach (SharpTreeNode node in e.NewItems) { @@ -260,7 +260,7 @@ namespace ICSharpCode.ILSpyX.TreeView #region Expanding / LazyLoading - public virtual object ExpandedIcon { + public virtual object? ExpandedIcon { get { return Icon; } } @@ -371,13 +371,13 @@ namespace ICSharpCode.ILSpyX.TreeView public IEnumerable Ancestors() { - for (SharpTreeNode n = this.Parent; n != null; n = n.Parent) + for (SharpTreeNode? n = this.Parent; n != null; n = n.Parent) yield return n; } public IEnumerable AncestorsAndSelf() { - for (SharpTreeNode n = this; n != null; n = n.Parent) + for (SharpTreeNode? n = this; n != null; n = n.Parent) yield return n; } @@ -402,7 +402,7 @@ namespace ICSharpCode.ILSpyX.TreeView } } - public virtual string LoadEditText() + public virtual string? LoadEditText() { return null; } @@ -699,7 +699,7 @@ namespace ICSharpCode.ILSpyX.TreeView #region INotifyPropertyChanged Members - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; public void RaisePropertyChanged(string name) { @@ -725,10 +725,10 @@ namespace ICSharpCode.ILSpyX.TreeView { } - public override string ToString() + public override string? ToString() { // used for keyboard navigation - object text = this.Text; + object? text = this.Text; return text != null ? text.ToString() : string.Empty; } } diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index 039230e85..c86dc1e80 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy.Analyzers /// public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode { - public abstract IEntity Member { get; } + public abstract IEntity? Member { get; } public IEntity? SourceMember { get; protected set; } @@ -65,13 +65,12 @@ namespace ICSharpCode.ILSpy.Analyzers } foreach (LoadedAssembly asm in removedAssemblies) { - if (this.Member.ParentModule.MetadataFile == asm.GetMetadataFileOrNull()) + if (this.Member.ParentModule!.MetadataFile == asm.GetMetadataFileOrNull()) return false; // remove this node } this.Children.RemoveAll( delegate (SharpTreeNode n) { - AnalyzerTreeNode an = n as AnalyzerTreeNode; - return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); + return n is not AnalyzerTreeNode an || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); }); return true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs index 3ef317edc..a197ed0a2 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs @@ -17,6 +17,8 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -57,6 +59,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedEvent)) { this.Children.Add(new AnalyzerSearchTreeNode(analyzedEvent, analyzer, lazy.Metadata?.Header)); @@ -64,10 +67,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes } } - bool TryFindBackingField(IEvent analyzedEvent, out IField backingField) + bool TryFindBackingField(IEvent analyzedEvent, [NotNullWhen(true)] out IField? backingField) { backingField = null; - foreach (var field in analyzedEvent.DeclaringTypeDefinition.GetFields(options: GetMemberOptions.IgnoreInheritedMembers)) + foreach (var field in analyzedEvent.DeclaringTypeDefinition?.GetFields(options: GetMemberOptions.IgnoreInheritedMembers) ?? []) { if (field.Name == analyzedEvent.Name && field.Accessibility == Decompiler.TypeSystem.Accessibility.Private) { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs index acfe6880b..48831a67c 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -45,6 +46,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedField)) { this.Children.Add(new AnalyzerSearchTreeNode(analyzedField, analyzer, lazy.Metadata?.Header)); diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs index 711ffd05c..421c9bf2d 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -47,9 +48,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedMethod)) { - this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer, lazy.Metadata.Header)); + this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer, lazy.Metadata!.Header)); } } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs index cde606d36..7695b625f 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Windows; using ICSharpCode.Decompiler.TypeSystem; @@ -44,16 +45,17 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes public override object Text => analyzedModule.AssemblyName; - public override object ToolTip => analyzedModule.MetadataFile?.FileName; + public override object? ToolTip => analyzedModule.MetadataFile?.FileName; protected override void LoadChildren() { foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedModule)) { - this.Children.Add(new AnalyzerSearchTreeNode(analyzedModule, analyzer, lazy.Metadata.Header)); + this.Children.Add(new AnalyzerSearchTreeNode(analyzedModule, analyzer, lazy.Metadata!.Header)); } } } @@ -69,7 +71,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes MessageBus.Send(this, new NavigateToReferenceEventArgs(analyzedModule.MetadataFile)); } - public override IEntity Member => null; + public override IEntity? Member => null; public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { @@ -84,8 +86,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes } this.Children.RemoveAll( delegate (SharpTreeNode n) { - AnalyzerTreeNode an = n as AnalyzerTreeNode; - return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); + return n is not AnalyzerTreeNode an || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); }); return true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs index c306caf82..4de437182 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -53,9 +54,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedProperty)) { - this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer, lazy.Metadata.Header)); + this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer, lazy.Metadata!.Header)); } } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs index 7ae84a094..c4cd300ce 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -45,9 +46,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes foreach (var lazy in Analyzers) { var analyzer = lazy.Value; + Debug.Assert(analyzer != null); if (analyzer.Show(analyzedType)) { - this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer, lazy.Metadata.Header)); + this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer, lazy.Metadata!.Header)); } } } diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs index 0e9b98f30..c201179c1 100644 --- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs +++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs @@ -602,7 +602,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree List path = new List(); while (node.Parent != null) { - path.Add(node.ToString()); + path.Add(node.ToString()!); node = node.Parent; } path.Reverse(); diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 5ad397a07..f8da82342 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -1100,7 +1100,11 @@ namespace ICSharpCode.ILSpy.TextView SaveFileDialog dlg = new SaveFileDialog(); dlg.DefaultExt = language.FileExtension; dlg.Filter = language.Name + "|*" + language.FileExtension + Properties.Resources.AllFiles; - dlg.FileName = WholeProjectDecompiler.CleanUpFileName(treeNodes.First().Text.ToString(), language.FileExtension); + string? nodeText = treeNodes.First().Text?.ToString(); + if (!string.IsNullOrWhiteSpace(nodeText)) + { + dlg.FileName = WholeProjectDecompiler.CleanUpFileName(nodeText, language.FileExtension); + } if (dlg.ShowDialog() == true) { SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), dlg.FileName); From 5297b0b322e8fc33a97d0d40db8a1c416e65a281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ku=C4=8Dera?= Date: Fri, 10 Oct 2025 12:10:31 +0100 Subject: [PATCH 27/32] List name first in ILSpy title for multiple instance --- ILSpy/AssemblyTree/AssemblyTreeModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs index c201179c1..7f2829e03 100644 --- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs +++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs @@ -469,9 +469,9 @@ namespace ICSharpCode.ILSpy.AssemblyTree #endif else #if DEBUG - mainWindow.Title = $"ILSpy {DecompilerVersionInfo.FullVersion} - " + assemblyList.ListName; + mainWindow.Title = string.Format(settingsService.MiscSettings.AllowMultipleInstances ? "{1} - {0}" : "{0} - {1}", $"ILSpy {DecompilerVersionInfo.FullVersion}", assemblyList.ListName); #else - mainWindow.Title = "ILSpy - " + assemblyList.ListName; + mainWindow.Title = string.Format(settingsService.MiscSettings.AllowMultipleInstances ? "{1} - {0}" : "{0} - {1}", "ILSpy", assemblyList.ListName); #endif } From d736b02e2b78e342cd3a1546517bf3c6850ff1c1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 11 Oct 2025 09:26:44 +0200 Subject: [PATCH 28/32] Fix #3480: assert at ExpressionBuilder.BuildArrayInitializerExpression with properties that are not C# indexers, but parameterized properties. --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 4c038c621..7701ae7ce 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -3513,11 +3513,11 @@ namespace ICSharpCode.Decompiler.CSharp ); break; case IL.Transforms.AccessPathKind.Setter: - Debug.Assert(lastElement.Member is IProperty || lastElement.Member is IField); - if (lastElement.Indices?.Length > 0) + Debug.Assert(lastElement.Member is IProperty or IField); + if (lastElement.Indices?.Length is var indices and > 0) { var property = (IProperty)lastElement.Member; - Debug.Assert(property.IsIndexer); + Debug.Assert(property.Parameters.Count == indices); Debug.Assert(property.Setter != null, $"Indexer property {property} has no setter"); elementsStack.Peek().Add( new CallBuilder(this, typeSystem, settings) From 995d31fc2d56be836fd4f20d242c44c3dfd7661e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 11 Oct 2025 10:03:32 +0200 Subject: [PATCH 29/32] Fix #3318: missing x:FieldModifier in BAML decompiler --- .../Rewrite/ConnectionIdRewritePass.cs | 8 ++++-- ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs | 8 ++++-- .../Cases/Issue3318.xaml | 3 +++ .../Cases/Issue3318.xaml.cs | 26 +++++++++++++++++++ .../ILSpy.BamlDecompiler.Tests.csproj | 4 +++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml create mode 100644 ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml.cs diff --git a/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs index ed51d50a9..0c082902c 100644 --- a/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs @@ -22,13 +22,12 @@ using System.Linq; using System.Reflection.Metadata; using System.Xml.Linq; +using ICSharpCode.BamlDecompiler.Xaml; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; -using ICSharpCode.BamlDecompiler.Xaml; - namespace ICSharpCode.BamlDecompiler.Rewrite { using ICSharpCode.Decompiler.TypeSystem; @@ -67,6 +66,11 @@ namespace ICSharpCode.BamlDecompiler.Rewrite { element.Add(new XAttribute(xName, fieldAssignment.Field.Name)); } + // x:FieldModifier can only be "public" or "internal" (in C#), where "internal" is the default and thus omitted + if (fieldAssignment.Field.Accessibility is Accessibility.Public) + { + element.Add(new XAttribute(ctx.GetKnownNamespace("FieldModifier", XamlContext.KnownNamespace_Xaml, element), "public")); + } ctx.GeneratedMembers.Add(fieldAssignment.Field.MetadataToken); found = true; } diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 61aa2fb11..951d3c5c6 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -17,10 +17,8 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections; using System.IO; using System.Linq; -using System.Threading; using System.Xml.Linq; using ICSharpCode.BamlDecompiler; @@ -155,6 +153,12 @@ namespace ILSpy.BamlDecompiler.Tests RunTest("cases/issue2116"); } + [Test] + public void Issue3318() + { + RunTest("cases/issue3318"); + } + [Test] public void ReadonlyProperty() { diff --git a/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml b/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml new file mode 100644 index 000000000..d873046b1 --- /dev/null +++ b/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml @@ -0,0 +1,3 @@ + + + diff --git a/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml.cs b/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml.cs new file mode 100644 index 000000000..17789b0b5 --- /dev/null +++ b/ILSpy.BamlDecompiler.Tests/Cases/Issue3318.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ILSpy.BamlDecompiler.Tests.Cases +{ + /// + /// Interaction logic for Issue3318.xaml + /// + public partial class Issue3318 : UserControl + { + public Issue3318() + { + InitializeComponent(); + } + } +} diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj index ca43a1bbc..aa80040c3 100644 --- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj +++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -62,6 +62,7 @@ + MyControl.xaml @@ -104,6 +105,9 @@ MSBuild:Compile + + MSBuild:Compile + Designer From d11c40719dd142c9c7d47f0896da26414c5079c1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 11 Oct 2025 21:10:51 +0200 Subject: [PATCH 30/32] #3569: Don't move out variable declarations out of lambdas. --- .../CSharp/Transforms/DeclareVariables.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index fd27a9fea..d64137b80 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -290,6 +290,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // track loops and function bodies as scopes, for comparison with CaptureScope. scopeTracking.Add((new InsertionPoint { level = nodeLevel, nextNode = node }, scope)); } + else if (node is LambdaExpression { Body: Expression expr }) + { + // expression-bodied lambdas don't have a BlockStatement linking to the BlockContainer + scope = node.Annotation()?.Body as BlockContainer; + if (scope != null) + { + scopeTracking.Add((new InsertionPoint { level = nodeLevel + 1, nextNode = expr }, scope)); + } + } else { scope = null; // don't remove a scope if we didn't add one @@ -455,7 +464,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // We can only insert variable declarations in blocks, but FindInsertionPoints() didn't // guarantee that it finds only blocks. // Fix that up now. - while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) + while (!(v.InsertionPoint.nextNode.Parent is BlockStatement or LambdaExpression)) { if (v.InsertionPoint.nextNode.Parent is ForStatement f && v.InsertionPoint.nextNode == f.Initializers.FirstOrDefault() && IsMatchingAssignment(v, out _)) { @@ -673,6 +682,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } var vds = new VariableDeclarationStatement(type, v.Name, initializer); vds.Variables.Single().AddAnnotation(new ILVariableResolveResult(ilVariable)); + if (v.InsertionPoint.nextNode.Parent is LambdaExpression lambda) + { + Debug.Assert(lambda.Body is not BlockStatement); + lambda.Body = new BlockStatement() { + new ReturnStatement((Expression)lambda.Body.Detach()) + }; + } + if (v.InsertionPoint.nextNode.Parent is ReturnStatement) + { + v.InsertionPoint = v.InsertionPoint.Up(); + } Debug.Assert(v.InsertionPoint.nextNode.Role == BlockStatement.StatementRole); if (v.DefaultInitialization == VariableInitKind.NeedsSkipInit) { From c075f7b9c80a5ca85be6d5c36ffb2f044dab50d1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 11 Oct 2025 21:47:11 +0200 Subject: [PATCH 31/32] Fix out var for expressions appearing in a lambda and not in a statement. --- .../TestCases/Pretty/OutVariables.cs | 9 +++++++++ .../CSharp/Transforms/DeclareVariables.cs | 8 +++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs index d7bd852c3..6d519c523 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs @@ -72,5 +72,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty GetObject(out dynamic obj); obj.Method(); } + + public void M5() + { + Func func = () => TryGet(out var result) && result != null; + Func func2 = () => TryGet(out var result) && result != null; + + func(); + func2(); + } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index d64137b80..73f11bc6a 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -776,11 +776,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } switch (node) { - case IfElseStatement _: // variable declared in if condition appears in parent scope - case ExpressionStatement _: + case IfElseStatement: // variable declared in if condition appears in parent scope + case ExpressionStatement: return node == v.InsertionPoint.nextNode; - case Statement _: + case Statement: return false; // other statements (e.g. while) don't allow variables to be promoted to parent scope + case LambdaExpression lambda: + return lambda.Body == v.InsertionPoint.nextNode; } } return false; From 80a9f513796484583da081d341a7ebd431067549 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 22:02:36 +0000 Subject: [PATCH 32/32] Bump github/codeql-action from 3 to 4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index da921e613..8668cfd62 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} @@ -44,4 +44,4 @@ jobs: run: dotnet build ILSpy.XPlat.slnf --configuration Release -p:RestoreEnablePackagePruning=false - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a8859f6ba..fb55017d1 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -43,6 +43,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif