From ce04dc2a55c0286aceeef5629810779aa1c44aa0 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sat, 15 Aug 2026 00:33:13 +0900 Subject: [PATCH 1/6] Add real disassembler IL corpus --- .gitattributes | 3 + CHANGELOG.md | 8 + .../Fixtures/ILCorpus/README.md | 55 + .../Fixtures/ILCorpus/Source/AssemblyInfo.cs | 9 + .../ILCorpus/Source/ILCorpus.Sample.csproj | 15 + .../ILCorpus/Source/ILCorpus.TestKey.snk | Bin 0 -> 1172 bytes .../ILCorpus/Source/RepresentativeTypes.cs | 97 ++ .../Fixtures/ILCorpus/dotnet-ildasm-0.12.2.il | 641 ++++++++++++ .../Fixtures/ILCorpus/ilspycmd-9.1.0.7988.il | 979 ++++++++++++++++++ .../Fixtures/ILCorpus/regenerate.ps1 | 48 + .../FolderDiffIL4DotNet.Tests.csproj | 1 + .../Services/ILOutputCorpusTests.cs | 120 +++ 12 files changed, 1976 insertions(+) create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/README.md create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/AssemblyInfo.cs create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.Sample.csproj create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.TestKey.snk create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/RepresentativeTypes.cs create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/dotnet-ildasm-0.12.2.il create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/ilspycmd-9.1.0.7988.il create mode 100644 FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 create mode 100644 FolderDiffIL4DotNet.Tests/Services/ILOutputCorpusTests.cs diff --git a/.gitattributes b/.gitattributes index 82f41b1d..8712709a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,3 +9,6 @@ *.jpeg binary *.png binary *.zip binary + +# Preserve raw disassembler output while keeping whitespace checks enabled elsewhere. +FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/*.il whitespace=-blank-at-eol,-blank-at-eof diff --git a/CHANGELOG.md b/CHANGELOG.md index 72df58dd..6fb38034 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### [Unreleased] +#### Added + +- **Real disassembler IL corpus** — Added reproducible source and pinned golden IL from `dotnet-ildasm 0.12.2.0` and `ilspycmd 9.1.0.7988`, the fallback baseline for inspecting assemblies targeting .NET 8/9/10. The signed test assembly covers ordinary classes and multiple methods, instance/static constructors, async and iterator state machines, lambdas and compiler-generated types, generic types and methods, properties, events, fields, signed AssemblyRefs, and reproducible COM interop metadata. A clearly identified test-only strong-name key keeps the sample assembly and public key token reproducible. ActiveX wrapper output is documented but excluded because portable `aximp` tooling and reproducible input are not available in the cross-platform .NET SDK. Corpus regeneration requires PowerShell 7 (`pwsh`); its .NET major-version roll-forward policy now covers tool version probes as well as build/generation and restores the caller's environment afterward. + ### [1.24.0] - 2026-07-29 #### Added @@ -1719,6 +1723,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### [Unreleased] +#### 追加 + +- **実逆アセンブラ IL コーパス** — 再生成可能なソースと、`dotnet-ildasm 0.12.2.0` および.NET 8/9/10をtarget frameworkとするAssemblyを調査するfallback baselineである `ilspycmd 9.1.0.7988` から取得したgolden ILを追加しました。署名済みテストAssemblyは、通常classと複数method、instance/static constructor、async/iterator state machine、lambda/compiler-generated type、generic type/method、property/event/field、署名済みAssemblyRef、再現可能なCOM interop metadataを網羅します。用途を明記したテスト専用strong-name鍵により、サンプルAssemblyとpublic key tokenの再現性を維持します。ActiveX wrapper出力は、cross-platform .NET SDKでportableな `aximp` ツールと再現可能な入力を用意できないため、除外理由のみ文書化しています。コーパス再生成にはPowerShell 7(`pwsh`)が必要で、.NET major-version roll-forwardポリシーはtool version probeからbuild/生成までを包含し、終了後に呼び出し元環境を復元します。 + ### [1.24.0] - 2026-07-29 #### 追加 diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/README.md b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/README.md new file mode 100644 index 00000000..755a4d52 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/README.md @@ -0,0 +1,55 @@ +# Real IL output corpus + +## English + +This directory contains golden IL emitted from the same small, deterministic test assembly by two supported disassemblers: + +- `dotnet-ildasm 0.12.2.0`: `dotnet-ildasm-0.12.2.il` +- `ilspycmd 9.1.0.7988`: `ilspycmd-9.1.0.7988.il` + +The sample covers ordinary nested classes and methods, instance and static constructors, async and iterator state machines, lambdas and compiler-generated types, generic types and methods, properties, events, fields, a strong-name-signed assembly, signed framework AssemblyRefs, and reproducible COM interop metadata. + +The fixtures establish that `dotnet-ildasm` emits `// Method begins at Relative Virtual Address (RVA) 0x` and `// Code size `, while `ilspycmd` emits `// Method begins at RVA 0x` and `// Code size: `. They also establish that dotnet-ildasm custom-attribute signatures include `class ` before the assembly-qualified attribute type while ilspycmd signatures omit it. + +`nildiff` itself targets `net8.0` and requires the .NET 8 runtime. `ilspycmd 9.1.0.7988` is pinned as the fallback baseline for inspecting assemblies that target .NET 8, .NET 9, or .NET 10; those target-framework versions do not describe the runtime used to execute `nildiff`. + +The committed `ILCorpus.TestKey.snk` is a test-only strong-name key. It is public test material, not a credential, and must never be used to sign production assemblies. + +ActiveX wrapper output is not included. Reproducing `AxHost.TypeLibraryTimeStampAttribute` requires Windows-specific `aximp` input and tooling that are not part of the .NET SDK, so it would not be a portable, reproducible fixture. The source-level COM interface and coclass metadata are included instead. + +From the repository root, regenerate both files with: + +```powershell +pwsh -File FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 +``` + +Regeneration requires PowerShell 7 (`pwsh`), .NET SDK 8.0.423 from `global.json`, and both pinned disassemblers on `PATH`. The script uses cross-platform PowerShell APIs and the same command works on Windows, macOS, and Linux; fixture output should still be reviewed on the platform where it was generated. + +Review fixture changes before committing them. Disassembler upgrades intentionally require updating the pinned filenames, version checks, tests, and this document together. + +## 日本語 + +このディレクトリには、同じ小型の決定的テストAssemblyを、サポート対象の2つの逆アセンブラで処理したgolden ILを保存しています。 + +- `dotnet-ildasm 0.12.2.0`: `dotnet-ildasm-0.12.2.il` +- `ilspycmd 9.1.0.7988`: `ilspycmd-9.1.0.7988.il` + +サンプルには、通常のclass内の複数method、instance/static constructor、async/iterator state machine、lambda/compiler-generated type、generic type/method、property/event/field、strong-name署名Assembly、署名されたframework AssemblyRef、再現可能なCOM interop metadataが含まれます。 + +fixtureにより、`dotnet-ildasm` は `// Method begins at Relative Virtual Address (RVA) 0x` と `// Code size `、`ilspycmd` は `// Method begins at RVA 0x` と `// Code size: ` を出力することを固定しています。また、dotnet-ildasmのcustom attributeシグネチャはAssembly修飾付きattribute型の前に `class ` を含み、ilspycmdは含まないことも固定しています。 + +`nildiff` 本体のtarget frameworkは `net8.0` で、実行には.NET 8 runtimeが必要です。`ilspycmd 9.1.0.7988` は、.NET 8、.NET 9、.NET 10をtarget frameworkとするAssemblyを調査するためのfallback baselineとして固定しています。これらのtarget framework versionは、`nildiff` 自体を実行するruntimeを意味しません。 + +コミットされている `ILCorpus.TestKey.snk` はテスト専用strong-name鍵です。公開テスト資材でありcredentialではありません。production Assemblyの署名には使用しないでください。 + +ActiveX wrapper出力は含めていません。`AxHost.TypeLibraryTimeStampAttribute` の再現には、.NET SDKに含まれないWindows固有の `aximp` 入力とツールが必要で、portableかつ再現可能なfixtureにできないためです。代わりにソースから再現できるCOM interfaceとcoclass metadataを含めています。 + +リポジトリルートから、次のコマンドで両方のファイルを再生成します。 + +```powershell +pwsh -File FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 +``` + +再生成にはPowerShell 7(`pwsh`)、`global.json` で固定した.NET SDK 8.0.423、`PATH` 上の両固定バージョン逆アセンブラが必要です。このスクリプトはcross-platformなPowerShell APIを使用しており、Windows、macOS、Linuxで同じコマンドを使えますが、生成したplatform上でfixture差分を確認してください。 + +コミット前にfixture差分を確認してください。逆アセンブラを更新する場合は、固定バージョン入りファイル名、バージョン検証、テスト、この文書を同時に更新します。 diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/AssemblyInfo.cs b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/AssemblyInfo.cs new file mode 100644 index 00000000..f3792e2c --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/AssemblyInfo.cs @@ -0,0 +1,9 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("nildiff IL corpus sample")] +[assembly: AssemblyDescription("Test-only assembly used to capture real disassembler output.")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] +[assembly: Guid("d1d8c6cc-1d58-4d3b-9f2f-a0172c9c4331")] diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.Sample.csproj b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.Sample.csproj new file mode 100644 index 00000000..f2603b59 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.Sample.csproj @@ -0,0 +1,15 @@ + + + net8.0 + ILCorpus.Sample + ILCorpus.Sample + enable + disable + true + none + false + false + true + ILCorpus.TestKey.snk + + diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.TestKey.snk b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/ILCorpus.TestKey.snk new file mode 100644 index 0000000000000000000000000000000000000000..9838f6e748197975b6ef109d6a67d1932f72e8aa GIT binary patch literal 1172 zcmV;F1Z(>T0ssI2qyPX?Q$aES2mk;90098u4aJ65GWZo?tSOitDrgjDaa0U|E3%ZY zvrWKd&t0BRR|AHpJy&*qB8l1;fTbw4KDRMbM=NFLerjM{y+SJEFp~@U5R)qrid+Tp zUvcEeX^VIy2}i3#9F3FeI1e`&?2SFFZz8=OiD=1jC)!3Zls?XKHhT$?A^60Q%indsCeh~Ha>ShF){ZPne zze3Pu)Gwp73UJ;mtwUpd>oTjev&wD|IKp@;HFOtgsp10y)k+BIb+k@0>b52%69 zS^Pm-i&l$H)_!qvjpI6xcrqUyMVC_>Z#!bTh*1vc@BacD2Gs00?Qhir#*qdrk%$K& zub3d34e{KCAvu<;>}eJdF(i*|VMq~=WGNU`|>(!Fq;J?OMyhT z!p<&E^DSPZeYfMZ`(oJnw1|+9_Q^%cr#UCgEVSV^{G-XEc`fivOwvC%N)esbtBO0N zdMmqaHKCvig%86`6yEz!YA)cmEnA)`7|UW?o5^_Qryj_W(sQuukF#UzfMCHt8@$T~ zJ@Y;hc(*fyaKvHw7i@gYsZz-yx(wNa1fYG^w{OC{gvrEauYWl^n{<$4F=kGWGL78M zlGwa55iCxL>`aTr-kf@)`f_nyuQN$Jwh-B1!1-AxF)J=zU*_~nETeC(RB0k`p#cgy4`-6^h|aBe(@v5reoz z>Vt3lbK{uqB1Wb0omYGdKAF literal 0 HcmV?d00001 diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/RepresentativeTypes.cs b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/RepresentativeTypes.cs new file mode 100644 index 00000000..8f511293 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/Source/RepresentativeTypes.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ILCorpus.Sample +{ + public sealed class RepresentativeType + where T : class, new() + { + public const int DefaultValue = 7; + public static readonly string StaticValue; + + private T _value; + + static RepresentativeType() + { + StaticValue = "initialized"; + } + + public RepresentativeType() + { + _value = new T(); + Name = string.Empty; + } + + public string Name { get; set; } + + public T Value + { + get => _value; + set + { + _value = value; + Changed?.Invoke(this, EventArgs.Empty); + } + } + + public event EventHandler? Changed; + + public int Add(int left, int right) + { + return left + right; + } + + public TResult Convert(Func converter) + { + return converter(_value); + } + + public async Task ComputeAsync(int value) + { + await Task.Yield(); + return value + DefaultValue; + } + + public IEnumerable CountTo(int maximum) + { + for (var value = 0; value < maximum; value++) + { + yield return value; + } + } + + public Func CreateAdder(int offset) + { + return value => value + offset; + } + } + + [ComVisible(true)] + [ComImport] + [Guid("58883045-92b4-4c9f-a42a-3e25a9b90f78")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + public interface ICorpusComContract + { + [DispId(1)] + string Echo([MarshalAs(UnmanagedType.BStr)] string value); + + [DispId(2)] + int Number { get; set; } + } + + [ComVisible(true)] + [Guid("432398e1-334f-45af-8387-82f34b8ac526")] + [ClassInterface(ClassInterfaceType.None)] + public sealed class CorpusComClass : ICorpusComContract + { + public int Number { get; set; } + + public string Echo(string value) + { + return value; + } + } +} diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/dotnet-ildasm-0.12.2.il b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/dotnet-ildasm-0.12.2.il new file mode 100644 index 00000000..76b36963 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/dotnet-ildasm-0.12.2.il @@ -0,0 +1,641 @@ + +.assembly extern System.Runtime +{ + .publickeytoken = ( B0 3F 5F 7F 11 D5 0A 3A ) // .._..... + .ver 8:0:0:0 +} + +.assembly extern System.Runtime.InteropServices +{ + .publickeytoken = ( B0 3F 5F 7F 11 D5 0A 3A ) // .._..... + .ver 8:0:0:0 +} + +.assembly extern System.Threading +{ + .publickeytoken = ( B0 3F 5F 7F 11 D5 0A 3A ) // .._..... + .ver 8:0:0:0 +} + +.assembly 'ILCorpus.Sample' +{ + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) // ........ + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ....T..WrapNonExceptionThrows. + .custom instance void class [System.Runtime]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 18 6E 69 6C 64 69 66 66 20 49 4C 20 63 6F 72 70 75 73 20 73 61 6D 70 6C 65 00 00 ) // ...nildiff.IL.corpus.sample.. + .custom instance void class [System.Runtime]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 3C 54 65 73 74 2D 6F 6E 6C 79 20 61 73 73 65 6D 62 6C 79 20 75 73 65 64 20 74 6F 20 63 61 70 74 75 72 65 20 72 65 61 6C 20 64 69 73 61 73 73 65 6D 62 6C 65 72 20 6F 75 74 70 75 74 2E 00 00 ) // ...Test.only.assembly.used.to.capture.real.disassembler.output... + .custom instance void class [System.Runtime]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0.. + .custom instance void class [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) // ..... + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 64 31 64 38 63 36 63 63 2D 31 64 35 38 2D 34 64 33 62 2D 39 66 32 66 2D 61 30 31 37 32 63 39 63 34 33 33 31 00 00 ) // ...d1d8c6cc.1d58.4d3b.9f2f.a0172c9c4331.. + .custom instance void class [System.Runtime]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 18 2E 4E 45 54 43 6F 72 65 41 70 70 2C 56 65 72 73 69 6F 6E 3D 76 38 2E 30 01 00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C 61 79 4E 61 6D 65 08 2E 4E 45 54 20 38 2E 30 ) // ....NETCoreApp.Version.v8.0..T..FrameworkDisplayName..NET.8.0 + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} + +.module 'ILCorpus.Sample.dll' +// MVID: {06e8a859-d81d-48da-a59a-eb5b8dc94c2e} +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WindowsCui +.corflags 0x00000009 // + +.class public auto ansi sealed ILCorpus.Sample.RepresentativeType`1 extends [System.Runtime]System.Object +{ + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(byte) = ( 01 00 01 00 00 ) // ..... + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(byte) = ( 01 00 00 00 00 ) // ..... + .field public static int32 DefaultValue + .field public static initonly string StaticValue + .field private var _value + .field private string 'k__BackingField' + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .field private class [System.Runtime]System.EventHandler Changed + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(byte) = ( 01 00 02 00 00 ) // ..... + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .method private hidebysig specialname rtspecialname static default void .cctor() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x2050 + // Code size 11 (0xB) + .maxstack 8 + IL_0000: ldstr "initialized" + IL_0005: stsfld string [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::StaticValue + IL_000a: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::.cctor() + .method public hidebysig specialname rtspecialname instance default void .ctor() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x205C + // Code size 29 (0x1D) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [System.Runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: call !!0 class [System.Runtime]System.Activator::CreateInstance() + IL_000c: stfld var [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::_value + IL_0011: ldarg.0 + IL_0012: ldsfld string string::Empty + IL_0017: call instance void class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::set_Name(string) + IL_001c: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::.ctor() + .method public hidebysig specialname instance default string get_Name() cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x207A + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld string [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::'k__BackingField' + IL_0006: ret + } // End of method System.String ILCorpus.Sample.RepresentativeType`1::get_Name() + .method public hidebysig specialname instance default void set_Name(string 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x2082 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld string [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::'k__BackingField' + IL_0007: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::set_Name(System.String) + .method public hidebysig specialname instance default var get_Value() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x208B + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld var [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::_value + IL_0006: ret + } // End of method T ILCorpus.Sample.RepresentativeType`1::get_Value() + .method public hidebysig specialname instance default void set_Value(var 'value') cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x2093 + // Code size 30 (0x1E) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld var [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::_value + IL_0007: ldarg.0 + IL_0008: ldfld class [System.Runtime]System.EventHandler [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::Changed + IL_000d: dup + IL_000e: brtrue.s IL_0012 + IL_0010: pop + IL_0011: ret + IL_0012: ldarg.0 + IL_0013: ldsfld class [System.Runtime]System.EventArgs [System.Runtime]System.EventArgs::Empty + IL_0018: callvirt instance void class [System.Runtime]System.EventHandler::Invoke([System.Runtime]System.Object, [System.Runtime]System.EventArgs) + IL_001d: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::set_Value(T) + .method public hidebysig specialname instance default void add_Changed(class [System.Runtime]System.EventHandler 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(byte) = ( 01 00 02 00 00 ) // ..... + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x20B4 + // Code size 41 (0x29) + .maxstack 3 + .locals init(class [System.Runtime]System.EventHandler V_0, class [System.Runtime]System.EventHandler V_1, class [System.Runtime]System.EventHandler V_2) + IL_0000: ldarg.0 + IL_0001: ldfld class [System.Runtime]System.EventHandler [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::Changed + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldarg.1 + IL_000b: call [System.Runtime]System.Delegate class [System.Runtime]System.Delegate::Combine([System.Runtime]System.Delegate, [System.Runtime]System.Delegate) + IL_0010: castclass class System.EventHandler + IL_0015: stloc.2 + IL_0016: ldarg.0 + IL_0017: ldflda class [System.Runtime]System.EventHandler [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::Changed + IL_001c: ldloc.2 + IL_001d: ldloc.1 + IL_001e: call !!0 class [System.Threading]System.Threading.Interlocked::CompareExchange(!!0&, !!0, !!0) + IL_0023: stloc.0 + IL_0024: ldloc.0 + IL_0025: ldloc.1 + IL_0026: bne.un.s IL_0007 + IL_0028: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::add_Changed(System.EventHandler) + .method public hidebysig specialname instance default void remove_Changed(class [System.Runtime]System.EventHandler 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(byte) = ( 01 00 02 00 00 ) // ..... + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x20EC + // Code size 41 (0x29) + .maxstack 3 + .locals init(class [System.Runtime]System.EventHandler V_0, class [System.Runtime]System.EventHandler V_1, class [System.Runtime]System.EventHandler V_2) + IL_0000: ldarg.0 + IL_0001: ldfld class [System.Runtime]System.EventHandler [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::Changed + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldarg.1 + IL_000b: call [System.Runtime]System.Delegate class [System.Runtime]System.Delegate::Remove([System.Runtime]System.Delegate, [System.Runtime]System.Delegate) + IL_0010: castclass class System.EventHandler + IL_0015: stloc.2 + IL_0016: ldarg.0 + IL_0017: ldflda class [System.Runtime]System.EventHandler [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::Changed + IL_001c: ldloc.2 + IL_001d: ldloc.1 + IL_001e: call !!0 class [System.Threading]System.Threading.Interlocked::CompareExchange(!!0&, !!0, !!0) + IL_0023: stloc.0 + IL_0024: ldloc.0 + IL_0025: ldloc.1 + IL_0026: bne.un.s IL_0007 + IL_0028: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1::remove_Changed(System.EventHandler) + .method public hidebysig instance default int32 Add(int32 left, int32 right) cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x2121 + // Code size 4 (0x4) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } // End of method System.Int32 ILCorpus.Sample.RepresentativeType`1::Add(System.Int32,System.Int32) + .method public hidebysig instance default mvar Convert(class [System.Runtime]System.Func`2 converter) cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x2126 + // Code size 13 (0xD) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld var [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1::_value + IL_0007: callvirt instance var class [System.Runtime]System.Func`2::Invoke(var) + IL_000c: ret + } // End of method TResult ILCorpus.Sample.RepresentativeType`1::Convert(System.Func`2) + .method public hidebysig instance default [System.Runtime]System.Threading.Tasks.Task`1 ComputeAsync(int32 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor([System.Runtime]System.Type) = ( 01 00 38 49 4C 43 6F 72 70 75 73 2E 53 61 6D 70 6C 65 2E 52 65 70 72 65 73 65 6E 74 61 74 69 76 65 54 79 70 65 60 31 2B 3C 43 6F 6D 70 75 74 65 41 73 79 6E 63 3E 64 5F 5F 31 37 00 00 ) // ..8ILCorpus.Sample.RepresentativeType.1..ComputeAsync.d__17.. + // Method begins at Relative Virtual Address (RVA) 0x2134 + // Code size 55 (0x37) + .maxstack 2 + .locals init(class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17 V_0) + IL_0000: ldloca.s class V_0 + IL_0002: call [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0007: stfld class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_000c: ldloca.s class V_0 + IL_000e: ldarg.1 + IL_000f: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::value + IL_0014: ldloca.s class V_0 + IL_0016: ldc.i4.m1 + IL_0017: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_001c: ldloca.s class V_0 + IL_001e: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_0023: ldloca.s class V_0 + IL_0025: call instance System.Void class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start< ILCorpus.Sample.RepresentativeType`1/d__17>(!!0&) + IL_002a: ldloca.s class V_0 + IL_002c: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_0031: call instance [System.Runtime]System.Threading.Tasks.Task`1 class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_0036: ret + } // End of method System.Threading.Tasks.Task`1 ILCorpus.Sample.RepresentativeType`1::ComputeAsync(System.Int32) + .method public hidebysig instance default [System.Runtime]System.Collections.Generic.IEnumerable`1 CountTo(int32 maximum) cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor([System.Runtime]System.Type) = ( 01 00 33 49 4C 43 6F 72 70 75 73 2E 53 61 6D 70 6C 65 2E 52 65 70 72 65 73 65 6E 74 61 74 69 76 65 54 79 70 65 60 31 2B 3C 43 6F 75 6E 74 54 6F 3E 64 5F 5F 31 38 00 00 ) // ..3ILCorpus.Sample.RepresentativeType.1..CountTo.d__18.. + // Method begins at Relative Virtual Address (RVA) 0x2177 + // Code size 15 (0xF) + .maxstack 8 + IL_0000: ldc.i4.s -2 + IL_0002: newobj instance void class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::.ctor(int32) + IL_0007: dup + IL_0008: ldarg.1 + IL_0009: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>3__maximum' + IL_000e: ret + } // End of method System.Collections.Generic.IEnumerable`1 ILCorpus.Sample.RepresentativeType`1::CountTo(System.Int32) + .method public hidebysig instance default [System.Runtime]System.Func`2 CreateAdder(int32 offset) cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x2187 + // Code size 24 (0x18) + .maxstack 8 + IL_0000: newobj instance void class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::.ctor() + IL_0005: dup + IL_0006: ldarg.1 + IL_0007: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::offset + IL_000c: ldftn instance int32 class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::b__0(int32) + IL_0012: newobj instance void class [System.Runtime]System.Func`2::.ctor([System.Runtime]System.Object, [System.Runtime]System.IntPtr) + IL_0017: ret + } // End of method System.Func`2 ILCorpus.Sample.RepresentativeType`1::CreateAdder(System.Int32) + .property instance string Name () + { + .get instance default string ILCorpus.Sample.RepresentativeType`1::get_Name () + .set instance default void ILCorpus.Sample.RepresentativeType`1::set_Name (string 'value') + } // End of property System.String ILCorpus.Sample.RepresentativeType`1::Name() + .property instance var Value () + { + .get instance default var ILCorpus.Sample.RepresentativeType`1::get_Value () + .set instance default void ILCorpus.Sample.RepresentativeType`1::set_Value (var 'value') + } // End of property T ILCorpus.Sample.RepresentativeType`1::Value() + .event class [System.Runtime]System.EventHandler Changed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(byte) = ( 01 00 02 00 00 ) // ..... + .addon instance default void ILCorpus.Sample.RepresentativeType`1::add_Changed (class [System.Runtime]System.EventHandler 'value') + .removeon instance default void ILCorpus.Sample.RepresentativeType`1::remove_Changed (class [System.Runtime]System.EventHandler 'value') + } // End of property System.EventHandler ILCorpus.Sample.RepresentativeType`1::Changed + + .class nested private auto ansi sealed beforefieldinit <>c__DisplayClass19_0 extends [System.Runtime]System.Object + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .field public int32 offset + .method public hidebysig specialname rtspecialname instance default void .ctor() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x21BC + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::.ctor() + .method hidebysig instance default int32 b__0(int32 'value') cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x21C4 + // Code size 9 (0x9) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::offset + IL_0007: add + IL_0008: ret + } // End of method System.Int32 ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0::b__0(System.Int32) + } // End of class ILCorpus.Sample.RepresentativeType`1/<>c__DisplayClass19_0 + + .class nested private auto ansi sealed beforefieldinit d__17 extends [System.Runtime]System.ValueType implements [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .field public int32 '<>1__state' + .field public class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 '<>t__builder' + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(byte) = ( 01 00 00 00 00 ) // ..... + .field public int32 value + .field private valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter '<>u__1' + .method private hidebysig newslot virtual final instance default void MoveNext() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x21D0 + // Code size 157 (0x9D) + .maxstack 3 + .locals init(int32 V_0, int32 V_1, valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter V_2, valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable V_3, class [System.Runtime]System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0041 + IL_000a: call valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable class [System.Runtime]System.Threading.Tasks.Task::Yield() + IL_000f: stloc.3 + IL_0010: ldloca.s class V_3 + IL_0012: call instance valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter class valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable::GetAwaiter() + IL_0017: stloc.2 + IL_0018: ldloca.s class V_2 + IL_001a: call instance bool class valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::get_IsCompleted() + IL_001f: brtrue.s IL_005d + IL_0021: ldarg.0 + IL_0022: ldc.i4.0 + IL_0023: dup + IL_0024: stloc.0 + IL_0025: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_002a: ldarg.0 + IL_002b: ldloc.2 + IL_002c: stfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>u__1' + IL_0031: ldarg.0 + IL_0032: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_0037: ldloca.s class V_2 + IL_0039: ldarg.0 + IL_003a: call instance System.Void class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompletedd__17>(!!0&, !!1&) + IL_003f: leave.s IL_009c + IL_0041: ldarg.0 + IL_0042: ldfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>u__1' + IL_0047: stloc.2 + IL_0048: ldarg.0 + IL_0049: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>u__1' + IL_004e: initobj class System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter + IL_0054: ldarg.0 + IL_0055: ldc.i4.m1 + IL_0056: dup + IL_0057: stloc.0 + IL_0058: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_005d: ldloca.s class V_2 + IL_005f: call instance void class valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::GetResult() + IL_0064: ldarg.0 + IL_0065: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::value + IL_006a: ldc.i4.7 + IL_006b: add + IL_006c: stloc.1 + IL_006d: leave.s IL_0088 + } + catch [System.Runtime]System.Exception + { + IL_006f: stloc.s class V_4 + IL_0071: ldarg.0 + IL_0072: ldc.i4.s -2 + IL_0074: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_0079: ldarg.0 + IL_007a: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_007f: ldloc.s class V_4 + IL_0081: call instance void class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException([System.Runtime]System.Exception) + IL_0086: leave.s IL_009c + } + IL_0088: ldarg.0 + IL_0089: ldc.i4.s -2 + IL_008b: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>1__state' + IL_0090: ldarg.0 + IL_0091: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_0096: ldloc.1 + IL_0097: call instance void class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(var) + IL_009c: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/d__17::MoveNext() + .method private hidebysig newslot virtual final instance default void SetStateMachine(class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x228C + // Code size 13 (0xD) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__17::'<>t__builder' + IL_0006: ldarg.1 + IL_0007: call instance void class [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine([System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_000c: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/d__17::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + } // End of class ILCorpus.Sample.RepresentativeType`1/d__17 + + .class nested private auto ansi sealed beforefieldinit d__18 extends [System.Runtime]System.Object implements [System.Runtime]System.Collections.Generic.IEnumerable`1, [System.Runtime]System.Collections.IEnumerable, [System.Runtime]System.Collections.Generic.IEnumerator`1, [System.Runtime]System.Collections.IEnumerator, [System.Runtime]System.IDisposable + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .field private int32 '<>1__state' + .field private int32 '<>2__current' + .field private int32 '<>l__initialThreadId' + .field private int32 maximum + .field public int32 '<>3__maximum' + .field private int32 '5__2' + .method public hidebysig specialname rtspecialname instance default void .ctor(int32 <>1__state) cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x229A + // Code size 25 (0x19) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [System.Runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_000d: ldarg.0 + IL_000e: call int32 class [System.Runtime]System.Environment::get_CurrentManagedThreadId() + IL_0013: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>l__initialThreadId' + IL_0018: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/d__18::.ctor(System.Int32) + .method private hidebysig newslot virtual final instance default void System.IDisposable.Dispose() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x22B4 + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/d__18::System.IDisposable.Dispose() + .method private hidebysig newslot virtual final instance default bool MoveNext() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x22B8 + // Code size 92 (0x5C) + .maxstack 3 + .locals init(int32 V_0, int32 V_1) + IL_0000: ldarg.0 + IL_0001: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + 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_0035 + IL_000e: ldc.i4.0 + IL_000f: ret + IL_0010: ldarg.0 + IL_0011: ldc.i4.m1 + IL_0012: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_0017: ldarg.0 + IL_0018: ldc.i4.0 + IL_0019: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'5__2' + IL_001e: br.s IL_004c + IL_0020: ldarg.0 + IL_0021: ldarg.0 + IL_0022: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'5__2' + IL_0027: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>2__current' + IL_002c: ldarg.0 + IL_002d: ldc.i4.1 + IL_002e: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_0033: ldc.i4.1 + IL_0034: ret + IL_0035: ldarg.0 + IL_0036: ldc.i4.m1 + IL_0037: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_003c: ldarg.0 + IL_003d: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'5__2' + IL_0042: stloc.1 + IL_0043: ldarg.0 + IL_0044: ldloc.1 + IL_0045: ldc.i4.1 + IL_0046: add + IL_0047: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'5__2' + IL_004c: ldarg.0 + IL_004d: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'5__2' + IL_0052: ldarg.0 + IL_0053: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::maximum + IL_0058: blt.s IL_0020 + IL_005a: ldc.i4.0 + IL_005b: ret + } // End of method System.Boolean ILCorpus.Sample.RepresentativeType`1/d__18::MoveNext() + .method private hidebysig newslot virtual specialname final instance default int32 System.Collections.Generic.IEnumerator.get_Current() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x2320 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>2__current' + IL_0006: ret + } // End of method System.Int32 ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.Generic.IEnumerator.get_Current() + .method private hidebysig newslot virtual final instance default void System.Collections.IEnumerator.Reset() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x2328 + // Code size 6 (0x6) + .maxstack 8 + IL_0000: newobj instance void class [System.Runtime]System.NotSupportedException::.ctor() + IL_0005: throw + } // End of method System.Void ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.IEnumerator.Reset() + .method private hidebysig newslot virtual specialname final instance default [System.Runtime]System.Object System.Collections.IEnumerator.get_Current() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + .param [0] + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(byte) = ( 01 00 00 00 00 ) // ..... + // Method begins at Relative Virtual Address (RVA) 0x232F + // Code size 12 (0xC) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>2__current' + IL_0006: box class System.Int32 + IL_000b: ret + } // End of method System.Object ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.IEnumerator.get_Current() + .method private hidebysig newslot virtual final instance default [System.Runtime]System.Collections.Generic.IEnumerator`1 System.Collections.Generic.IEnumerable.GetEnumerator() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x233C + // Code size 55 (0x37) + .maxstack 2 + .locals init(class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_0006: ldc.i4.s -2 + IL_0008: bne.un.s IL_0022 + IL_000a: ldarg.0 + IL_000b: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>l__initialThreadId' + IL_0010: call int32 class [System.Runtime]System.Environment::get_CurrentManagedThreadId() + IL_0015: bne.un.s IL_0022 + IL_0017: ldarg.0 + IL_0018: ldc.i4.0 + IL_0019: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>1__state' + IL_001e: ldarg.0 + IL_001f: stloc.0 + IL_0020: br.s IL_0029 + IL_0022: ldc.i4.0 + IL_0023: newobj instance void class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::.ctor(int32) + IL_0028: stloc.0 + IL_0029: ldloc.0 + IL_002a: ldarg.0 + IL_002b: ldfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::'<>3__maximum' + IL_0030: stfld int32 [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::maximum + IL_0035: ldloc.0 + IL_0036: ret + } // End of method System.Collections.Generic.IEnumerator`1 ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.Generic.IEnumerable.GetEnumerator() + .method private hidebysig newslot virtual final instance default [System.Runtime]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() cil managed + { + .custom instance void class [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x237F + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance [System.Runtime]System.Collections.Generic.IEnumerator`1 class [ILCorpus.Sample.dll]ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.Generic.IEnumerable.GetEnumerator() + IL_0006: ret + } // End of method System.Collections.IEnumerator ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.IEnumerable.GetEnumerator() + .property instance int32 System.Collections.Generic.IEnumerator.Current () + { + .get instance default int32 ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.Generic.IEnumerator.get_Current () + } // End of property System.Int32 ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.Generic.IEnumerator.Current() + .property instance [System.Runtime]System.Object System.Collections.IEnumerator.Current () + { + .get instance default [System.Runtime]System.Object ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.IEnumerator.get_Current () + } // End of property System.Object ILCorpus.Sample.RepresentativeType`1/d__18::System.Collections.IEnumerator.Current() + } // End of class ILCorpus.Sample.RepresentativeType`1/d__18 +} // End of class ILCorpus.Sample.RepresentativeType`1 + +.class public interface abstract auto ansi beforefieldinit ILCorpus.Sample.ICorpusComContract +{ + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(byte) = ( 01 00 01 00 00 ) // ..... + .custom instance void class [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 01 00 00 ) // ..... + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 35 38 38 38 33 30 34 35 2D 39 32 62 34 2D 34 63 39 66 2D 61 34 32 61 2D 33 65 32 35 61 39 62 39 30 66 37 38 00 00 ) // ...58883045.92b4.4c9f.a42a.3e25a9b90f78.. + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ComInterfaceType) = ( 01 00 00 00 00 00 00 00 ) // ........ + .method public hidebysig newslot abstract virtual instance default string Echo(string 'value') cil managed + { + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 01 00 00 00 00 00 ) // ........ + } // End of method System.String ILCorpus.Sample.ICorpusComContract::Echo(System.String) + .method public hidebysig newslot abstract virtual specialname instance default int32 get_Number() cil managed + { + } // End of method System.Int32 ILCorpus.Sample.ICorpusComContract::get_Number() + .method public hidebysig newslot abstract virtual specialname instance default void set_Number(int32 'value') cil managed + { + } // End of method System.Void ILCorpus.Sample.ICorpusComContract::set_Number(System.Int32) + .property instance int32 Number () + { + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 02 00 00 00 00 00 ) // ........ + .get instance default int32 ILCorpus.Sample.ICorpusComContract::get_Number () + .set instance default void ILCorpus.Sample.ICorpusComContract::set_Number (int32 'value') + } // End of property System.Int32 ILCorpus.Sample.ICorpusComContract::Number() +} // End of class ILCorpus.Sample.ICorpusComContract + +.class public auto ansi sealed beforefieldinit ILCorpus.Sample.CorpusComClass extends [System.Runtime]System.Object implements ILCorpus.Sample.ICorpusComContract +{ + .custom instance void class [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 01 00 00 ) // ..... + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 34 33 32 33 39 38 65 31 2D 33 33 34 66 2D 34 35 61 66 2D 38 33 38 37 2D 38 32 66 33 34 62 38 61 63 35 32 36 00 00 ) // ...432398e1.334f.45af.8387.82f34b8ac526.. + .custom instance void class [System.Runtime.InteropServices]System.Runtime.InteropServices.ClassInterfaceAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ClassInterfaceType) = ( 01 00 00 00 00 00 00 00 ) // ........ + .field private int32 'k__BackingField' + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + .method public hidebysig newslot virtual specialname final instance default int32 get_Number() cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x21A0 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 ILCorpus.Sample.CorpusComClass::'k__BackingField' + IL_0006: ret + } // End of method System.Int32 ILCorpus.Sample.CorpusComClass::get_Number() + .method public hidebysig newslot virtual specialname final instance default void set_Number(int32 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // .... + // Method begins at Relative Virtual Address (RVA) 0x21A8 + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 ILCorpus.Sample.CorpusComClass::'k__BackingField' + IL_0007: ret + } // End of method System.Void ILCorpus.Sample.CorpusComClass::set_Number(System.Int32) + .method public hidebysig newslot virtual final instance default string Echo(string 'value') cil managed + { + .custom instance void class [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(byte) = ( 01 00 01 00 00 ) // ..... + // Method begins at Relative Virtual Address (RVA) 0x21B1 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ret + } // End of method System.String ILCorpus.Sample.CorpusComClass::Echo(System.String) + .method public hidebysig specialname rtspecialname instance default void .ctor() cil managed + { + // Method begins at Relative Virtual Address (RVA) 0x21B4 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // End of method System.Void ILCorpus.Sample.CorpusComClass::.ctor() + .property instance int32 Number () + { + .get instance default int32 ILCorpus.Sample.CorpusComClass::get_Number () + .set instance default void ILCorpus.Sample.CorpusComClass::set_Number (int32 'value') + } // End of property System.Int32 ILCorpus.Sample.CorpusComClass::Number() +} // End of class ILCorpus.Sample.CorpusComClass diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/ilspycmd-9.1.0.7988.il b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/ilspycmd-9.1.0.7988.il new file mode 100644 index 00000000..596cf33d --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/ilspycmd-9.1.0.7988.il @@ -0,0 +1,979 @@ +// IL code: ILCorpus.Sample +.class private auto ansi '' +{ +} // end of class + +.class public auto ansi sealed ILCorpus.Sample.RepresentativeType`1 + extends [System.Runtime]System.Object +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 01 00 00 + ) + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + // Nested Types + .class nested private auto ansi sealed beforefieldinit '<>c__DisplayClass19_0' + extends [System.Runtime]System.Object + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Fields + .field public int32 offset + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x21bc + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // end of method '<>c__DisplayClass19_0'::.ctor + + .method assembly hidebysig + instance int32 'b__0' ( + int32 'value' + ) cil managed + { + // Method begins at RVA 0x21c4 + // Header size: 1 + // Code size: 9 (0x9) + .maxstack 8 + + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'<>c__DisplayClass19_0'::offset + IL_0007: add + IL_0008: ret + } // end of method '<>c__DisplayClass19_0'::'b__0' + + } // end of class <>c__DisplayClass19_0 + + .class nested private auto ansi sealed beforefieldinit 'd__17' + extends [System.Runtime]System.ValueType + implements [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .interfaceimpl type [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + // Fields + .field public int32 '<>1__state' + .field public valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 '<>t__builder' + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + .field public int32 'value' + .field private valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter '<>u__1' + + // Methods + .method private final hidebysig newslot virtual + instance void MoveNext () cil managed + { + .override method instance void [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() + // Method begins at RVA 0x21d0 + // Header size: 12 + // Code size: 157 (0x9d) + .maxstack 3 + .locals init ( + [0] int32, + [1] int32, + [2] valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter, + [3] valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable, + [4] class [System.Runtime]System.Exception + ) + + IL_0000: ldarg.0 + IL_0001: ldfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0041 + + IL_000a: call valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable [System.Runtime]System.Threading.Tasks.Task::Yield() + IL_000f: stloc.3 + IL_0010: ldloca.s 3 + IL_0012: call instance valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable::GetAwaiter() + IL_0017: stloc.2 + IL_0018: ldloca.s 2 + IL_001a: call instance bool [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::get_IsCompleted() + IL_001f: brtrue.s IL_005d + + IL_0021: ldarg.0 + IL_0022: ldc.i4.0 + IL_0023: dup + IL_0024: stloc.0 + IL_0025: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + IL_002a: ldarg.0 + IL_002b: ldloc.2 + IL_002c: stfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>u__1' + IL_0031: ldarg.0 + IL_0032: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_0037: ldloca.s 2 + IL_0039: ldarg.0 + IL_003a: call instance void valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompletedd__17'>(!!0&, !!1&) + IL_003f: leave.s IL_009c + + IL_0041: ldarg.0 + IL_0042: ldfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>u__1' + IL_0047: stloc.2 + IL_0048: ldarg.0 + IL_0049: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>u__1' + IL_004e: initobj [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter + IL_0054: ldarg.0 + IL_0055: ldc.i4.m1 + IL_0056: dup + IL_0057: stloc.0 + IL_0058: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + + IL_005d: ldloca.s 2 + IL_005f: call instance void [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::GetResult() + IL_0064: ldarg.0 + IL_0065: ldfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'value' + IL_006a: ldc.i4.7 + IL_006b: add + IL_006c: stloc.1 + IL_006d: leave.s IL_0088 + } // end .try + catch [System.Runtime]System.Exception + { + IL_006f: stloc.s 4 + IL_0071: ldarg.0 + IL_0072: ldc.i4.s -2 + IL_0074: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + IL_0079: ldarg.0 + IL_007a: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_007f: ldloc.s 4 + IL_0081: call instance void valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [System.Runtime]System.Exception) + IL_0086: leave.s IL_009c + } // end handler + + IL_0088: ldarg.0 + IL_0089: ldc.i4.s -2 + IL_008b: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + IL_0090: ldarg.0 + IL_0091: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_0096: ldloc.1 + IL_0097: call instance void valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + + IL_009c: ret + } // end of method 'd__17'::MoveNext + + .method private final hidebysig newslot virtual + instance void SetStateMachine ( + class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine + ) cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance void [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine(class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine) + // Method begins at RVA 0x228c + // Header size: 1 + // Code size: 13 (0xd) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_0006: ldarg.1 + IL_0007: call instance void valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [System.Runtime]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_000c: ret + } // end of method 'd__17'::SetStateMachine + + } // end of class d__17 + + .class nested private auto ansi sealed beforefieldinit 'd__18' + extends [System.Runtime]System.Object + implements class [System.Runtime]System.Collections.Generic.IEnumerable`1, + [System.Runtime]System.Collections.IEnumerable, + class [System.Runtime]System.Collections.Generic.IEnumerator`1, + [System.Runtime]System.Collections.IEnumerator, + [System.Runtime]System.IDisposable + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .interfaceimpl type class [System.Runtime]System.Collections.Generic.IEnumerable`1 + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + .interfaceimpl type [System.Runtime]System.Collections.IEnumerable + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + .interfaceimpl type class [System.Runtime]System.Collections.Generic.IEnumerator`1 + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + .interfaceimpl type [System.Runtime]System.Collections.IEnumerator + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + .interfaceimpl type [System.Runtime]System.IDisposable + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + + // Fields + .field private int32 '<>1__state' + .field private int32 '<>2__current' + .field private int32 '<>l__initialThreadId' + .field private int32 maximum + .field public int32 '<>3__maximum' + .field private int32 '5__2' + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor ( + int32 '<>1__state' + ) cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x229a + // Header size: 1 + // Code size: 25 (0x19) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_000d: ldarg.0 + IL_000e: call int32 [System.Runtime]System.Environment::get_CurrentManagedThreadId() + IL_0013: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>l__initialThreadId' + IL_0018: ret + } // end of method 'd__18'::.ctor + + .method private final hidebysig newslot virtual + instance void System.IDisposable.Dispose () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance void [System.Runtime]System.IDisposable::Dispose() + // Method begins at RVA 0x22b4 + // Header size: 1 + // Code size: 1 (0x1) + .maxstack 8 + + IL_0000: ret + } // end of method 'd__18'::System.IDisposable.Dispose + + .method private final hidebysig newslot virtual + instance bool MoveNext () cil managed + { + .override method instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext() + // Method begins at RVA 0x22b8 + // Header size: 12 + // Code size: 92 (0x5c) + .maxstack 3 + .locals init ( + [0] int32, + [1] int32 + ) + + IL_0000: ldarg.0 + IL_0001: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + 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_0035 + + IL_000e: ldc.i4.0 + IL_000f: ret + + IL_0010: ldarg.0 + IL_0011: ldc.i4.m1 + IL_0012: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_0017: ldarg.0 + IL_0018: ldc.i4.0 + IL_0019: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'5__2' + IL_001e: br.s IL_004c + + IL_0020: ldarg.0 + IL_0021: ldarg.0 + IL_0022: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'5__2' + IL_0027: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>2__current' + IL_002c: ldarg.0 + IL_002d: ldc.i4.1 + IL_002e: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_0033: ldc.i4.1 + IL_0034: ret + + IL_0035: ldarg.0 + IL_0036: ldc.i4.m1 + IL_0037: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_003c: ldarg.0 + IL_003d: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'5__2' + IL_0042: stloc.1 + IL_0043: ldarg.0 + IL_0044: ldloc.1 + IL_0045: ldc.i4.1 + IL_0046: add + IL_0047: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'5__2' + + IL_004c: ldarg.0 + IL_004d: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'5__2' + IL_0052: ldarg.0 + IL_0053: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::maximum + IL_0058: blt.s IL_0020 + + IL_005a: ldc.i4.0 + IL_005b: ret + } // end of method 'd__18'::MoveNext + + .method private final hidebysig specialname newslot virtual + instance int32 'System.Collections.Generic.IEnumerator.get_Current' () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance !0 class [System.Runtime]System.Collections.Generic.IEnumerator`1::get_Current() + // Method begins at RVA 0x2320 + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>2__current' + IL_0006: ret + } // end of method 'd__18'::'System.Collections.Generic.IEnumerator.get_Current' + + .method private final hidebysig newslot virtual + instance void System.Collections.IEnumerator.Reset () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance void [System.Runtime]System.Collections.IEnumerator::Reset() + // Method begins at RVA 0x2328 + // Header size: 1 + // Code size: 6 (0x6) + .maxstack 8 + + IL_0000: newobj instance void [System.Runtime]System.NotSupportedException::.ctor() + IL_0005: throw + } // end of method 'd__18'::System.Collections.IEnumerator.Reset + + .method private final hidebysig specialname newslot virtual + instance object System.Collections.IEnumerator.get_Current () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance object [System.Runtime]System.Collections.IEnumerator::get_Current() + .param [0] + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 00 00 00 + ) + // Method begins at RVA 0x232f + // Header size: 1 + // Code size: 12 (0xc) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>2__current' + IL_0006: box [System.Runtime]System.Int32 + IL_000b: ret + } // end of method 'd__18'::System.Collections.IEnumerator.get_Current + + .method private final hidebysig newslot virtual + instance class [System.Runtime]System.Collections.Generic.IEnumerator`1 'System.Collections.Generic.IEnumerable.GetEnumerator' () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance class [System.Runtime]System.Collections.Generic.IEnumerator`1 class [System.Runtime]System.Collections.Generic.IEnumerable`1::GetEnumerator() + // Method begins at RVA 0x233c + // Header size: 12 + // Code size: 55 (0x37) + .maxstack 2 + .locals init ( + [0] class ILCorpus.Sample.RepresentativeType`1/'d__18' + ) + + IL_0000: ldarg.0 + IL_0001: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_0006: ldc.i4.s -2 + IL_0008: bne.un.s IL_0022 + + IL_000a: ldarg.0 + IL_000b: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>l__initialThreadId' + IL_0010: call int32 [System.Runtime]System.Environment::get_CurrentManagedThreadId() + IL_0015: bne.un.s IL_0022 + + IL_0017: ldarg.0 + IL_0018: ldc.i4.0 + IL_0019: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>1__state' + IL_001e: ldarg.0 + IL_001f: stloc.0 + IL_0020: br.s IL_0029 + + IL_0022: ldc.i4.0 + IL_0023: newobj instance void class ILCorpus.Sample.RepresentativeType`1/'d__18'::.ctor(int32) + IL_0028: stloc.0 + + IL_0029: ldloc.0 + IL_002a: ldarg.0 + IL_002b: ldfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>3__maximum' + IL_0030: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::maximum + IL_0035: ldloc.0 + IL_0036: ret + } // end of method 'd__18'::'System.Collections.Generic.IEnumerable.GetEnumerator' + + .method private final hidebysig newslot virtual + instance class [System.Runtime]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed + { + .custom instance void [System.Runtime]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( + 01 00 00 00 + ) + .override method instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() + // Method begins at RVA 0x237f + // 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 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'System.Collections.Generic.IEnumerable.GetEnumerator'() + IL_0006: ret + } // end of method 'd__18'::System.Collections.IEnumerable.GetEnumerator + + // Properties + .property instance int32 'System.Collections.Generic.IEnumerator.Current'() + { + .get instance int32 ILCorpus.Sample.RepresentativeType`1/'d__18'::'System.Collections.Generic.IEnumerator.get_Current'() + } + .property instance object System.Collections.IEnumerator.Current() + { + .get instance object ILCorpus.Sample.RepresentativeType`1/'d__18'::System.Collections.IEnumerator.get_Current() + } + + } // end of class d__18 + + + // Fields + .field public static literal int32 DefaultValue = int32(7) + .field public static initonly string StaticValue + .field private !T _value + .field private string 'k__BackingField' + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + .field private class [System.Runtime]System.EventHandler Changed + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 02 00 00 + ) + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + + // Methods + .method private hidebysig specialname rtspecialname static + void .cctor () cil managed + { + // Method begins at RVA 0x2050 + // Header size: 1 + // Code size: 11 (0xb) + .maxstack 8 + + IL_0000: ldstr "initialized" + IL_0005: stsfld string class ILCorpus.Sample.RepresentativeType`1::StaticValue + IL_000a: ret + } // end of method RepresentativeType`1::.cctor + + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x205c + // Header size: 1 + // Code size: 29 (0x1d) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: call !!0 [System.Runtime]System.Activator::CreateInstance() + IL_000c: stfld !0 class ILCorpus.Sample.RepresentativeType`1::_value + IL_0011: ldarg.0 + IL_0012: ldsfld string [System.Runtime]System.String::Empty + IL_0017: call instance void class ILCorpus.Sample.RepresentativeType`1::set_Name(string) + IL_001c: ret + } // end of method RepresentativeType`1::.ctor + + .method public hidebysig specialname + instance string get_Name () cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x207a + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld string class ILCorpus.Sample.RepresentativeType`1::'k__BackingField' + IL_0006: ret + } // end of method RepresentativeType`1::get_Name + + .method public hidebysig specialname + instance void set_Name ( + string 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2082 + // Header size: 1 + // Code size: 8 (0x8) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld string class ILCorpus.Sample.RepresentativeType`1::'k__BackingField' + IL_0007: ret + } // end of method RepresentativeType`1::set_Name + + .method public hidebysig specialname + instance !T get_Value () cil managed + { + // Method begins at RVA 0x208b + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld !0 class ILCorpus.Sample.RepresentativeType`1::_value + IL_0006: ret + } // end of method RepresentativeType`1::get_Value + + .method public hidebysig specialname + instance void set_Value ( + !T 'value' + ) cil managed + { + // Method begins at RVA 0x2093 + // Header size: 1 + // Code size: 30 (0x1e) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld !0 class ILCorpus.Sample.RepresentativeType`1::_value + IL_0007: ldarg.0 + IL_0008: ldfld class [System.Runtime]System.EventHandler class ILCorpus.Sample.RepresentativeType`1::Changed + IL_000d: dup + IL_000e: brtrue.s IL_0012 + + IL_0010: pop + IL_0011: ret + + IL_0012: ldarg.0 + IL_0013: ldsfld class [System.Runtime]System.EventArgs [System.Runtime]System.EventArgs::Empty + IL_0018: callvirt instance void [System.Runtime]System.EventHandler::Invoke(object, class [System.Runtime]System.EventArgs) + IL_001d: ret + } // end of method RepresentativeType`1::set_Value + + .method public hidebysig specialname + instance void add_Changed ( + class [System.Runtime]System.EventHandler 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 02 00 00 + ) + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x20b4 + // Header size: 12 + // Code size: 41 (0x29) + .maxstack 3 + .locals init ( + [0] class [System.Runtime]System.EventHandler, + [1] class [System.Runtime]System.EventHandler, + [2] class [System.Runtime]System.EventHandler + ) + + IL_0000: ldarg.0 + IL_0001: ldfld class [System.Runtime]System.EventHandler class ILCorpus.Sample.RepresentativeType`1::Changed + IL_0006: stloc.0 + // loop start (head: IL_0007) + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldarg.1 + IL_000b: call class [System.Runtime]System.Delegate [System.Runtime]System.Delegate::Combine(class [System.Runtime]System.Delegate, class [System.Runtime]System.Delegate) + IL_0010: castclass [System.Runtime]System.EventHandler + IL_0015: stloc.2 + IL_0016: ldarg.0 + IL_0017: ldflda class [System.Runtime]System.EventHandler class ILCorpus.Sample.RepresentativeType`1::Changed + IL_001c: ldloc.2 + IL_001d: ldloc.1 + IL_001e: call !!0 [System.Threading]System.Threading.Interlocked::CompareExchange(!!0&, !!0, !!0) + IL_0023: stloc.0 + IL_0024: ldloc.0 + IL_0025: ldloc.1 + IL_0026: bne.un.s IL_0007 + // end loop + IL_0028: ret + } // end of method RepresentativeType`1::add_Changed + + .method public hidebysig specialname + instance void remove_Changed ( + class [System.Runtime]System.EventHandler 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 02 00 00 + ) + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x20ec + // Header size: 12 + // Code size: 41 (0x29) + .maxstack 3 + .locals init ( + [0] class [System.Runtime]System.EventHandler, + [1] class [System.Runtime]System.EventHandler, + [2] class [System.Runtime]System.EventHandler + ) + + IL_0000: ldarg.0 + IL_0001: ldfld class [System.Runtime]System.EventHandler class ILCorpus.Sample.RepresentativeType`1::Changed + IL_0006: stloc.0 + // loop start (head: IL_0007) + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldarg.1 + IL_000b: call class [System.Runtime]System.Delegate [System.Runtime]System.Delegate::Remove(class [System.Runtime]System.Delegate, class [System.Runtime]System.Delegate) + IL_0010: castclass [System.Runtime]System.EventHandler + IL_0015: stloc.2 + IL_0016: ldarg.0 + IL_0017: ldflda class [System.Runtime]System.EventHandler class ILCorpus.Sample.RepresentativeType`1::Changed + IL_001c: ldloc.2 + IL_001d: ldloc.1 + IL_001e: call !!0 [System.Threading]System.Threading.Interlocked::CompareExchange(!!0&, !!0, !!0) + IL_0023: stloc.0 + IL_0024: ldloc.0 + IL_0025: ldloc.1 + IL_0026: bne.un.s IL_0007 + // end loop + IL_0028: ret + } // end of method RepresentativeType`1::remove_Changed + + .method public hidebysig + instance int32 Add ( + int32 left, + int32 right + ) cil managed + { + // Method begins at RVA 0x2121 + // Header size: 1 + // Code size: 4 (0x4) + .maxstack 8 + + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } // end of method RepresentativeType`1::Add + + .method public hidebysig + instance !!TResult Convert ( + class [System.Runtime]System.Func`2 converter + ) cil managed + { + .param type TResult + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 02 00 00 + ) + // Method begins at RVA 0x2126 + // Header size: 1 + // Code size: 13 (0xd) + .maxstack 8 + + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld !0 class ILCorpus.Sample.RepresentativeType`1::_value + IL_0007: callvirt instance !1 class [System.Runtime]System.Func`2::Invoke(!0) + IL_000c: ret + } // end of method RepresentativeType`1::Convert + + .method public hidebysig + instance class [System.Runtime]System.Threading.Tasks.Task`1 ComputeAsync ( + int32 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [System.Runtime]System.Type) = ( + 01 00 38 49 4c 43 6f 72 70 75 73 2e 53 61 6d 70 + 6c 65 2e 52 65 70 72 65 73 65 6e 74 61 74 69 76 + 65 54 79 70 65 60 31 2b 3c 43 6f 6d 70 75 74 65 + 41 73 79 6e 63 3e 64 5f 5f 31 37 00 00 + ) + // Method begins at RVA 0x2134 + // Header size: 12 + // Code size: 55 (0x37) + .maxstack 2 + .locals init ( + [0] valuetype ILCorpus.Sample.RepresentativeType`1/'d__17' + ) + + IL_0000: ldloca.s 0 + IL_0002: call valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0007: stfld valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_000c: ldloca.s 0 + IL_000e: ldarg.1 + IL_000f: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'value' + IL_0014: ldloca.s 0 + IL_0016: ldc.i4.m1 + IL_0017: stfld int32 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>1__state' + IL_001c: ldloca.s 0 + IL_001e: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_0023: ldloca.s 0 + IL_0025: call instance void valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Startd__17'>(!!0&) + IL_002a: ldloca.s 0 + IL_002c: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype ILCorpus.Sample.RepresentativeType`1/'d__17'::'<>t__builder' + IL_0031: call instance class [System.Runtime]System.Threading.Tasks.Task`1 valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_0036: ret + } // end of method RepresentativeType`1::ComputeAsync + + .method public hidebysig + instance class [System.Runtime]System.Collections.Generic.IEnumerable`1 CountTo ( + int32 maximum + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor(class [System.Runtime]System.Type) = ( + 01 00 33 49 4c 43 6f 72 70 75 73 2e 53 61 6d 70 + 6c 65 2e 52 65 70 72 65 73 65 6e 74 61 74 69 76 + 65 54 79 70 65 60 31 2b 3c 43 6f 75 6e 74 54 6f + 3e 64 5f 5f 31 38 00 00 + ) + // Method begins at RVA 0x2177 + // Header size: 1 + // Code size: 15 (0xf) + .maxstack 8 + + IL_0000: ldc.i4.s -2 + IL_0002: newobj instance void class ILCorpus.Sample.RepresentativeType`1/'d__18'::.ctor(int32) + IL_0007: dup + IL_0008: ldarg.1 + IL_0009: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'d__18'::'<>3__maximum' + IL_000e: ret + } // end of method RepresentativeType`1::CountTo + + .method public hidebysig + instance class [System.Runtime]System.Func`2 CreateAdder ( + int32 offset + ) cil managed + { + // Method begins at RVA 0x2187 + // Header size: 1 + // Code size: 24 (0x18) + .maxstack 8 + + IL_0000: newobj instance void class ILCorpus.Sample.RepresentativeType`1/'<>c__DisplayClass19_0'::.ctor() + IL_0005: dup + IL_0006: ldarg.1 + IL_0007: stfld int32 class ILCorpus.Sample.RepresentativeType`1/'<>c__DisplayClass19_0'::offset + IL_000c: ldftn instance int32 class ILCorpus.Sample.RepresentativeType`1/'<>c__DisplayClass19_0'::'b__0'(int32) + IL_0012: newobj instance void class [System.Runtime]System.Func`2::.ctor(object, native int) + IL_0017: ret + } // end of method RepresentativeType`1::CreateAdder + + // Events + .event [System.Runtime]System.EventHandler Changed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( + 01 00 02 00 00 + ) + .addon instance void ILCorpus.Sample.RepresentativeType`1::add_Changed(class [System.Runtime]System.EventHandler) + .removeon instance void ILCorpus.Sample.RepresentativeType`1::remove_Changed(class [System.Runtime]System.EventHandler) + } + + + // Properties + .property instance string Name() + { + .get instance string ILCorpus.Sample.RepresentativeType`1::get_Name() + .set instance void ILCorpus.Sample.RepresentativeType`1::set_Name(string) + } + .property instance !T Value() + { + .get instance !0 ILCorpus.Sample.RepresentativeType`1::get_Value() + .set instance void ILCorpus.Sample.RepresentativeType`1::set_Value(!0) + } + +} // end of class ILCorpus.Sample.RepresentativeType`1 + +.class interface public auto ansi abstract import beforefieldinit ILCorpus.Sample.ICorpusComContract +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 01 00 00 + ) + .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( + 01 00 01 00 00 + ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( + 01 00 24 35 38 38 38 33 30 34 35 2d 39 32 62 34 + 2d 34 63 39 66 2d 61 34 32 61 2d 33 65 32 35 61 + 39 62 39 30 66 37 38 00 00 + ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ComInterfaceType) = ( + 01 00 00 00 00 00 00 00 + ) + // Methods + .method public hidebysig newslot abstract virtual + instance string Echo ( + string marshal(bstr) 'value' + ) cil managed + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( + 01 00 01 00 00 00 00 00 + ) + } // end of method ICorpusComContract::Echo + + .method public hidebysig specialname newslot abstract virtual + instance int32 get_Number () cil managed + { + } // end of method ICorpusComContract::get_Number + + .method public hidebysig specialname newslot abstract virtual + instance void set_Number ( + int32 'value' + ) cil managed + { + } // end of method ICorpusComContract::set_Number + + // Properties + .property instance int32 Number() + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( + 01 00 02 00 00 00 00 00 + ) + .get instance int32 ILCorpus.Sample.ICorpusComContract::get_Number() + .set instance void ILCorpus.Sample.ICorpusComContract::set_Number(int32) + } + +} // end of class ILCorpus.Sample.ICorpusComContract + +.class public auto ansi sealed beforefieldinit ILCorpus.Sample.CorpusComClass + extends [System.Runtime]System.Object + implements ILCorpus.Sample.ICorpusComContract +{ + .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( + 01 00 01 00 00 + ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( + 01 00 24 34 33 32 33 39 38 65 31 2d 33 33 34 66 + 2d 34 35 61 66 2d 38 33 38 37 2d 38 32 66 33 34 + 62 38 61 63 35 32 36 00 00 + ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.ClassInterfaceAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ClassInterfaceType) = ( + 01 00 00 00 00 00 00 00 + ) + // Fields + .field private int32 'k__BackingField' + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + + // Methods + .method public final hidebysig specialname newslot virtual + instance int32 get_Number () cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x21a0 + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldfld int32 ILCorpus.Sample.CorpusComClass::'k__BackingField' + IL_0006: ret + } // end of method CorpusComClass::get_Number + + .method public final hidebysig specialname newslot virtual + instance void set_Number ( + int32 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x21a8 + // Header size: 1 + // Code size: 8 (0x8) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 ILCorpus.Sample.CorpusComClass::'k__BackingField' + IL_0007: ret + } // end of method CorpusComClass::set_Number + + .method public final hidebysig newslot virtual + instance string Echo ( + string 'value' + ) cil managed + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( + 01 00 01 00 00 + ) + // Method begins at RVA 0x21b1 + // Header size: 1 + // Code size: 2 (0x2) + .maxstack 8 + + IL_0000: ldarg.1 + IL_0001: ret + } // end of method CorpusComClass::Echo + + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x21b4 + // Header size: 1 + // Code size: 7 (0x7) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: ret + } // end of method CorpusComClass::.ctor + + // Properties + .property instance int32 Number() + { + .get instance int32 ILCorpus.Sample.CorpusComClass::get_Number() + .set instance void ILCorpus.Sample.CorpusComClass::set_Number(int32) + } + +} // end of class ILCorpus.Sample.CorpusComClass + diff --git a/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 new file mode 100644 index 00000000..288a8694 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Fixtures/ILCorpus/regenerate.ps1 @@ -0,0 +1,48 @@ +[CmdletBinding()] +param( + [string] $Configuration = "Release" +) + +$ErrorActionPreference = "Stop" +$fixtureRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +$sourceRoot = Join-Path $fixtureRoot "Source" +$projectPath = Join-Path $sourceRoot "ILCorpus.Sample.csproj" +$assemblyPath = Join-Path $sourceRoot "bin/$Configuration/net8.0/ILCorpus.Sample.dll" +$dotnetIldasmOutput = Join-Path $fixtureRoot "dotnet-ildasm-0.12.2.il" +$ilspyOutput = Join-Path $fixtureRoot "ilspycmd-9.1.0.7988.il" + +$previousRollForward = $env:DOTNET_ROLL_FORWARD +try { + $env:DOTNET_ROLL_FORWARD = "Major" + + $dotnetIldasmVersion = (& dotnet-ildasm --version | Out-String) + if ($dotnetIldasmVersion -notmatch "0\.12\.2\.0") { + throw "Expected dotnet-ildasm 0.12.2.0, but got: $dotnetIldasmVersion" + } + + $ilspyVersion = (& ilspycmd --version | Out-String) + if ($ilspyVersion -notmatch "9\.1\.0\.7988") { + throw "Expected ilspycmd 9.1.0.7988, but got: $ilspyVersion" + } + + dotnet build $projectPath --configuration $Configuration --nologo + if ($LASTEXITCODE -ne 0) { + throw "Failed to build the IL corpus sample assembly." + } + + dotnet-ildasm $assemblyPath --output $dotnetIldasmOutput --force + if ($LASTEXITCODE -ne 0) { + throw "dotnet-ildasm failed." + } + + & ilspycmd --ilcode --disable-updatecheck $assemblyPath | + Set-Content -LiteralPath $ilspyOutput -Encoding utf8 + if ($LASTEXITCODE -ne 0) { + throw "ilspycmd failed." + } +} +finally { + $env:DOTNET_ROLL_FORWARD = $previousRollForward +} + +Write-Host "Regenerated IL corpus fixtures in $fixtureRoot" diff --git a/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj b/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj index 089f9dd1..f18e7fa2 100644 --- a/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj +++ b/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/FolderDiffIL4DotNet.Tests/Services/ILOutputCorpusTests.cs b/FolderDiffIL4DotNet.Tests/Services/ILOutputCorpusTests.cs new file mode 100644 index 00000000..05e25386 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/Services/ILOutputCorpusTests.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Xunit; + +namespace FolderDiffIL4DotNet.Tests.Services +{ + [Trait("Category", "Unit")] + public sealed class ILOutputCorpusTests + { + private static readonly string CorpusRoot = Path.Combine( + FindRepositoryRoot(), "FolderDiffIL4DotNet.Tests", "Fixtures", "ILCorpus"); + + public static IEnumerable DisassemblerFixtures() + { + yield return new object[] { "dotnet-ildasm", "dotnet-ildasm-0.12.2.il" }; + yield return new object[] { "ilspycmd", "ilspycmd-9.1.0.7988.il" }; + } + + [Theory] + [MemberData(nameof(DisassemblerFixtures))] + public void RealIlFixture_CoversRepresentativeLanguageAndMetadataShapes( + string disassembler, + string fixtureFileName) + { + var text = ReadFixture(fixtureFileName); + var lines = File.ReadAllLines(Path.Combine(CorpusRoot, fixtureFileName)); + + Assert.True(lines.Length > 500, $"{disassembler} fixture appears truncated."); + Assert.Contains("RepresentativeType`1", text, StringComparison.Ordinal); + Assert.Contains(".ctor", text, StringComparison.Ordinal); + Assert.Contains(".cctor", text, StringComparison.Ordinal); + Assert.Contains("d__", text, StringComparison.Ordinal); + Assert.Contains("d__", text, StringComparison.Ordinal); + Assert.Contains("<>c__DisplayClass", text, StringComparison.Ordinal); + Assert.Contains("Convert", text, StringComparison.Ordinal); + Assert.Contains(".property", text, StringComparison.Ordinal); + Assert.Contains(".event", text, StringComparison.Ordinal); + Assert.Contains(".field", text, StringComparison.Ordinal); + Assert.Contains("ICorpusComContract", text, StringComparison.Ordinal); + Assert.Contains("GuidAttribute", text, StringComparison.Ordinal); + Assert.Contains("InterfaceTypeAttribute", text, StringComparison.Ordinal); + Assert.Contains("DispIdAttribute", text, StringComparison.Ordinal); + } + + [Theory] + [MemberData(nameof(DisassemblerFixtures))] + public void RealIlFixture_PreservesClassAndNestedMethodStructure( + string disassembler, + string fixtureFileName) + { + var text = ReadFixture(fixtureFileName); + int classStart = text.IndexOf(".class public auto ansi sealed ILCorpus.Sample.RepresentativeType`1", StringComparison.Ordinal); + int constructor = text.IndexOf(".ctor", classStart, StringComparison.Ordinal); + int ordinaryMethod = text.IndexOf(" Add", constructor, StringComparison.Ordinal); + int asyncStateMachine = text.IndexOf("d__", classStart, StringComparison.Ordinal); + + Assert.True(classStart >= 0, $"{disassembler} fixture must contain the representative class."); + Assert.True(constructor > classStart, $"{disassembler} fixture must nest constructors in the class."); + Assert.True(ordinaryMethod > constructor, $"{disassembler} fixture must contain multiple class methods."); + Assert.True(asyncStateMachine > classStart, $"{disassembler} fixture must contain an async state-machine type."); + } + + [Fact] + public void DotNetIldasmFixture_ContainsSignedAssemblyAndAssemblyReferenceEvidence() + { + var text = ReadFixture("dotnet-ildasm-0.12.2.il"); + var project = File.ReadAllText(Path.Combine(CorpusRoot, "Source", "ILCorpus.Sample.csproj")); + + Assert.Contains("true", project, StringComparison.Ordinal); + Assert.True(File.Exists(Path.Combine(CorpusRoot, "Source", "ILCorpus.TestKey.snk"))); + Assert.Contains(".corflags 0x00000009", text, StringComparison.Ordinal); + Assert.Contains(".assembly extern System.Runtime", text, StringComparison.Ordinal); + Assert.Contains(".publickeytoken = (", text, StringComparison.Ordinal); + } + + [Fact] + public void DotNetIldasmFixture_ContainsItsActualCommentAndAttributeSyntax() + { + var text = ReadFixture("dotnet-ildasm-0.12.2.il"); + + Assert.Contains("// MVID: {", text, StringComparison.Ordinal); + Assert.Contains("// Method begins at Relative Virtual Address (RVA) 0x", text, StringComparison.Ordinal); + Assert.Contains("// Code size ", text, StringComparison.Ordinal); + Assert.Contains(".custom instance void class [System.Runtime]", text, StringComparison.Ordinal); + } + + [Fact] + public void IlspyFixture_ContainsItsActualCommentAndAttributeSyntax() + { + var text = ReadFixture("ilspycmd-9.1.0.7988.il"); + + Assert.Contains("// Method begins at RVA 0x", text, StringComparison.Ordinal); + Assert.Contains("// Code size: ", text, StringComparison.Ordinal); + Assert.Contains(".custom instance void [System.Runtime]", text, StringComparison.Ordinal); + Assert.DoesNotContain(".custom instance void class [System.Runtime]", text, StringComparison.Ordinal); + Assert.Contains("abstract import beforefieldinit ILCorpus.Sample.ICorpusComContract", text, StringComparison.Ordinal); + Assert.DoesNotContain("// Method begins at Relative Virtual Address (RVA) 0x", text, StringComparison.Ordinal); + } + + private static string ReadFixture(string fixtureFileName) + => File.ReadAllText(Path.Combine(CorpusRoot, fixtureFileName)); + + private static string FindRepositoryRoot() + { + string? directory = AppContext.BaseDirectory; + while (directory != null) + { + if (File.Exists(Path.Combine(directory, "FolderDiffIL4DotNet.sln"))) + { + return directory; + } + + directory = Path.GetDirectoryName(directory); + } + + throw new DirectoryNotFoundException("Could not locate the repository root for IL corpus fixtures."); + } + } +} From d4d1ef07485c8997b6f9c30fab5182a7b4ae49b9 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sun, 16 Aug 2026 01:53:31 +0900 Subject: [PATCH 2/6] Remove the ShouldIgnoreMVID setting --- CHANGELOG.md | 8 ++ .../Models/ConfigSettingsTests.cs | 15 +++ .../ProgramRunnerTests.RemovedSettings.cs | 106 ++++++++++++++++++ .../ConfigServiceTests.EnvVarsAndMutation.cs | 19 ++++ .../Services/ConfigServiceTests.cs | 17 +++ .../ILOutputServiceTests.Precompute.cs | 4 - .../Services/ILOutputServiceTests.cs | 34 ++---- .../ReportGenerateServiceTests.Header.cs | 20 ---- Models/ConfigSettings.ILSettings.cs | 12 -- Models/ConfigSettings.cs | 2 - Models/ConfigSettingsBuilder.ILSettings.cs | 3 - Models/ConfigSettingsBuilder.cs | 30 +++++ Models/IReadOnlyConfigSettings.cs | 3 - Runner/ProgramRunner.Config.cs | 20 ++-- Services/ConfigService.cs | 18 +++ .../HtmlReportGenerateService.Sections.cs | 8 +- Services/ILOutputService.Comparison.cs | 22 ++-- Services/ILOutputService.cs | 19 +--- .../SectionWriters/HeaderSectionWriter.cs | 11 +- USER_GUIDE.md | 12 +- doc/config.sample.jsonc | 9 +- doc/config.schema.json | 5 - 22 files changed, 265 insertions(+), 132 deletions(-) create mode 100644 FolderDiffIL4DotNet.Tests/ProgramRunnerTests.RemovedSettings.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fb38034..a70400aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - **Real disassembler IL corpus** — Added reproducible source and pinned golden IL from `dotnet-ildasm 0.12.2.0` and `ilspycmd 9.1.0.7988`, the fallback baseline for inspecting assemblies targeting .NET 8/9/10. The signed test assembly covers ordinary classes and multiple methods, instance/static constructors, async and iterator state machines, lambdas and compiler-generated types, generic types and methods, properties, events, fields, signed AssemblyRefs, and reproducible COM interop metadata. A clearly identified test-only strong-name key keeps the sample assembly and public key token reproducible. ActiveX wrapper output is documented but excluded because portable `aximp` tooling and reproducible input are not available in the cross-platform .NET SDK. Corpus regeneration requires PowerShell 7 (`pwsh`); its .NET major-version roll-forward policy now covers tool version probes as well as build/generation and restores the caller's environment afterward. +#### Removed + +- **`ShouldIgnoreMVID` configuration setting and API** — Removed as a breaking change; MVID lines are now always excluded from IL comparison. Supplying the former JSON key or `FOLDERDIFF_SHOULDIGNOREMVID` environment variable fails with an explicit migration error instead of being accepted and ignored. + ### [1.24.0] - 2026-07-29 #### Added @@ -1727,6 +1731,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - **実逆アセンブラ IL コーパス** — 再生成可能なソースと、`dotnet-ildasm 0.12.2.0` および.NET 8/9/10をtarget frameworkとするAssemblyを調査するfallback baselineである `ilspycmd 9.1.0.7988` から取得したgolden ILを追加しました。署名済みテストAssemblyは、通常classと複数method、instance/static constructor、async/iterator state machine、lambda/compiler-generated type、generic type/method、property/event/field、署名済みAssemblyRef、再現可能なCOM interop metadataを網羅します。用途を明記したテスト専用strong-name鍵により、サンプルAssemblyとpublic key tokenの再現性を維持します。ActiveX wrapper出力は、cross-platform .NET SDKでportableな `aximp` ツールと再現可能な入力を用意できないため、除外理由のみ文書化しています。コーパス再生成にはPowerShell 7(`pwsh`)が必要で、.NET major-version roll-forwardポリシーはtool version probeからbuild/生成までを包含し、終了後に呼び出し元環境を復元します。 +#### 削除 + +- **`ShouldIgnoreMVID` 設定とAPI** — 破壊的変更として削除しました。MVID行は常にIL比較から除外します。旧JSON keyまたは環境変数 `FOLDERDIFF_SHOULDIGNOREMVID` を指定すると、受理して無視せず明示的な移行エラーで失敗します。 + ### [1.24.0] - 2026-07-29 #### 追加 diff --git a/FolderDiffIL4DotNet.Tests/Models/ConfigSettingsTests.cs b/FolderDiffIL4DotNet.Tests/Models/ConfigSettingsTests.cs index db6510d7..acd65b8f 100644 --- a/FolderDiffIL4DotNet.Tests/Models/ConfigSettingsTests.cs +++ b/FolderDiffIL4DotNet.Tests/Models/ConfigSettingsTests.cs @@ -167,6 +167,21 @@ public void Validate_DefaultSettings_IsValid() Assert.Empty(result.Errors); } + [Theory] + [InlineData("ShouldIgnoreMVID")] + [InlineData("shouldignoremvid")] + public void Validate_RemovedShouldIgnoreMvidSetting_ReturnsMigrationError(string propertyName) + { + var builder = JsonSerializer.Deserialize($"{{ \"{propertyName}\": false }}")!; + + var result = builder.Validate(); + + Assert.False(result.IsValid); + string error = Assert.Single(result.Errors); + Assert.Contains("'ShouldIgnoreMVID' setting has been removed", error, StringComparison.Ordinal); + Assert.Contains("always excluded", error, StringComparison.Ordinal); + } + [Theory] [InlineData(0)] [InlineData(-1)] diff --git a/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.RemovedSettings.cs b/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.RemovedSettings.cs new file mode 100644 index 00000000..9e987d49 --- /dev/null +++ b/FolderDiffIL4DotNet.Tests/ProgramRunnerTests.RemovedSettings.cs @@ -0,0 +1,106 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using FolderDiffIL4DotNet.Runner; +using FolderDiffIL4DotNet.Services; +using FolderDiffIL4DotNet.Tests.Helpers; +using Xunit; + +namespace FolderDiffIL4DotNet.Tests +{ + public sealed partial class ProgramRunnerTests + { + [Theory] + [InlineData("--validate-config")] + [InlineData("--print-config")] + public async Task RunAsync_RemovedShouldIgnoreMvidSetting_ReturnsMigrationError(string command) + { + var logger = new TestLogger(logFileAbsolutePath: "test.log"); + var runner = new ProgramRunner(logger, new ConfigService()); + var originalOut = Console.Out; + var originalError = Console.Error; + using var outputWriter = new StringWriter(); + using var errorWriter = new StringWriter(); + Console.SetOut(outputWriter); + Console.SetError(errorWriter); + + try + { + await WithConfigFileAsync("""{ "ShouldIgnoreMVID": false }""", async () => + { + int exitCode = await runner.RunAsync(new[] { command }); + + Assert.Equal(3, exitCode); + Assert.Contains("'ShouldIgnoreMVID' setting has been removed", errorWriter.ToString(), StringComparison.Ordinal); + Assert.Contains("always excluded", errorWriter.ToString(), StringComparison.Ordinal); + Assert.DoesNotContain("\"ShouldIgnoreMVID\"", outputWriter.ToString(), StringComparison.Ordinal); + }); + } + finally + { + Console.SetOut(originalOut); + Console.SetError(originalError); + } + } + + [Theory] + [InlineData("ShouldIgnoreMVID")] + [InlineData("shouldignoremvid")] + public async Task RunAsync_ClearCacheFlag_WithRemovedShouldIgnoreMvidSetting_ReturnsMigrationError(string propertyName) + { + var logger = new TestLogger(logFileAbsolutePath: "test.log"); + var runner = new ProgramRunner(logger, new ConfigService()); + var originalError = Console.Error; + using var errorWriter = new StringWriter(); + Console.SetError(errorWriter); + + try + { + await WithConfigFileAsync($"{{ \"{propertyName}\": false }}", async () => + { + int exitCode = await runner.RunAsync(new[] { "--clear-cache" }); + + Assert.Equal(3, exitCode); + Assert.Contains("'ShouldIgnoreMVID' setting has been removed", errorWriter.ToString(), StringComparison.Ordinal); + Assert.Contains("always excluded", errorWriter.ToString(), StringComparison.Ordinal); + Assert.DoesNotContain("--clear-cache requires an interactive terminal", errorWriter.ToString(), StringComparison.Ordinal); + }); + } + finally + { + Console.SetError(originalError); + } + } + + [Fact] + public async Task RunAsync_ClearCacheFlag_WithRemovedShouldIgnoreMvidEnvironmentVariable_ReturnsMigrationError() + { + const string removedEnvironmentVariable = "FOLDERDIFF_SHOULDIGNOREMVID"; + string? originalValue = Environment.GetEnvironmentVariable(removedEnvironmentVariable); + var logger = new TestLogger(logFileAbsolutePath: "test.log"); + var runner = new ProgramRunner(logger, new ConfigService()); + var originalError = Console.Error; + using var errorWriter = new StringWriter(); + Console.SetError(errorWriter); + + try + { + Environment.SetEnvironmentVariable(removedEnvironmentVariable, "false"); + await WithConfigFileAsync("{}", async () => + { + int exitCode = await runner.RunAsync(new[] { "--clear-cache" }); + + Assert.Equal(3, exitCode); + Assert.Contains($"'{removedEnvironmentVariable}' has been removed", errorWriter.ToString(), StringComparison.Ordinal); + Assert.Contains("always excluded", errorWriter.ToString(), StringComparison.Ordinal); + Assert.DoesNotContain("--clear-cache requires an interactive terminal", errorWriter.ToString(), StringComparison.Ordinal); + }); + } + finally + { + Environment.SetEnvironmentVariable(removedEnvironmentVariable, originalValue); + Console.SetError(originalError); + } + } + } +} diff --git a/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.EnvVarsAndMutation.cs b/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.EnvVarsAndMutation.cs index 95cac660..6892ea4e 100644 --- a/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.EnvVarsAndMutation.cs +++ b/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.EnvVarsAndMutation.cs @@ -84,6 +84,25 @@ await WithEnvVarsAsync( }); } + [Fact] + public async Task LoadConfigBuilderAsync_RemovedShouldIgnoreMvidEnvVar_ThrowsMigrationError() + { + await WithConfigFileAsync("{}", async () => + { + await WithEnvVarsAsync( + new[] { ("FOLDERDIFF_SHOULDIGNOREMVID", "false") }, + async () => + { + var service = new ConfigService(); + + var ex = await Assert.ThrowsAsync(() => service.LoadConfigBuilderAsync()); + + Assert.Contains("'FOLDERDIFF_SHOULDIGNOREMVID' has been removed", ex.Message, StringComparison.Ordinal); + Assert.Contains("always excluded", ex.Message, StringComparison.Ordinal); + }); + }); + } + [Fact] public async Task LoadConfigBuilderAsync_EnvVarOverridesStringProperty_AppliesOverride() { diff --git a/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.cs b/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.cs index 6164ae31..7f0bf21f 100644 --- a/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.cs +++ b/FolderDiffIL4DotNet.Tests/Services/ConfigServiceTests.cs @@ -22,6 +22,23 @@ public async Task LoadConfigBuilderAsync_ExplicitConfigFileMissing_ThrowsFileNot Assert.Contains(Path.GetFullPath(missingConfigPath), ex.Message, StringComparison.Ordinal); } + [Theory] + [InlineData("ShouldIgnoreMVID")] + [InlineData("shouldignoremvid")] + public async Task LoadConfigBuilderAsync_RemovedShouldIgnoreMvidSetting_ThrowsMigrationError(string propertyName) + { + await WithConfigFileAsync($"{{ \"{propertyName}\": false }}", async () => + { + var service = new ConfigService(); + + var ex = await Assert.ThrowsAsync(() => service.LoadConfigBuilderAsync()); + + Assert.Contains("'ShouldIgnoreMVID' setting has been removed", ex.Message, StringComparison.Ordinal); + Assert.Contains("always excluded", ex.Message, StringComparison.Ordinal); + Assert.NotNull(ConfigService.TryGetResolvedConfigFileAbsolutePath(ex)); + }); + } + [Fact] public async Task LoadConfigBuilderAsync_DefaultUserConfigMissing_FallsBackToBundledConfig() { diff --git a/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.Precompute.cs b/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.Precompute.cs index 9f2c8d6b..894313b9 100644 --- a/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.Precompute.cs +++ b/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.Precompute.cs @@ -63,7 +63,6 @@ public async Task DiffDotNetAssembliesAsync_WhenIlTextOutputFails_LogsRelativeAn { var config = new ConfigSettingsBuilder { - ShouldIgnoreMVID = true, IgnoredExtensions = new(), TextFileExtensions = new() }.Build(); @@ -102,7 +101,6 @@ public async Task DiffDotNetAssembliesAsync_WhenOneIlSideStaysEmpty_ThrowsAfterR { var config = new ConfigSettingsBuilder { - ShouldIgnoreMVID = true, IgnoredExtensions = new(), TextFileExtensions = new() }.Build(); @@ -151,7 +149,6 @@ public async Task DiffDotNetAssembliesAsync_WhenRawIlSideRecovers_RetriesAndWrit { var config = new ConfigSettingsBuilder { - ShouldIgnoreMVID = true, IgnoredExtensions = new(), TextFileExtensions = new() }.Build(); @@ -190,7 +187,6 @@ public async Task DiffDotNetAssembliesAsync_WhenFilteredIlSideIsEmpty_LogsWithou { var config = new ConfigSettingsBuilder { - ShouldIgnoreMVID = true, IgnoredExtensions = new(), TextFileExtensions = new() }.Build(); diff --git a/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.cs b/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.cs index 8af16b9e..233f0552 100644 --- a/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.cs +++ b/FolderDiffIL4DotNet.Tests/Services/ILOutputServiceTests.cs @@ -141,7 +141,7 @@ public void SplitAndFilterIlLines_CombinesSplitAndFilter_MatchesSplitThenWhereBe var method = typeof(ILOutputService).GetMethod("SplitAndFilterIlLines", BindingFlags.Static | BindingFlags.NonPublic); Assert.NotNull(method); - var result = (List)method.Invoke(null, new object[] { ilText, false, ignoreStrings, true }); + var result = (List)method.Invoke(null, new object[] { ilText, false, ignoreStrings }); // MVID lines should be excluded; non-MVID lines retained (including empty trailing line from final \n) Assert.DoesNotContain(result, line => line.StartsWith("// MVID:", StringComparison.Ordinal)); @@ -158,7 +158,7 @@ public void SplitAndFilterIlLines_WithConfiguredIgnoreStrings_ExcludesMatchingLi var method = typeof(ILOutputService).GetMethod("SplitAndFilterIlLines", BindingFlags.Static | BindingFlags.NonPublic); Assert.NotNull(method); - var result = (List)method.Invoke(null, new object[] { ilText, true, ignoreStrings, true }); + var result = (List)method.Invoke(null, new object[] { ilText, true, ignoreStrings }); Assert.Equal(new[] { "line1", "line3", "" }, result); } @@ -195,10 +195,9 @@ public async Task PrecomputeAsync_WithCacheDisabled_ReturnsWithoutThrowing() private static bool InvokeShouldExcludeIlLine(string line, bool shouldIgnoreContainingStrings, IReadOnlyCollection ilIgnoreContainingStrings) { - // Pass shouldIgnoreMVID=true as the default to match previous behavior / 従来の動作に合わせて shouldIgnoreMVID=true をデフォルトで渡す var method = typeof(ILOutputService).GetMethod("ShouldExcludeIlLine", BindingFlags.Static | BindingFlags.NonPublic); Assert.NotNull(method); - var result = method.Invoke(null, new object[] { line, shouldIgnoreContainingStrings, ilIgnoreContainingStrings, true }); + var result = method.Invoke(null, new object[] { line, shouldIgnoreContainingStrings, ilIgnoreContainingStrings }); return Assert.IsType(result); } @@ -639,8 +638,8 @@ public void StreamingFilteredSequenceEqual_MatchesSplitAndFilterBehavior() Assert.NotNull(splitAndFilter); var ignoreStrings = new List(); - var legacy1 = (List)splitAndFilter.Invoke(null, new object[] { ilText1, false, ignoreStrings, true })!; - var legacy2 = (List)splitAndFilter.Invoke(null, new object[] { ilText2, false, ignoreStrings, true })!; + var legacy1 = (List)splitAndFilter.Invoke(null, new object[] { ilText1, false, ignoreStrings })!; + var legacy2 = (List)splitAndFilter.Invoke(null, new object[] { ilText2, false, ignoreStrings })!; bool legacyResult = legacy1.SequenceEqual(legacy2); var lines1 = DotNetDisassembleService.SplitToLines(ilText1); @@ -650,29 +649,18 @@ public void StreamingFilteredSequenceEqual_MatchesSplitAndFilterBehavior() Assert.Equal(legacyResult, streamingResult); } - // --- ShouldIgnoreMVID tests / MVID 無視フラグテスト --- + // --- Unconditional MVID exclusion tests --- + // --- MVID 無条件除外テスト --- [Fact] [Trait("Category", "Unit")] - public void StreamingFilteredSequenceEqual_WhenShouldIgnoreMVIDFalse_IncludesMVIDLines() + public void StreamingFilteredSequenceEqual_DifferentMvidValues_ExcludesMvidLines() { - // When ShouldIgnoreMVID is false, MVID lines affect comparison result. - // ShouldIgnoreMVID が false の場合、MVID 行は比較結果に影響する。 + // MVID lines are always excluded from comparison. + // MVID 行は常に比較から除外される。 var lines1 = new List { "// MVID: ABC", "class Foo {", "}" }; var lines2 = new List { "// MVID: XYZ", "class Foo {", "}" }; - var result = ILOutputService.StreamingFilteredSequenceEqual(lines1, lines2, false, new List(), shouldIgnoreMVID: false); - Assert.False(result); - } - - [Fact] - [Trait("Category", "Unit")] - public void StreamingFilteredSequenceEqual_WhenShouldIgnoreMVIDTrue_ExcludesMVIDLines() - { - // Default behavior: MVID lines are excluded from comparison. - // デフォルト動作: MVID 行は比較から除外される。 - var lines1 = new List { "// MVID: ABC", "class Foo {", "}" }; - var lines2 = new List { "// MVID: XYZ", "class Foo {", "}" }; - var result = ILOutputService.StreamingFilteredSequenceEqual(lines1, lines2, false, new List(), shouldIgnoreMVID: true); + var result = ILOutputService.StreamingFilteredSequenceEqual(lines1, lines2, false, new List()); Assert.True(result); } diff --git a/FolderDiffIL4DotNet.Tests/Services/ReportGenerateServiceTests.Header.cs b/FolderDiffIL4DotNet.Tests/Services/ReportGenerateServiceTests.Header.cs index 6347d7c3..701f3be0 100644 --- a/FolderDiffIL4DotNet.Tests/Services/ReportGenerateServiceTests.Header.cs +++ b/FolderDiffIL4DotNet.Tests/Services/ReportGenerateServiceTests.Header.cs @@ -126,25 +126,6 @@ public void GenerateDiffReport_HeaderShowsMvidReasonNote() Assert.Contains("lines starting with \"// MVID:\" (if present) are ignored because they contain disassembler-emitted Module Version ID metadata", reportText); } - [Fact] - public void GenerateDiffReport_WhenShouldIgnoreMVIDFalse_OmitsMvidNote() - { - var oldDir = Path.Combine(_rootDir, "old-mvid-off"); - var newDir = Path.Combine(_rootDir, "new-mvid-off"); - var reportDir = Path.Combine(_rootDir, "report-mvid-off"); - Directory.CreateDirectory(oldDir); - Directory.CreateDirectory(newDir); - Directory.CreateDirectory(reportDir); - - var builder = CreateConfigBuilder(); - builder.ShouldIgnoreMVID = false; - _service.GenerateDiffReport(CreateReportContext(oldDir, newDir, reportDir, builder.Build())); - - var reportPath = Path.Combine(reportDir, "diff_report.md"); - var reportText = File.ReadAllText(reportPath); - Assert.DoesNotContain("// MVID:", reportText); - } - [Fact] public void GenerateDiffReport_IlDiffDetailsIncludeDisassemblerLabel() { @@ -334,4 +315,3 @@ public void GenerateDiffReport_NoMixedWarning_WhenSingleDisassemblerUsed() } } } - diff --git a/Models/ConfigSettings.ILSettings.cs b/Models/ConfigSettings.ILSettings.cs index 6c24cda6..7aed70e8 100644 --- a/Models/ConfigSettings.ILSettings.cs +++ b/Models/ConfigSettings.ILSettings.cs @@ -13,9 +13,6 @@ public sealed partial class ConfigSettings public const bool DefaultShouldIgnoreILLinesContainingConfiguredStrings = false; /// Default value for . / の既定値。 public const bool DefaultSkipIL = false; - /// Default value for . / の既定値。 - public const bool DefaultShouldIgnoreMVID = true; - // ── IL cache defaults / IL キャッシュデフォルト ─────────────────────── /// Default value for . / の既定値。 public const bool DefaultEnableILCache = true; @@ -62,15 +59,6 @@ public sealed partial class ConfigSettings /// public bool SkipIL { get; } - /// - /// Whether to ignore MVID (Module Version ID) lines during IL comparison. - /// When false, MVID differences are included in the comparison, which can detect - /// recompilation even when the source code is identical. - /// IL 比較時に MVID(Module Version ID)行を無視するかどうか。 - /// false の場合、ソースコードが同一でも再コンパイルを検出するために MVID 差異が比較に含まれる。 - /// - public bool ShouldIgnoreMVID { get; } - // ── IL cache properties / IL キャッシュプロパティ ───────────────────── /// diff --git a/Models/ConfigSettings.cs b/Models/ConfigSettings.cs index cdfb9369..34d6a731 100644 --- a/Models/ConfigSettings.cs +++ b/Models/ConfigSettings.cs @@ -103,8 +103,6 @@ internal ConfigSettings(ConfigSettingsBuilder builder) ShouldIgnoreILLinesContainingConfiguredStrings = builder.ShouldIgnoreILLinesContainingConfiguredStrings; ILIgnoreLineContainingStrings = builder.ILIgnoreLineContainingStrings.AsReadOnly(); SkipIL = builder.SkipIL; - ShouldIgnoreMVID = builder.ShouldIgnoreMVID; - // IL cache / IL キャッシュ EnableILCache = builder.EnableILCache; ILCacheDirectoryAbsolutePath = builder.ILCacheDirectoryAbsolutePath; diff --git a/Models/ConfigSettingsBuilder.ILSettings.cs b/Models/ConfigSettingsBuilder.ILSettings.cs index d83a5a06..b863dada 100644 --- a/Models/ConfigSettingsBuilder.ILSettings.cs +++ b/Models/ConfigSettingsBuilder.ILSettings.cs @@ -27,9 +27,6 @@ public List ILIgnoreLineContainingStrings /// public bool SkipIL { get; set; } = ConfigSettings.DefaultSkipIL; - /// - public bool ShouldIgnoreMVID { get; set; } = ConfigSettings.DefaultShouldIgnoreMVID; - // ── IL cache / IL キャッシュ ──────────────────────────────────────── /// diff --git a/Models/ConfigSettingsBuilder.cs b/Models/ConfigSettingsBuilder.cs index c2cba477..a5ef887c 100644 --- a/Models/ConfigSettingsBuilder.cs +++ b/Models/ConfigSettingsBuilder.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; @@ -21,6 +22,9 @@ namespace FolderDiffIL4DotNet.Models /// public sealed partial class ConfigSettingsBuilder { + internal const string REMOVED_SHOULD_IGNORE_MVID_ERROR = + "The 'ShouldIgnoreMVID' setting has been removed. MVID lines are always excluded from IL comparison; remove this setting from the configuration."; + /// /// Captures unmapped JSON properties (e.g. $schema) so that deserialization /// does not fail when the config file contains a schema reference. @@ -30,6 +34,27 @@ public sealed partial class ConfigSettingsBuilder [JsonExtensionData] public Dictionary? ExtensionData { get; set; } + internal bool HasRemovedShouldIgnoreMvidSetting + { + get + { + if (ExtensionData == null) + { + return false; + } + + foreach (string propertyName in ExtensionData.Keys) + { + if (string.Equals(propertyName, "ShouldIgnoreMVID", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + } + private List _ignoredExtensions = ConfigSettings.CreateDefaultIgnoredExtensions(); private List _textFileExtensions = ConfigSettings.CreateDefaultTextFileExtensions(); private List _spinnerFrames = ConfigSettings.CreateDefaultSpinnerFrames(); @@ -70,6 +95,11 @@ public ConfigValidationResult Validate() { var errors = new List(); + if (HasRemovedShouldIgnoreMvidSetting) + { + errors.Add(REMOVED_SHOULD_IGNORE_MVID_ERROR); + } + if (MaxLogGenerations < 1) { errors.Add($"MaxLogGenerations must be 1 or greater (current value: {MaxLogGenerations})."); diff --git a/Models/IReadOnlyConfigSettings.cs b/Models/IReadOnlyConfigSettings.cs index f8705f78..a386b5ca 100644 --- a/Models/IReadOnlyConfigSettings.cs +++ b/Models/IReadOnlyConfigSettings.cs @@ -85,9 +85,6 @@ public interface IReadOnlyConfigSettings /// Whether to skip IL comparison for .NET assemblies. / .NET アセンブリの IL 比較をスキップするかどうか。 bool SkipIL { get; } - /// Whether to ignore MVID lines during IL comparison (default true). / IL 比較時に MVID 行を無視するかどうか(デフォルト true)。 - bool ShouldIgnoreMVID { get; } - // ── IL cache / IL キャッシュ ──────────────────────────────────────── /// Whether to cache IL disassembly results. / IL 逆アセンブル結果をキャッシュするか。 diff --git a/Runner/ProgramRunner.Config.cs b/Runner/ProgramRunner.Config.cs index 4d9362fe..64f93531 100644 --- a/Runner/ProgramRunner.Config.cs +++ b/Runner/ProgramRunner.Config.cs @@ -27,18 +27,18 @@ public sealed partial class ProgramRunner /// private async Task ClearCacheAsync(string? configPath) { - if (Console.IsInputRedirected) - { - Console.Error.WriteLine("--clear-cache requires an interactive terminal (stdin must not be redirected)."); - return (int)ProgramExitCode.InvalidArguments; - } - try { // Resolve cache directory from config (if available) or use default // 設定(利用可能な場合)またはデフォルトからキャッシュディレクトリを解決 string cacheDir = await ResolveCacheDirectoryAsync(configPath); + if (Console.IsInputRedirected) + { + Console.Error.WriteLine("--clear-cache requires an interactive terminal (stdin must not be redirected)."); + return (int)ProgramExitCode.InvalidArguments; + } + if (!Directory.Exists(cacheDir)) { Console.WriteLine($"IL cache directory does not exist: {cacheDir}"); @@ -163,6 +163,12 @@ private async Task ClearCacheAsync(string? configPath) Console.WriteLine($"Cleared {deleted} IL cache file(s) from: {cacheDir}"); return 0; } + catch (InvalidDataException ex) + { + Console.Error.WriteLine( + $"Failed to resolve IL cache configuration for '{GetConfigErrorTarget(configPath, ex)}' ({ex.GetType().Name}): {ex.Message}"); + return (int)ProgramExitCode.ConfigurationError; + } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException || AppDataPaths.IsLocalApplicationDataResolutionFailure(ex)) { @@ -186,7 +192,7 @@ private async Task ResolveCacheDirectoryAsync(string? configPath) : config.ILCacheDirectoryAbsolutePath; } catch (Exception ex) when (ex is ArgumentException or NotSupportedException - or FileNotFoundException or InvalidDataException + or FileNotFoundException or IOException or UnauthorizedAccessException) { return AppDataPaths.GetDefaultIlCacheDirectoryAbsolutePath(); diff --git a/Services/ConfigService.cs b/Services/ConfigService.cs index 82a9aa80..f6221563 100644 --- a/Services/ConfigService.cs +++ b/Services/ConfigService.cs @@ -21,6 +21,7 @@ public sealed class ConfigService " (e.g. remove the comma in \"Key\": \"value\",})."; internal const string ERROR_CONFIG_VALIDATION_PREFIX = "config.json contains invalid settings:"; internal const string ENV_VAR_PREFIX = "FOLDERDIFF_"; + internal const string REMOVED_SHOULD_IGNORE_MVID_ENV_VAR = ENV_VAR_PREFIX + "SHOULDIGNOREMVID"; internal const string RESOLVED_CONFIG_PATH_DATA_KEY = "FolderDiffIL4DotNet.ResolvedConfigFileAbsolutePath"; private readonly Func _bundledConfigPathResolver; @@ -63,6 +64,23 @@ public async Task LoadConfigBuilderAsync(string? configFi configFileAbsolutePath); } + if (builder.HasRemovedShouldIgnoreMvidSetting) + { + throw StampResolvedConfigFileAbsolutePath( + new InvalidDataException( + $"{ConfigSettingsBuilder.REMOVED_SHOULD_IGNORE_MVID_ERROR} File: '{configFileAbsolutePath}'."), + configFileAbsolutePath); + } + + if (Environment.GetEnvironmentVariable(REMOVED_SHOULD_IGNORE_MVID_ENV_VAR) != null) + { + throw StampResolvedConfigFileAbsolutePath( + new InvalidDataException( + $"Environment variable '{REMOVED_SHOULD_IGNORE_MVID_ENV_VAR}' has been removed. " + + "MVID lines are always excluded from IL comparison; remove this environment variable."), + configFileAbsolutePath); + } + ApplyEnvironmentVariableOverrides(builder); return builder; diff --git a/Services/HtmlReport/HtmlReportGenerateService.Sections.cs b/Services/HtmlReport/HtmlReportGenerateService.Sections.cs index ce1ba32c..8b3245c0 100644 --- a/Services/HtmlReport/HtmlReportGenerateService.Sections.cs +++ b/Services/HtmlReport/HtmlReportGenerateService.Sections.cs @@ -70,11 +70,9 @@ private void AppendHeaderSection( } } - // MVID note — only shown when MVID lines are actually ignored / MVID ノート — MVID 行が実際に除外される場合のみ表示 - if (config.ShouldIgnoreMVID) - { - writer.WriteLine($"
{HtmlEncode("IL Diff Note")}
{HtmlEncode("Lines starting with")} {HtmlEncode(Constants.IL_MVID_LINE_PREFIX)} {HtmlEncode("are auto-ignored (Module Version ID metadata).")}
"); - } + // MVID lines are always excluded from IL comparison. + // MVID 行は常に IL 比較から除外します。 + writer.WriteLine($"
{HtmlEncode("IL Diff Note")}
{HtmlEncode("Lines starting with")} {HtmlEncode(Constants.IL_MVID_LINE_PREFIX)} {HtmlEncode("are auto-ignored (Module Version ID metadata).")}
"); writer.WriteLine(""); // report-header } diff --git a/Services/ILOutputService.Comparison.cs b/Services/ILOutputService.Comparison.cs index 9d440cad..107704af 100644 --- a/Services/ILOutputService.Comparison.cs +++ b/Services/ILOutputService.Comparison.cs @@ -29,8 +29,7 @@ internal static bool StreamingFilteredSequenceEqual( IReadOnlyList lines1, IReadOnlyList lines2, bool shouldIgnoreContainingStrings, - IReadOnlyCollection ilIgnoreContainingStrings, - bool shouldIgnoreMVID = true) + IReadOnlyCollection ilIgnoreContainingStrings) { int i = 0; int j = 0; @@ -38,12 +37,12 @@ internal static bool StreamingFilteredSequenceEqual( int count2 = lines2.Count; while (true) { - while (i < count1 && ShouldExcludeIlLine(lines1[i], shouldIgnoreContainingStrings, ilIgnoreContainingStrings, shouldIgnoreMVID)) + while (i < count1 && ShouldExcludeIlLine(lines1[i], shouldIgnoreContainingStrings, ilIgnoreContainingStrings)) { i++; } - while (j < count2 && ShouldExcludeIlLine(lines2[j], shouldIgnoreContainingStrings, ilIgnoreContainingStrings, shouldIgnoreMVID)) + while (j < count2 && ShouldExcludeIlLine(lines2[j], shouldIgnoreContainingStrings, ilIgnoreContainingStrings)) { j++; } @@ -83,13 +82,12 @@ internal static bool StreamingFilteredSequenceEqual( internal static List FilterIlLines( IReadOnlyList lines, bool shouldIgnoreContainingStrings, - IReadOnlyCollection ilIgnoreContainingStrings, - bool shouldIgnoreMVID = true) + IReadOnlyCollection ilIgnoreContainingStrings) { var result = new List(lines.Count); for (int i = 0; i < lines.Count; i++) { - if (!ShouldExcludeIlLine(lines[i], shouldIgnoreContainingStrings, ilIgnoreContainingStrings, shouldIgnoreMVID)) + if (!ShouldExcludeIlLine(lines[i], shouldIgnoreContainingStrings, ilIgnoreContainingStrings)) { result.Add(lines[i]); } @@ -107,8 +105,7 @@ internal static List FilterIlLines( private static List SplitAndFilterIlLines( string ilText, bool shouldIgnoreContainingStrings, - IReadOnlyCollection ilIgnoreContainingStrings, - bool shouldIgnoreMVID = true) + IReadOnlyCollection ilIgnoreContainingStrings) { var result = new List(); int startIndex = 0; @@ -128,7 +125,7 @@ private static List SplitAndFilterIlLines( startIndex = newlineIndex + 1; } - if (!ShouldExcludeIlLine(line, shouldIgnoreContainingStrings, ilIgnoreContainingStrings, shouldIgnoreMVID)) + if (!ShouldExcludeIlLine(line, shouldIgnoreContainingStrings, ilIgnoreContainingStrings)) { result.Add(line); } @@ -144,15 +141,14 @@ private static List SplitAndFilterIlLines( private static bool ShouldExcludeIlLine( string line, bool shouldIgnoreContainingStrings, - IReadOnlyCollection ilIgnoreContainingStrings, - bool shouldIgnoreMVID = true) + IReadOnlyCollection ilIgnoreContainingStrings) { if (line is null) { return false; } - if (shouldIgnoreMVID && line.StartsWith(Constants.IL_MVID_LINE_PREFIX, StringComparison.Ordinal)) + if (line.StartsWith(Constants.IL_MVID_LINE_PREFIX, StringComparison.Ordinal)) { return true; } diff --git a/Services/ILOutputService.cs b/Services/ILOutputService.cs index 9a71333f..fba41f50 100644 --- a/Services/ILOutputService.cs +++ b/Services/ILOutputService.cs @@ -141,7 +141,6 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma var ilIgnoreContainingStrings = GetNormalizedIlIgnoreContainingStrings(_config); bool shouldIgnore = _config.ShouldIgnoreILLinesContainingConfiguredStrings; - bool ignoreMVID = _config.ShouldIgnoreMVID; for (int attemptNumber = 1; attemptNumber <= EMPTY_IL_LINE_SET_DISASSEMBLY_ATTEMPT_LIMIT; attemptNumber++) { @@ -171,7 +170,6 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma shouldOutputIlText, shouldIgnore, ilIgnoreContainingStrings.Count, - ignoreMVID, attemptNumber, EMPTY_IL_LINE_SET_DISASSEMBLY_ATTEMPT_LIMIT, canRetryEmptyLineSet); @@ -190,11 +188,11 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma // If lines differ, fall back to block-aware comparison to handle method reordering. // ストリーミング比較: フィルタ済み行リストを実体化せずに行単位でフィルタ・比較する。 // 行単位で不一致の場合、メソッド並び順変更を考慮しブロック単位比較にフォールバック。 - bool areILsEqual = StreamingFilteredSequenceEqual(il1Lines, il2Lines, shouldIgnore, ilIgnoreContainingStrings, ignoreMVID); + bool areILsEqual = StreamingFilteredSequenceEqual(il1Lines, il2Lines, shouldIgnore, ilIgnoreContainingStrings); if (!areILsEqual) { - var filtered1 = FilterIlLines(il1Lines, shouldIgnore, ilIgnoreContainingStrings, ignoreMVID); - var filtered2 = FilterIlLines(il2Lines, shouldIgnore, ilIgnoreContainingStrings, ignoreMVID); + var filtered1 = FilterIlLines(il1Lines, shouldIgnore, ilIgnoreContainingStrings); + var filtered2 = FilterIlLines(il2Lines, shouldIgnore, ilIgnoreContainingStrings); LogEmptyFilteredLineSetIfNeeded( fileRelativePath, file1AbsolutePath, @@ -208,7 +206,6 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma shouldOutputIlText, shouldIgnore, ilIgnoreContainingStrings.Count, - ignoreMVID, attemptNumber); areILsEqual = BlockAwareSequenceEqual(filtered1, filtered2); @@ -218,8 +215,8 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma // Materialized path: need full filtered lists for IL text file output. // 実体化パス: IL テキストファイル出力用にフィルタ済み全行リストが必要。 - var il1LinesExcluded = FilterIlLines(il1Lines, shouldIgnore, ilIgnoreContainingStrings, ignoreMVID); - var il2LinesExcluded = FilterIlLines(il2Lines, shouldIgnore, ilIgnoreContainingStrings, ignoreMVID); + var il1LinesExcluded = FilterIlLines(il1Lines, shouldIgnore, ilIgnoreContainingStrings); + var il2LinesExcluded = FilterIlLines(il2Lines, shouldIgnore, ilIgnoreContainingStrings); LogEmptyFilteredLineSetIfNeeded( fileRelativePath, file1AbsolutePath, @@ -233,7 +230,6 @@ public async Task PrecomputeAsync(IEnumerable filesAbsolutePaths, int ma shouldOutputIlText, shouldIgnore, ilIgnoreContainingStrings.Count, - ignoreMVID, attemptNumber); bool areEqual = il1LinesExcluded.SequenceEqual(il2LinesExcluded); @@ -277,7 +273,6 @@ private void LogEmptyFilteredLineSetIfNeeded( bool shouldOutputIlText, bool shouldIgnoreContainingStrings, int ignoreStringCount, - bool shouldIgnoreMvid, int attemptNumber) { bool filteredLineSetIsEmpty = !rawLineSetIsEmpty && (filteredOldLineCount == 0 || filteredNewLineCount == 0); @@ -300,7 +295,6 @@ private void LogEmptyFilteredLineSetIfNeeded( shouldOutputIlText, shouldIgnoreContainingStrings, ignoreStringCount, - shouldIgnoreMvid, attemptNumber, EMPTY_IL_LINE_SET_DISASSEMBLY_ATTEMPT_LIMIT, willRetry: false); @@ -320,7 +314,6 @@ private void LogIlLineSetDiagnostics( bool shouldOutputIlText, bool shouldIgnoreContainingStrings, int ignoreStringCount, - bool shouldIgnoreMvid, int attemptNumber, int maxAttemptCount, bool willRetry) @@ -330,7 +323,7 @@ private void LogIlLineSetDiagnostics( : string.Empty; _logger.LogMessage( logLevel, - $"IL comparison {stage} produced an empty line set for '{fileRelativePath}' (Old='{oldFileAbsolutePath}', New='{newFileAbsolutePath}', Disassembler='{disassemblerLabel ?? "(unknown)"}', RawOldLines={rawOldLineCount}, RawNewLines={rawNewLineCount}{filteredCounts}, ShouldOutputIlText={shouldOutputIlText}, IgnoreConfiguredStrings={shouldIgnoreContainingStrings}, IgnoreStringCount={ignoreStringCount}, IgnoreMVID={shouldIgnoreMvid}, Attempt={attemptNumber}/{maxAttemptCount}, WillRetry={willRetry}). Empty IL on one side can later appear as an inline diff skip with 0 vs N lines.", + $"IL comparison {stage} produced an empty line set for '{fileRelativePath}' (Old='{oldFileAbsolutePath}', New='{newFileAbsolutePath}', Disassembler='{disassemblerLabel ?? "(unknown)"}', RawOldLines={rawOldLineCount}, RawNewLines={rawNewLineCount}{filteredCounts}, ShouldOutputIlText={shouldOutputIlText}, IgnoreConfiguredStrings={shouldIgnoreContainingStrings}, IgnoreStringCount={ignoreStringCount}, Attempt={attemptNumber}/{maxAttemptCount}, WillRetry={willRetry}). Empty IL on one side can later appear as an inline diff skip with 0 vs N lines.", shouldOutputMessageToConsole: true); } diff --git a/Services/SectionWriters/HeaderSectionWriter.cs b/Services/SectionWriters/HeaderSectionWriter.cs index 13f16cb1..0fa2ddaa 100644 --- a/Services/SectionWriters/HeaderSectionWriter.cs +++ b/Services/SectionWriters/HeaderSectionWriter.cs @@ -76,13 +76,10 @@ public void Write(StreamWriter writer, ReportWriteContext ctx) // (end of Configuration Details section) writer.WriteLine(); - // Notes — only show MVID note when MVID lines are actually ignored - // ノート — MVID 行が実際に除外される場合のみ MVID ノートを表示 - if (ctx.Config.ShouldIgnoreMVID) - { - writer.WriteLine($"> {NOTE_MVID_SKIP}"); - writer.WriteLine(); - } + // MVID lines are always excluded from IL comparison. + // MVID 行は常に IL 比較から除外します。 + writer.WriteLine($"> {NOTE_MVID_SKIP}"); + writer.WriteLine(); } } diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 1e802414..db2f94d0 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -492,6 +492,7 @@ For one matched pair, the decision order is: Important details: - `Added`, `Removed`, `Unchanged`, and `Modified` are decided by relative path, not by file name alone. - If [`ShouldIgnoreILLinesContainingConfiguredStrings`](#config-en-shouldignoreillinescontainingconfiguredstrings) is `true`, lines containing any configured ignore string are also skipped during IL comparison. +- `ShouldIgnoreMVID` has been removed. If that key or the former `FOLDERDIFF_SHOULDIGNOREMVID` environment variable is specified, nildiff stops with a migration error instead of silently accepting it; remove the obsolete input. MVID lines are always excluded from IL comparison. - If raw disassembly returns an empty line set on one or both sides, `nildiff` retries that old/new pair up to 5 attempts. If any raw side is still empty after the retry limit, the comparison fails with an error instead of writing empty `*_IL.txt` output. - If filtering removes all IL lines on one or both sides after raw disassembly succeeded, `nildiff` logs the empty filtered side but does not retry, because that can be a legitimate result of the configured ignore rules. - If IL comparison itself fails, the run stops instead of silently falling back to a weaker comparison. @@ -640,11 +641,6 @@ Override only the settings you want to change. For example: false Enables additional IL line-ignore filter by substring. - - ShouldIgnoreMVID - true - Whether to exclude MVID (Module Version ID) lines from IL comparison. Set to false to detect recompilation even when source code is identical. - ILIgnoreLineContainingStrings [] @@ -1385,6 +1381,7 @@ flowchart TD 重要な点: - `Added` / `Removed` / `Unchanged` / `Modified` は、ファイル名だけでなく相対パスを基準に決まります。 - [`ShouldIgnoreILLinesContainingConfiguredStrings`](#config-ja-shouldignoreillinescontainingconfiguredstrings) が `true` の場合は、設定した文字列を含む行も IL 比較から除外します。 +- `ShouldIgnoreMVID` は廃止しました。このkeyまたは旧環境変数 `FOLDERDIFF_SHOULDIGNOREMVID` を指定すると、黙って受理せず移行エラーで停止します。廃止済みの指定を削除してください。MVID行は常にIL比較から除外します。 - フィルタ前の raw 逆アセンブル結果が old/new の少なくとも片側で空になった場合、`nildiff` は同じペアを最大 5 回まで再試行します。それでも少なくとも片側が空なら、空の `*_IL.txt` を書かずに error で比較を失敗させます。 - raw 逆アセンブルは成功し、その後のフィルタで少なくとも片側の IL 行がすべて除外された場合は、設定された無視ルールの正当な結果でありえるため、空のフィルタ後行セットをログに残しますが再試行はしません。 - IL 比較そのものに失敗した場合は、弱い比較へ黙って落とさず、その実行全体を停止します。 @@ -1533,11 +1530,6 @@ JSON Schema ファイル([`doc/config.schema.json`](doc/config.schema.json)) false IL 比較時の追加行除外(部分一致)を有効化するか。 - - ShouldIgnoreMVID - true - IL 比較から MVID(Module Version ID)行を除外するかどうか。false にするとソースコードが同一でも再コンパイルを検出できる。 - ILIgnoreLineContainingStrings [] diff --git a/doc/config.sample.jsonc b/doc/config.sample.jsonc index 41b933ce..2412fb5d 100644 --- a/doc/config.sample.jsonc +++ b/doc/config.sample.jsonc @@ -93,11 +93,10 @@ // CLI override: --skip-il "SkipIL": false, - // Whether to ignore MVID (Module Version ID) lines during IL comparison (default: true). - // Set to false to detect recompilation even when source code is identical. - // IL 比較時に MVID 行を無視するかどうか(デフォルト: true)。 - // false にするとソースコード同一でも再コンパイルを検出できる。 - "ShouldIgnoreMVID": true, + // MVID lines are always excluded from IL comparison; no setting is required. + // Removed ShouldIgnoreMVID inputs are rejected with an explicit migration error. + // MVID 行は常に IL 比較から除外されるため、設定は不要。 + // 廃止済みの ShouldIgnoreMVID を指定すると、明示的な移行エラーになる。 // Ignore IL lines containing these strings during comparison (default: false) // 比較時にこれらの文字列を含む IL 行を無視する(デフォルト: false) diff --git a/doc/config.schema.json b/doc/config.schema.json index 6fcd4361..5b64e01d 100644 --- a/doc/config.schema.json +++ b/doc/config.schema.json @@ -113,11 +113,6 @@ "default": true, "description": "Output full IL disassembly text under the active reports root in /