diff --git a/.github/workflows/build-frontends.yml b/.github/workflows/build-frontends.yml index 5f437b3d1f..2ebe5fd40d 100644 --- a/.github/workflows/build-frontends.yml +++ b/.github/workflows/build-frontends.yml @@ -14,10 +14,10 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Setup .NET - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: '8.0.x' + dotnet-quality: 'ga' - name: Install dependencies run: dotnet restore ILSpy.XPlat.slnf @@ -38,7 +38,7 @@ jobs: - name: Upload binlog if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: binlog path: '**/*.binlog' diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index acc6c810cf..444d22b3c6 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -26,8 +26,13 @@ jobs: submodules: true fetch-depth: 0 + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + dotnet-quality: 'ga' + - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.3 + uses: microsoft/setup-msbuild@v2 - name: Install dotnet-format run: dotnet tool install -g dotnet-format --version "6.2.315104" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json @@ -48,12 +53,12 @@ jobs: - name: Execute unit tests run: dotnet test --logger "junit;LogFileName=${{ matrix.configuration }}.xml" --results-directory test-results $env:Tests1 $env:Tests2 $env:Tests3 env: - Tests1: ICSharpCode.Decompiler.Tests\bin\${{ matrix.configuration }}\net6.0-windows\win-x64\ICSharpCode.Decompiler.Tests.dll - Tests2: ILSpy.Tests\bin\${{ matrix.configuration }}\net6.0-windows\ILSpy.Tests.dll - Tests3: ILSpy.BamlDecompiler.Tests\bin\${{ matrix.configuration }}\net6.0-windows\win-x64\ILSpy.BamlDecompiler.Tests.dll + Tests1: ICSharpCode.Decompiler.Tests\bin\${{ matrix.configuration }}\net8.0-windows\win-x64\ICSharpCode.Decompiler.Tests.dll + Tests2: ILSpy.Tests\bin\${{ matrix.configuration }}\net8.0-windows\ILSpy.Tests.dll + Tests3: ILSpy.BamlDecompiler.Tests\bin\${{ matrix.configuration }}\net8.0-windows\win-x64\ILSpy.BamlDecompiler.Tests.dll - name: Upload Test Logs - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: success() || failure() with: name: test-results-${{ matrix.configuration }} @@ -76,7 +81,7 @@ jobs: git diff --exit-code - name: Zip ILSpy (framework-dependent) - run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries.zip .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*.dll .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*.exe .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*.config .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*.json .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*\ILSpy.resources.dll .\ILSpy\bin\${{ matrix.configuration }}\net6.0-windows\*\ILSpy.ReadyToRun.Plugin.resources.dll + run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries.zip .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.dll .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.exe .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.config .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.json .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*\ILSpy.resources.dll .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*\ILSpy.ReadyToRun.Plugin.resources.dll - name: Publish x64/arm64 framework-dependent/self-contained shell: pwsh @@ -84,11 +89,11 @@ jobs: - name: Zip ILSpy Release (x64 self-contained) if: matrix.configuration == 'release' - run: 7z a -tzip $env:StagingDirectory\ILSpy_selfcontained_x64.zip .\ILSpy\bin\Release\net6.0-windows\win-x64\publish\selfcontained\* + run: 7z a -tzip $env:StagingDirectory\ILSpy_selfcontained_x64.zip .\ILSpy\bin\Release\net8.0-windows\win-x64\publish\selfcontained\* - name: Zip ILSpy Release (arm64 framework-dependent) if: matrix.configuration == 'release' - run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries_arm64.zip .\ILSpy\bin\Release\net6.0-windows\win-arm64\publish\fwdependent\* + run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries_arm64.zip .\ILSpy\bin\Release\net8.0-windows\win-arm64\publish\fwdependent\* - name: Build Installer (x64 and arm64, framework-dependent) if: matrix.configuration == 'release' @@ -106,7 +111,7 @@ jobs: # https://github.com/actions/upload-artifact - name: Upload VSIX (VS 2019) release build artifacts if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy VS Addin for VS 2017-2019 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ILSpy.AddIn\bin\${{ matrix.configuration }}\net472\*.vsix @@ -114,7 +119,7 @@ jobs: - name: Upload VSIX (VS 2022) release build artifacts if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy VS Addin for VS 2022 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ILSpy.AddIn.VS2022\bin\${{ matrix.configuration }}\net472\*.vsix @@ -122,7 +127,7 @@ jobs: - name: Upload Decompiler NuGet release build artifacts if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ICSharpCode.Decompiler NuGet Package (${{ matrix.configuration }}) path: ICSharpCode.Decompiler\bin\Release\ICSharpCode.Decompiler*.nupkg @@ -135,7 +140,7 @@ jobs: - name: Upload ILSpyX NuGet release build artifacts if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ICSharpCode.ILSpyX NuGet Package (${{ matrix.configuration }}) path: ICSharpCode.ILSpyX\bin\Release\ICSharpCode.ILSpyX*.nupkg @@ -147,7 +152,7 @@ jobs: dotnet nuget push "ICSharpCode.ILSpyX\bin\Release\ICSharpCode.ILSpyX*.nupkg" --api-key ${{ secrets.GITHUB_TOKEN }} --source https://nuget.pkg.github.com/${{ github.repository_owner }} - name: Upload zip binaries build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ${{ env.StagingDirectory }}\ILSpy_binaries.zip @@ -155,7 +160,7 @@ jobs: - name: Upload x64 self-contained zip (Release-only) if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy self-contained x64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ${{ env.StagingDirectory }}\ILSpy_selfcontained_x64.zip @@ -163,7 +168,7 @@ jobs: - name: Upload arm64 framework-dependent zip (Release-only) if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy arm64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ${{ env.StagingDirectory }}\ILSpy_binaries_arm64.zip @@ -171,7 +176,7 @@ jobs: - name: Upload x64 installer artifact if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy Installer x64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ILSpy.Installer\wix\*-x64.msi @@ -179,7 +184,7 @@ jobs: - name: Upload arm64 installer artifact if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpy Installer arm64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }}) path: ILSpy.Installer\wix\*-arm64.msi @@ -187,7 +192,7 @@ jobs: - name: Upload ilspycmd release build artifacts if: matrix.configuration == 'release' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ilspycmd dotnet tool (${{ matrix.configuration }}) path: ICSharpCode.ILSpyCmd\bin\Release\ilspycmd*.nupkg diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 93daa6d31a..1886a05af7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,17 +23,17 @@ jobs: fetch-depth: 0 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - - name: Setup .NET - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: '8.0.x' + dotnet-quality: 'ga' - name: Build run: dotnet build ILSpy.XPlat.slnf --configuration Release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/generate-bom.yml b/.github/workflows/generate-bom.yml index 12466c03de..5cfafea631 100644 --- a/.github/workflows/generate-bom.yml +++ b/.github/workflows/generate-bom.yml @@ -19,10 +19,10 @@ jobs: run: dotnet tool install --global CycloneDX - name: Analyze - run: dotnet CycloneDX ILSpy/ILSpy.csproj --out sbom --recursive --exclude-dev --exclude-test-projects + run: dotnet-CycloneDX ILSpy/ILSpy.csproj --output sbom --recursive --exclude-dev --exclude-test-projects - name: Upload BOM - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ILSpyBOM.xml path: sbom/bom.xml diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index f3de4cb41f..3bc404b704 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -8,7 +8,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v4.0.1 + - uses: dessant/lock-threads@v5.0.1 with: github-token: ${{ github.token }} issue-inactive-days: '90' diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000000..13e1ebab60 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,47 @@ + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Baml/BamlContext.cs b/ICSharpCode.BamlDecompiler/Baml/BamlContext.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/BamlContext.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlContext.cs index 7f66138c67..21a2e733fc 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlContext.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlContext.cs @@ -30,7 +30,7 @@ THE SOFTWARE. using Metadata = ICSharpCode.Decompiler.Metadata; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal class BamlContext { diff --git a/ILSpy.BamlDecompiler/Baml/BamlDocument.cs b/ICSharpCode.BamlDecompiler/Baml/BamlDocument.cs similarity index 97% rename from ILSpy.BamlDecompiler/Baml/BamlDocument.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlDocument.cs index 6126c003d7..6ed797e9d6 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlDocument.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlDocument.cs @@ -22,7 +22,7 @@ THE SOFTWARE. using System.Collections.Generic; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal class BamlDocument : List { diff --git a/ILSpy.BamlDecompiler/Baml/BamlNode.cs b/ICSharpCode.BamlDecompiler/Baml/BamlNode.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/BamlNode.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlNode.cs index a09c55851b..c8049a668a 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlNode.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlNode.cs @@ -25,7 +25,7 @@ THE SOFTWARE. using System.Diagnostics; using System.Threading; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal abstract class BamlNode { diff --git a/ILSpy.BamlDecompiler/Baml/BamlReader.cs b/ICSharpCode.BamlDecompiler/Baml/BamlReader.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/BamlReader.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlReader.cs index 8f1c6f861f..bed8f934a0 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlReader.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlReader.cs @@ -26,7 +26,7 @@ THE SOFTWARE. using System.Text; using System.Threading; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal class BamlBinaryReader : BinaryReader { diff --git a/ILSpy.BamlDecompiler/Baml/BamlRecords.cs b/ICSharpCode.BamlDecompiler/Baml/BamlRecords.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/BamlRecords.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlRecords.cs index dc64128a2e..f5d514730d 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlRecords.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlRecords.cs @@ -24,7 +24,7 @@ THE SOFTWARE. using System.Diagnostics; using System.IO; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal enum BamlRecordType : byte { diff --git a/ILSpy.BamlDecompiler/Baml/BamlWriter.cs b/ICSharpCode.BamlDecompiler/Baml/BamlWriter.cs similarity index 98% rename from ILSpy.BamlDecompiler/Baml/BamlWriter.cs rename to ICSharpCode.BamlDecompiler/Baml/BamlWriter.cs index f350b8edf2..a95a65c2ae 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlWriter.cs +++ b/ICSharpCode.BamlDecompiler/Baml/BamlWriter.cs @@ -24,7 +24,7 @@ THE SOFTWARE. using System.IO; using System.Text; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal class BamlBinaryWriter : BinaryWriter { diff --git a/ILSpy.BamlDecompiler/Baml/KnownMembers.cs b/ICSharpCode.BamlDecompiler/Baml/KnownMembers.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/KnownMembers.cs rename to ICSharpCode.BamlDecompiler/Baml/KnownMembers.cs index e6b7c4cb38..d70b088e06 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownMembers.cs +++ b/ICSharpCode.BamlDecompiler/Baml/KnownMembers.cs @@ -20,7 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { // Auto generated. Do not modify. diff --git a/ILSpy.BamlDecompiler/Baml/KnownThings.cs b/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs similarity index 97% rename from ILSpy.BamlDecompiler/Baml/KnownThings.cs rename to ICSharpCode.BamlDecompiler/Baml/KnownThings.cs index 746d531950..616d856173 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownThings.cs +++ b/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs @@ -27,7 +27,7 @@ THE SOFTWARE. using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal partial class KnownThings { @@ -59,7 +59,7 @@ public KnownThings(IDecompilerTypeSystem typeSystem) } catch (Exception ex) { - throw new ICSharpCode.Decompiler.DecompilerException(typeSystem.MainModule.PEFile, ex.Message, ex); + throw new ICSharpCode.Decompiler.DecompilerException(typeSystem.MainModule.MetadataFile, ex.Message, ex); } } diff --git a/ILSpy.BamlDecompiler/Baml/KnownThings.g.cs b/ICSharpCode.BamlDecompiler/Baml/KnownThings.g.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/KnownThings.g.cs rename to ICSharpCode.BamlDecompiler/Baml/KnownThings.g.cs index 7cefe0c136..0ff802a8d0 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownThings.g.cs +++ b/ICSharpCode.BamlDecompiler/Baml/KnownThings.g.cs @@ -22,7 +22,7 @@ THE SOFTWARE. using System; -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { internal partial class KnownThings { diff --git a/ILSpy.BamlDecompiler/Baml/KnownThings.gen.cs b/ICSharpCode.BamlDecompiler/Baml/KnownThings.gen.cs similarity index 100% rename from ILSpy.BamlDecompiler/Baml/KnownThings.gen.cs rename to ICSharpCode.BamlDecompiler/Baml/KnownThings.gen.cs diff --git a/ILSpy.BamlDecompiler/Baml/KnownTypes.cs b/ICSharpCode.BamlDecompiler/Baml/KnownTypes.cs similarity index 99% rename from ILSpy.BamlDecompiler/Baml/KnownTypes.cs rename to ICSharpCode.BamlDecompiler/Baml/KnownTypes.cs index 892ef17c52..e0abc8f125 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownTypes.cs +++ b/ICSharpCode.BamlDecompiler/Baml/KnownTypes.cs @@ -20,7 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace ILSpy.BamlDecompiler.Baml +namespace ICSharpCode.BamlDecompiler.Baml { // Auto generated. Do not modify. diff --git a/ILSpy.BamlDecompiler/BamlConnectionId.cs b/ICSharpCode.BamlDecompiler/BamlConnectionId.cs similarity index 97% rename from ILSpy.BamlDecompiler/BamlConnectionId.cs rename to ICSharpCode.BamlDecompiler/BamlConnectionId.cs index 30d11f0cfe..4c9ad1e53f 100644 --- a/ILSpy.BamlDecompiler/BamlConnectionId.cs +++ b/ICSharpCode.BamlDecompiler/BamlConnectionId.cs @@ -22,7 +22,7 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { /// /// Represents a field assignment of a XAML code-behind class. diff --git a/ILSpy.BamlDecompiler/BamlDecompilationResult.cs b/ICSharpCode.BamlDecompiler/BamlDecompilationResult.cs similarity index 98% rename from ILSpy.BamlDecompiler/BamlDecompilationResult.cs rename to ICSharpCode.BamlDecompiler/BamlDecompilationResult.cs index 83e8942ed4..e09a893cd2 100644 --- a/ILSpy.BamlDecompiler/BamlDecompilationResult.cs +++ b/ICSharpCode.BamlDecompiler/BamlDecompilationResult.cs @@ -23,7 +23,7 @@ using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { public class BamlDecompilationResult { diff --git a/ILSpy.BamlDecompiler/BamlDecompilerSettings.cs b/ICSharpCode.BamlDecompiler/BamlDecompilerSettings.cs similarity index 98% rename from ILSpy.BamlDecompiler/BamlDecompilerSettings.cs rename to ICSharpCode.BamlDecompiler/BamlDecompilerSettings.cs index 464298ad09..4f08915607 100644 --- a/ILSpy.BamlDecompiler/BamlDecompilerSettings.cs +++ b/ICSharpCode.BamlDecompiler/BamlDecompilerSettings.cs @@ -19,7 +19,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { public class BamlDecompilerSettings : INotifyPropertyChanged { diff --git a/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs b/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs similarity index 90% rename from ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs rename to ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs index f43a2d28c5..d6072b6a1c 100644 --- a/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs +++ b/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs @@ -26,9 +26,9 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { - class BamlDecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem + public class BamlDecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem { string[] defaultBamlReferences = new[] { "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", @@ -40,7 +40,7 @@ class BamlDecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" }; - public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver) + public BamlDecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver) { if (mainModule == null) throw new ArgumentNullException(nameof(mainModule)); @@ -48,8 +48,8 @@ public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyRes throw new ArgumentNullException(nameof(assemblyResolver)); // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. - var referencedAssemblies = new List(); - var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>(); + var referencedAssemblies = new List(); + var assemblyReferenceQueue = new Queue<(bool IsAssembly, MetadataFile MainModule, object Reference)>(); var mainMetadata = mainModule.Metadata; foreach (var h in mainMetadata.GetModuleReferences()) { @@ -73,16 +73,16 @@ public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyRes { assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference))); } - var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => + var comparer = KeyComparer.Create(((bool IsAssembly, MetadataFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); - var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); + var processedAssemblyReferences = new HashSet<(bool IsAssembly, MetadataFile Parent, object Reference)>(comparer); while (assemblyReferenceQueue.Count > 0) { var asmRef = assemblyReferenceQueue.Dequeue(); if (!processedAssemblyReferences.Add(asmRef)) continue; - PEFile asm; + MetadataFile asm; if (asmRef.IsAssembly) { asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference); diff --git a/ILSpy.BamlDecompiler/BamlElement.cs b/ICSharpCode.BamlDecompiler/BamlElement.cs similarity index 96% rename from ILSpy.BamlDecompiler/BamlElement.cs rename to ICSharpCode.BamlDecompiler/BamlElement.cs index 7728a99fbb..0e546a4748 100644 --- a/ILSpy.BamlDecompiler/BamlElement.cs +++ b/ICSharpCode.BamlDecompiler/BamlElement.cs @@ -23,9 +23,9 @@ THE SOFTWARE. using System.Collections.Generic; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { internal readonly struct XamlNode { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs index d8351f2538..844c825286 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class ConstructorParametersStartHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs index 632769a1b3..8f543271fc 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class DocumentHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/ElementHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/ElementHandler.cs index 418fc8ba87..351fbd3884 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/ElementHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class ElementHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs index 68a543acb5..366b8d93a5 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class KeyElementStartHandler : ElementHandler, IHandler, IDeferHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs index 49dfe1af64..c4b20965f5 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyArrayHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs index ecfb461145..e20ae0155b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyComplexHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs index e6c26c0d03..15a2626803 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyDictionaryHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs index bdc7a114b7..a7041d9cff 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyListHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs index a0b92cb3bc..24c0dfe650 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class AssemblyInfoHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs index 5165648f88..bcada05719 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class AttributeInfoHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs index adc3e23f48..a0b9f9bb1e 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class ConnectionIdHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs index 7f3a603374..a6ba8047ee 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class ConstructorParameterTypeHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs index 5d2cb13aa8..3f95e62dec 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class ContentPropertyHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs index fe54cd63b5..f8ac9786e9 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class DefAttributeHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs index 8cae7decc7..c8df693492 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class DefAttributeStringHandler : IHandler, IDeferHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs index 5bd50e9f6e..82a2d82a0a 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class DefAttributeTypeHandler : IHandler, IDeferHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs index 98a695e166..65385bf1c9 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Diagnostics; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class DeferableContentStartHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs index ea7d68e5f4..6398b2f3e4 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class LineNumberAndPositionHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/LinePositionHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/LinePositionHandler.cs index 25655e218d..feb1c36aa0 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/LinePositionHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class LinePositionHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs index 432aa68c40..f53b3fd5f4 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class LiteralContentHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs similarity index 96% rename from ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs index 53b5a773e9..520392349f 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class OptimizedStaticResourceHandler : IHandler, IDeferHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PIMappingHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PIMappingHandler.cs index 86e12f5761..e32ba8a4ed 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PIMappingHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PIMappingHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs index 849f0a91b3..f4d13ebdb5 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs @@ -22,9 +22,9 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PresentationOptionsAttributeHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs similarity index 97% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs index aca9bfd8ea..c62f2fa4aa 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs @@ -27,10 +27,10 @@ THE SOFTWARE. using System.Text; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyCustomHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyHandler.cs index 913712c4f0..e50002cebb 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs index 51d5b8ae4d..9405d210d3 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs @@ -24,10 +24,10 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyTypeReferenceHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs index ca171f4032..8de1f61bc3 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyWithConverterHandler : PropertyHandler, IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs similarity index 97% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs index 66da034523..034b6aac6b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs @@ -22,10 +22,10 @@ THE SOFTWARE. using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyWithExtensionHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs index 627ec1c8f9..a701316e97 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs @@ -23,10 +23,10 @@ THE SOFTWARE. using System; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class PropertyWithStaticResourceIdHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs index 94e4fc6149..b0f62432c8 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs @@ -18,10 +18,10 @@ using System; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { class StaticResourceIdHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs index 302839a9bd..37857e14e5 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs @@ -20,10 +20,10 @@ using System.Linq; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { class StaticResourceStartHandler : IHandler, IDeferHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/TextHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/TextHandler.cs index 72843f0241..fc41caf5e1 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/TextHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class TextHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs similarity index 93% rename from ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs index 41c34850fb..7b8ad9c18e 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class TextWithConverterHandler : TextHandler, IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs similarity index 94% rename from ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs index 90bbb776fd..583c680d53 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs @@ -20,9 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class TypeInfoHandler : IHandler { diff --git a/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs b/ICSharpCode.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs similarity index 95% rename from ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs rename to ICSharpCode.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs index 777327fcf5..399dd7d4d2 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs +++ b/ICSharpCode.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs @@ -28,10 +28,10 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers +namespace ICSharpCode.BamlDecompiler.Handlers { internal class XmlnsPropertyHandler : IHandler { diff --git a/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj b/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj new file mode 100644 index 0000000000..cd022af4bc --- /dev/null +++ b/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj @@ -0,0 +1,75 @@ + + + + net8.0 + + True + ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk + + en-US + False + False + False + + + + ICSharpCode.BamlDecompiler + 8.0.0.0-noversion + ILSpy BAML Decompiler + ILSpy Contributors + MIT + https://github.com/icsharpcode/ILSpy/ + Cross-Platform library for decompiling BAML. + PackageReadme.md + ic#code + BamlDecompiler + git + https://github.com/icsharpcode/ILSpy.git + ../ICSharpCode.Decompiler/DecompilerNuGetPackageIcon.png + false + Copyright 2024-$([System.DateTime]::Now.Year) AlphaSierraPapa + C# Decompiler ILSpy + + true + embedded + true + true + true + + + + + + + + + + + + + + + + true + + + + + + ILSpyUpdateAssemblyInfo; + $(GetPackageVersionDependsOn) + + + + + + + + + + + + + + diff --git a/ILSpy.BamlDecompiler/IHandlers.cs b/ICSharpCode.BamlDecompiler/IHandlers.cs similarity index 97% rename from ILSpy.BamlDecompiler/IHandlers.cs rename to ICSharpCode.BamlDecompiler/IHandlers.cs index 27db2853ea..c373f0bf26 100644 --- a/ILSpy.BamlDecompiler/IHandlers.cs +++ b/ICSharpCode.BamlDecompiler/IHandlers.cs @@ -24,9 +24,9 @@ THE SOFTWARE. using System.Collections.Generic; using System.Diagnostics; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { internal interface IHandler { diff --git a/ILSpy.BamlDecompiler/IRewritePass.cs b/ICSharpCode.BamlDecompiler/IRewritePass.cs similarity index 96% rename from ILSpy.BamlDecompiler/IRewritePass.cs rename to ICSharpCode.BamlDecompiler/IRewritePass.cs index a139dd4b25..cf0535465d 100644 --- a/ILSpy.BamlDecompiler/IRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/IRewritePass.cs @@ -22,7 +22,7 @@ THE SOFTWARE. using System.Xml.Linq; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { internal interface IRewritePass { diff --git a/ICSharpCode.BamlDecompiler/PackageReadme.md b/ICSharpCode.BamlDecompiler/PackageReadme.md new file mode 100644 index 0000000000..6c0fcf12e7 --- /dev/null +++ b/ICSharpCode.BamlDecompiler/PackageReadme.md @@ -0,0 +1,3 @@ +## About + +ICSharpCode.BamlDecompiler is the library used by the BAML Addin in ILSpy to decompile BAML to XAML. diff --git a/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/AttributeRewritePass.cs similarity index 96% rename from ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs rename to ICSharpCode.BamlDecompiler/Rewrite/AttributeRewritePass.cs index 06139367ed..da4704ef15 100644 --- a/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/AttributeRewritePass.cs @@ -23,9 +23,9 @@ THE SOFTWARE. using System.Collections.Generic; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite +namespace ICSharpCode.BamlDecompiler.Rewrite { internal class AttributeRewritePass : IRewritePass { diff --git a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs similarity index 98% rename from ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs rename to ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs index ba05f6df75..104f6343b7 100644 --- a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs @@ -27,9 +27,9 @@ using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite +namespace ICSharpCode.BamlDecompiler.Rewrite { using ICSharpCode.Decompiler.TypeSystem; @@ -128,7 +128,7 @@ void DecompileConnections(XamlContext ctx, List<(LongSet, FieldAssignment)> fiel IMethod connectMethod = null; MethodDefinition connectMetadataEntry = default; - var module = ctx.TypeSystem.MainModule.PEFile; + var module = ctx.TypeSystem.MainModule.MetadataFile; foreach (IMethod m in type.Methods) { @@ -171,9 +171,7 @@ void DecompileConnections(XamlContext ctx, List<(LongSet, FieldAssignment)> fiel ctx.GeneratedMembers.Add(connectMethod.MetadataToken); - - - var body = module.Reader.GetMethodBody(connectMetadataEntry.RelativeVirtualAddress); + var body = module.GetMethodBody(connectMetadataEntry.RelativeVirtualAddress); var genericContext = new GenericContext( classTypeParameters: connectMethod.DeclaringType?.TypeParameters, methodTypeParameters: connectMethod.TypeParameters); diff --git a/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/DocumentRewritePass.cs similarity index 97% rename from ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs rename to ICSharpCode.BamlDecompiler/Rewrite/DocumentRewritePass.cs index 80849609bd..4e84ac207f 100644 --- a/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/DocumentRewritePass.cs @@ -24,7 +24,7 @@ THE SOFTWARE. using System.Linq; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Rewrite +namespace ICSharpCode.BamlDecompiler.Rewrite { internal class DocumentRewritePass : IRewritePass { diff --git a/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs similarity index 97% rename from ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs rename to ICSharpCode.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs index 46af966472..3df7687530 100644 --- a/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs @@ -21,16 +21,14 @@ THE SOFTWARE. */ using System.Collections.Generic; -using System.DirectoryServices.ActiveDirectory; using System.Linq; -using System.Windows.Forms; using System.Xml.Linq; using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite +namespace ICSharpCode.BamlDecompiler.Rewrite { internal class MarkupExtensionRewritePass : IRewritePass { diff --git a/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/XClassRewritePass.cs similarity index 96% rename from ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs rename to ICSharpCode.BamlDecompiler/Rewrite/XClassRewritePass.cs index 7c4d956c1b..f184995465 100644 --- a/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/XClassRewritePass.cs @@ -23,9 +23,9 @@ THE SOFTWARE. using System.Linq; using System.Xml.Linq; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite +namespace ICSharpCode.BamlDecompiler.Rewrite { internal class XClassRewritePass : IRewritePass { diff --git a/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs b/ICSharpCode.BamlDecompiler/Xaml/NamespaceMap.cs similarity index 97% rename from ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs rename to ICSharpCode.BamlDecompiler/Xaml/NamespaceMap.cs index 290fe8e41e..6523c2be70 100644 --- a/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/NamespaceMap.cs @@ -25,7 +25,7 @@ THE SOFTWARE. using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal class NamespaceMap { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlExtension.cs similarity index 98% rename from ILSpy.BamlDecompiler/Xaml/XamlExtension.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlExtension.cs index 78d8f51765..a39be99d72 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlExtension.cs @@ -24,7 +24,7 @@ THE SOFTWARE. using System.Text; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal class XamlExtension { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlPathDeserializer.cs similarity index 99% rename from ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlPathDeserializer.cs index c23a4e77f3..0ac2c4d413 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlPathDeserializer.cs @@ -25,7 +25,7 @@ THE SOFTWARE. using System.IO; using System.Text; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { class XamlPathDeserializer { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlProperty.cs similarity index 98% rename from ILSpy.BamlDecompiler/Xaml/XamlProperty.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlProperty.cs index a6f3575faf..6372f2a0cf 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlProperty.cs @@ -26,7 +26,7 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal class XamlProperty { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlResourceKey.cs similarity index 97% rename from ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlResourceKey.cs index 5f4288b076..7e642fd05b 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlResourceKey.cs @@ -23,9 +23,9 @@ THE SOFTWARE. using System.Collections.Generic; using System.Diagnostics; -using ILSpy.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal class XamlResourceKey { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlType.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlType.cs similarity index 98% rename from ILSpy.BamlDecompiler/Xaml/XamlType.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlType.cs index b3b7a18d73..f2f9075729 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlType.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlType.cs @@ -25,7 +25,7 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal class XamlType { diff --git a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs b/ICSharpCode.BamlDecompiler/Xaml/XamlUtils.cs similarity index 98% rename from ILSpy.BamlDecompiler/Xaml/XamlUtils.cs rename to ICSharpCode.BamlDecompiler/Xaml/XamlUtils.cs index 878d8214e8..33ae2494a4 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs +++ b/ICSharpCode.BamlDecompiler/Xaml/XamlUtils.cs @@ -24,7 +24,7 @@ THE SOFTWARE. using System.Text; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Xaml +namespace ICSharpCode.BamlDecompiler.Xaml { internal static class XamlUtils { diff --git a/ILSpy.BamlDecompiler/XamlContext.cs b/ICSharpCode.BamlDecompiler/XamlContext.cs similarity index 98% rename from ILSpy.BamlDecompiler/XamlContext.cs rename to ICSharpCode.BamlDecompiler/XamlContext.cs index d9be0620ca..bd24cbeaf5 100644 --- a/ILSpy.BamlDecompiler/XamlContext.cs +++ b/ICSharpCode.BamlDecompiler/XamlContext.cs @@ -29,10 +29,10 @@ THE SOFTWARE. using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { internal class XamlContext { diff --git a/ILSpy.BamlDecompiler/XamlDecompiler.cs b/ICSharpCode.BamlDecompiler/XamlDecompiler.cs similarity index 95% rename from ILSpy.BamlDecompiler/XamlDecompiler.cs rename to ICSharpCode.BamlDecompiler/XamlDecompiler.cs index 0d5c5205c7..2467210aac 100644 --- a/ILSpy.BamlDecompiler/XamlDecompiler.cs +++ b/ICSharpCode.BamlDecompiler/XamlDecompiler.cs @@ -31,10 +31,10 @@ THE SOFTWARE. using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Baml; -using ILSpy.BamlDecompiler.Rewrite; +using ICSharpCode.BamlDecompiler.Baml; +using ICSharpCode.BamlDecompiler.Rewrite; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { public class XamlDecompiler { @@ -72,7 +72,7 @@ public XamlDecompiler(PEFile module, IAssemblyResolver assemblyResolver, BamlDec { } - internal XamlDecompiler(BamlDecompilerTypeSystem typeSystem, BamlDecompilerSettings settings) + public XamlDecompiler(BamlDecompilerTypeSystem typeSystem, BamlDecompilerSettings settings) { this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem)); this.settings = settings; diff --git a/ILSpy.BamlDecompiler/XmlnsDictionary.cs b/ICSharpCode.BamlDecompiler/XmlnsDictionary.cs similarity index 97% rename from ILSpy.BamlDecompiler/XmlnsDictionary.cs rename to ICSharpCode.BamlDecompiler/XmlnsDictionary.cs index 74ada58150..74f7f7f0db 100644 --- a/ILSpy.BamlDecompiler/XmlnsDictionary.cs +++ b/ICSharpCode.BamlDecompiler/XmlnsDictionary.cs @@ -25,9 +25,9 @@ THE SOFTWARE. using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ILSpy.BamlDecompiler.Xaml; +using ICSharpCode.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler +namespace ICSharpCode.BamlDecompiler { internal class XmlnsScope : List { diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs index 9b87d99bee..e94175e80a 100644 --- a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs +++ b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.IO; using System.Management.Automation; using System.Threading; @@ -89,7 +88,7 @@ protected override void ProcessRecord() private void DoDecompile(string path) { - PEFile module = Decompiler.TypeSystem.MainModule.PEFile; + MetadataFile module = Decompiler.TypeSystem.MainModule.MetadataFile; var assemblyResolver = new UniversalAssemblyResolver(module.FileName, false, module.Metadata.DetectTargetFrameworkId()); WholeProjectDecompiler decompiler = new WholeProjectDecompiler(assemblyResolver); decompiler.ProgressIndicator = this; diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj index c50801c161..f5d58901fe 100644 --- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj +++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj @@ -8,11 +8,9 @@ 8.0 - - - - + + diff --git a/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj b/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj index 8c8d40ddc3..af31fefa23 100644 --- a/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj +++ b/ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 enable diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs index ed4a3f2bb2..53cb566c07 100644 --- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs @@ -46,7 +46,7 @@ public void AllFilesHaveTests() if (file.Extension == ".txt" || file.Extension == ".exe" || file.Extension == ".config") continue; var testName = Path.GetFileNameWithoutExtension(file.Name); - Assert.Contains(testName, testNames); + Assert.That(testNames, Has.Member(testName)); } } @@ -336,10 +336,6 @@ public async Task StackTypes([Values(false, true)] bool force32Bit) [Test] public async Task UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions options) { - if (options.HasFlag(CompilerOptions.UseMcs2_6_4)) - { - Assert.Ignore("Decompiler bug with mono!"); - } await RunCS(options: options); } @@ -486,7 +482,7 @@ async Task RunIL(string testFileName, CompilerOptions options = CompilerOptions. bool optionsForce32Bit = options.HasFlag(CompilerOptions.Force32Bit); bool asmOptionsForce32Bit = asmOptions.HasFlag(AssemblerOptions.Force32Bit); - Assert.AreEqual(optionsForce32Bit, asmOptionsForce32Bit, "Inconsistent architecture."); + Assert.That(asmOptionsForce32Bit, Is.EqualTo(optionsForce32Bit), "Inconsistent architecture."); try { diff --git a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs index cfe14be750..7a1c200fa9 100644 --- a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs +++ b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs @@ -45,11 +45,11 @@ public RDTest(ILFunction f, ILVariable v) : base(f, _ => true, CancellationToken protected internal override void VisitTryFinally(TryFinally inst) { - Assert.IsTrue(IsPotentiallyUninitialized(state, v)); + Assert.That(IsPotentiallyUninitialized(state, v)); base.VisitTryFinally(inst); - Assert.IsTrue(state.IsReachable); - Assert.AreEqual(1, GetStores(state, v).Count()); - Assert.IsFalse(IsPotentiallyUninitialized(state, v)); + Assert.That(state.IsReachable); + Assert.That(GetStores(state, v).Count(), Is.EqualTo(1)); + Assert.That(!IsPotentiallyUninitialized(state, v)); } } diff --git a/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs index 9636facc1c..9fa9e7e855 100644 --- a/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs @@ -47,7 +47,7 @@ public void AllFilesHaveTests() if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { var testName = file.Name.Split('.')[0]; - Assert.Contains(testName, testNames); + Assert.That(testNames, Has.Member(testName)); } } } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs index 2c84b6180e..6b8e403e37 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs @@ -133,7 +133,7 @@ public static async Task CompileVB(string sourceFileName, Compi { Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); } - Assert.AreEqual(0, result.ExitCode, "vbc failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "vbc failed"); return results; } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index cd3f185dad..ecbcf5c1b7 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -105,12 +105,19 @@ static Tester() TesterPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location); TestCasePath = Path.Combine(TesterPath, "../../../../TestCases"); #if DEBUG - testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net7.0"); + testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net8.0"); #else - testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net7.0"); + testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net8.0"); #endif - packagesPropsFile = Path.Combine(TesterPath, "../../../../../packages.props"); - roslynLatestVersion = XDocument.Load(packagesPropsFile).XPathSelectElement("//RoslynVersion").Value; + // To parse: + packagesPropsFile = Path.Combine(TesterPath, "../../../../../Directory.Packages.props"); + roslynLatestVersion = ((IEnumerable)(XDocument + .Load(packagesPropsFile) + .XPathEvaluate("//Project//ItemGroup//PackageVersion[@Include='Microsoft.CodeAnalysis.CSharp']/@Version"))) + .OfType() + .Single() + .Value; + roslynToolset = new RoslynToolset(); vswhereToolset = new VsWhereToolset(); } @@ -191,7 +198,7 @@ public static async Task AssembleIL(string sourceFileName, AssemblerOpti { Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); } - Assert.AreEqual(0, result.ExitCode, "ilasm failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "ilasm failed"); return outputFile; } @@ -244,7 +251,7 @@ public static async Task Disassemble(string sourceFileName, string outpu { Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); } - Assert.AreEqual(0, result.ExitCode, "ildasm failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "ildasm failed"); // Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic), // the image base comment still varies... ildasm putting a random number here? @@ -270,8 +277,8 @@ private static string ReplacePrivImplDetails(string il) } static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NET, - new Version(7, 0), "Microsoft.NETCore.App") - .GetReferenceAssemblyPath(".NETCoreApp,Version=v7.0"); + new Version(8, 0), "Microsoft.NETCore.App") + .GetReferenceAssemblyPath(".NETCoreApp,Version=v8.0"); public static readonly string RefAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2"); @@ -309,7 +316,7 @@ private static string ReplacePrivImplDetails(string il) const string targetFrameworkAttributeSnippet = @" -[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v7.0"", FrameworkDisplayName = """")] +[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v8.0"", FrameworkDisplayName = """")] "; @@ -345,6 +352,7 @@ public static List GetPreprocessorSymbols(CompilerOptions flags) preprocessorSymbols.Add("NETCORE"); preprocessorSymbols.Add("NET60"); preprocessorSymbols.Add("NET70"); + preprocessorSymbols.Add("NET80"); } preprocessorSymbols.Add("ROSLYN"); preprocessorSymbols.Add("CS60"); @@ -374,6 +382,7 @@ public static List GetPreprocessorSymbols(CompilerOptions flags) preprocessorSymbols.Add("ROSLYN4"); preprocessorSymbols.Add("CS100"); preprocessorSymbols.Add("CS110"); + preprocessorSymbols.Add("CS120"); } } else if ((flags & CompilerOptions.UseMcsMask) != 0) @@ -511,7 +520,7 @@ public static async Task CompileCSharp(string sourceFileName, C Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); } - Assert.AreEqual(0, result.ExitCode, "csc failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "csc failed"); return results; } @@ -573,7 +582,7 @@ public static async Task CompileCSharp(string sourceFileName, C { Console.WriteLine("errors:" + Environment.NewLine + result.StandardError); } - Assert.AreEqual(0, result.ExitCode, "mcs failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "mcs failed"); return results; } @@ -755,8 +764,8 @@ public static async Task RunAndCompareOutput(string testFileName, string outputF (result2, output2, error2) = await Run(decompiledOutputFile).ConfigureAwait(false); } - Assert.AreEqual(0, result1, "Exit code != 0; did the test case crash?" + Environment.NewLine + error1); - Assert.AreEqual(0, result2, "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2); + Assert.That(result1, Is.EqualTo(0), "Exit code != 0; did the test case crash?" + Environment.NewLine + error1); + Assert.That(result2, Is.EqualTo(0), "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2); if (output1 != output2 || error1 != error2) { @@ -842,7 +851,7 @@ public static async Task SignAssembly(string assemblyPath, string keyFilePath) .WithValidation(CommandResultValidation.None); var result = await command.ExecuteBufferedAsync().ConfigureAwait(false); - Assert.AreEqual(0, result.ExitCode, "sn failed"); + Assert.That(result.ExitCode, Is.EqualTo(0), "sn failed"); if (!string.IsNullOrWhiteSpace(result.StandardOutput)) { diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 8ca93f4916..13c9a3f6b8 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -2,7 +2,7 @@ - net6.0-windows + net8.0-windows win-x64 false AutoGeneratedProgram @@ -17,7 +17,6 @@ false True - True True ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk @@ -41,28 +40,31 @@ TRACE;ROSLYN;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100 - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs index 6a2cc4ed34..04c94d0898 100644 --- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs @@ -45,8 +45,8 @@ public void AllFilesHaveTests() if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { var testName = file.Name.Split('.')[0]; - Assert.Contains(testName, testNames); - Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); + Assert.That(testNames, Has.Member(testName)); + Assert.That(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); } } } diff --git a/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs index f729215c4e..63eec4cd39 100644 --- a/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs +++ b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs @@ -55,7 +55,7 @@ ITypeDefinition GetDefinition(Type type) } var foundType = compilation.FindType(type).GetDefinition(); - Assert.IsNotNull(foundType); + Assert.That(foundType, Is.Not.Null); return foundType; } @@ -76,7 +76,7 @@ public void GenericType(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(Dictionary<,>)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "Object")] @@ -92,7 +92,7 @@ public void SimpleType(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(object)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "IEnumerable")] @@ -104,7 +104,7 @@ public void GenericInterface(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(IEnumerable<>)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "Enumerator")] @@ -121,7 +121,7 @@ public void GenericTypeWithNested(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(List<>.Enumerator)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "StaticClass")] @@ -137,7 +137,7 @@ public void StaticClassTest(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(StaticClass)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "SealedClass")] @@ -153,7 +153,7 @@ public void SealedClassTest(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(SealedClass)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "RefStruct")] @@ -169,7 +169,7 @@ public void RefStructTest(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(RefStruct)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "ReadonlyStruct")] @@ -185,7 +185,7 @@ public void ReadonlyStructTest(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(ReadonlyStruct)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } [TestCase(None, "ReadonlyRefStruct")] @@ -201,7 +201,7 @@ public void ReadonlyRefStructTest(ConversionFlags flags, string expectedOutput) { var typeDef = GetDefinition(typeof(ReadonlyRefStruct)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(typeDef)); + Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput)); } #endregion @@ -219,7 +219,7 @@ public void FuncDelegate(ConversionFlags flags, string expectedOutput) { var func = GetDefinition(typeof(Func<,>)); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(func)); + Assert.That(ambience.ConvertSymbol(func), Is.EqualTo(expectedOutput)); } #endregion @@ -232,7 +232,7 @@ public void SimpleField(ConversionFlags flags, string expectedOutput) var field = GetDefinition(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(field)); + Assert.That(ambience.ConvertSymbol(field), Is.EqualTo(expectedOutput)); } [TestCase(All & ~PlaceReturnTypeAfterParameterList, "private const int ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.Program.TEST2;")] @@ -242,7 +242,7 @@ public void SimpleConstField(ConversionFlags flags, string expectedOutput) var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "TEST2").Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(field)); + Assert.That(ambience.ConvertSymbol(field), Is.EqualTo(expectedOutput)); } #endregion @@ -254,7 +254,7 @@ public void EventWithDeclaringType() ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType; string result = ambience.ConvertSymbol(ev); - Assert.AreEqual("public event EventHandler Program.ProgramChanged;", result); + Assert.That(result, Is.EqualTo("public event EventHandler Program.ProgramChanged;")); } [Test] @@ -264,7 +264,7 @@ public void CustomEvent() ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; string result = ambience.ConvertSymbol(ev); - Assert.AreEqual("public event EventHandler SomeEvent;", result); + Assert.That(result, Is.EqualTo("public event EventHandler SomeEvent;")); } #endregion @@ -276,7 +276,7 @@ public void AutomaticProperty(ConversionFlags flags, string expectedOutput) var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.Name == "Test").Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop)); + Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput)); } [TestCase(StandardConversionFlags, "public int this[int index] { get; }")] @@ -286,7 +286,7 @@ public void Indexer(ConversionFlags flags, string expectedOutput) var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.IsIndexer).Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop)); + Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput)); } #endregion @@ -298,7 +298,7 @@ public void ConstructorTests(ConversionFlags flags, string expectedOutput) var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetConstructors().Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(prop)); + Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput)); } [TestCase(StandardConversionFlags, "~Program();")] @@ -309,7 +309,7 @@ public void DestructorTests(ConversionFlags flags, string expectedOutput) .GetMembers(m => m.SymbolKind == SymbolKind.Destructor, GetMemberOptions.IgnoreInheritedMembers).Single(); ambience.ConversionFlags = flags; - Assert.AreEqual(expectedOutput, ambience.ConvertSymbol(dtor)); + Assert.That(ambience.ConvertSymbol(dtor), Is.EqualTo(expectedOutput)); } #endregion diff --git a/ICSharpCode.Decompiler.Tests/Output/InsertParenthesesVisitorTests.cs b/ICSharpCode.Decompiler.Tests/Output/InsertParenthesesVisitorTests.cs index f9bb5ddef0..0e7a3f3160 100644 --- a/ICSharpCode.Decompiler.Tests/Output/InsertParenthesesVisitorTests.cs +++ b/ICSharpCode.Decompiler.Tests/Output/InsertParenthesesVisitorTests.cs @@ -68,8 +68,8 @@ public void EqualityInAssignment() ) ); - Assert.AreEqual("cond = a == b", InsertRequired(expr)); - Assert.AreEqual("cond = a == b", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("cond = a == b")); + Assert.That(InsertReadable(expr), Is.EqualTo("cond = a == b")); } [Test] @@ -86,8 +86,8 @@ public void LambdaInAssignment() } ); - Assert.AreEqual("p = () => a + b", InsertRequired(expr)); - Assert.AreEqual("p = () => a + b", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("p = () => a + b")); + Assert.That(InsertReadable(expr), Is.EqualTo("p = () => a + b")); } [Test] @@ -105,8 +105,8 @@ public void LambdaInDelegateAdditionRHS() } }; - Assert.AreEqual("p + () => a + b", InsertRequired(expr)); - Assert.AreEqual("p + (() => a + b)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("p + () => a + b")); + Assert.That(InsertReadable(expr), Is.EqualTo("p + (() => a + b)")); } [Test] @@ -124,8 +124,8 @@ public void LambdaInDelegateAdditionLHS() Right = new IdentifierExpression("p"), }; - Assert.AreEqual("(() => a + b) + p", InsertRequired(expr)); - Assert.AreEqual("(() => a + b) + p", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(() => a + b) + p")); + Assert.That(InsertReadable(expr), Is.EqualTo("(() => a + b) + p")); } [Test] @@ -138,8 +138,8 @@ public void TrickyCast1() ) }; - Assert.AreEqual("(int)-a", InsertRequired(expr)); - Assert.AreEqual("(int)(-a)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(int)-a")); + Assert.That(InsertReadable(expr), Is.EqualTo("(int)(-a)")); } [Test] @@ -152,8 +152,8 @@ public void TrickyCast2() ) }; - Assert.AreEqual("(MyType)(-a)", InsertRequired(expr)); - Assert.AreEqual("(MyType)(-a)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(MyType)(-a)")); + Assert.That(InsertReadable(expr), Is.EqualTo("(MyType)(-a)")); } [Test] @@ -166,8 +166,8 @@ public void TrickyCast3() ) }; - Assert.AreEqual("(MyType)!a", InsertRequired(expr)); - Assert.AreEqual("(MyType)(!a)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(MyType)!a")); + Assert.That(InsertReadable(expr), Is.EqualTo("(MyType)(!a)")); } [Test] @@ -178,8 +178,8 @@ public void TrickyCast4() Expression = new PrimitiveExpression(int.MinValue), }; - Assert.AreEqual("(MyType)(-2147483648)", InsertRequired(expr)); - Assert.AreEqual("(MyType)(-2147483648)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(MyType)(-2147483648)")); + Assert.That(InsertReadable(expr), Is.EqualTo("(MyType)(-2147483648)")); } [Test] @@ -190,8 +190,8 @@ public void TrickyCast5() Expression = new PrimitiveExpression(-1.0), }; - Assert.AreEqual("(MyType)(-1.0)", InsertRequired(expr)); - Assert.AreEqual("(MyType)(-1.0)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(MyType)(-1.0)")); + Assert.That(InsertReadable(expr), Is.EqualTo("(MyType)(-1.0)")); } [Test] @@ -202,8 +202,8 @@ public void TrickyCast6() Expression = new PrimitiveExpression(int.MinValue), }; - Assert.AreEqual("(double)-2147483648", InsertRequired(expr)); - Assert.AreEqual("(double)(-2147483648)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(double)-2147483648")); + Assert.That(InsertReadable(expr), Is.EqualTo("(double)(-2147483648)")); } [Test] @@ -217,8 +217,8 @@ public void CastAndInvoke() MemberName = "Length" }; - Assert.AreEqual("((string)a).Length", InsertRequired(expr)); - Assert.AreEqual("((string)a).Length", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("((string)a).Length")); + Assert.That(InsertReadable(expr), Is.EqualTo("((string)a).Length")); } [Test] @@ -229,8 +229,8 @@ public void DoubleNegation() new UnaryOperatorExpression(UnaryOperatorType.Minus, new IdentifierExpression("a")) ); - Assert.AreEqual("- -a", InsertRequired(expr)); - Assert.AreEqual("-(-a)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("- -a")); + Assert.That(InsertReadable(expr), Is.EqualTo("-(-a)")); } [Test] @@ -250,8 +250,8 @@ public void AdditionWithConditional() } }; - Assert.AreEqual("a + (b == null ? c : d)", InsertRequired(expr)); - Assert.AreEqual("a + ((b == null) ? c : d)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a + (b == null ? c : d)")); + Assert.That(InsertReadable(expr), Is.EqualTo("a + ((b == null) ? c : d)")); } [Test] @@ -269,16 +269,16 @@ public void TypeTestInConditional() FalseExpression = new IdentifierExpression("c") }; - Assert.AreEqual("a is int? ? b : c", InsertRequired(expr)); - Assert.AreEqual("(a is int?) ? b : c", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a is int? ? b : c")); + Assert.That(InsertReadable(expr), Is.EqualTo("(a is int?) ? b : c")); policy.SpaceBeforeConditionalOperatorCondition = false; policy.SpaceAfterConditionalOperatorCondition = false; policy.SpaceBeforeConditionalOperatorSeparator = false; policy.SpaceAfterConditionalOperatorSeparator = false; - Assert.AreEqual("a is int? ?b:c", InsertRequired(expr)); - Assert.AreEqual("(a is int?)?b:c", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a is int? ?b:c")); + Assert.That(InsertReadable(expr), Is.EqualTo("(a is int?)?b:c")); } [Test] @@ -302,8 +302,8 @@ public void MethodCallOnQueryExpression() MemberName = "ToArray" }); - Assert.AreEqual("(from a in b select a.c ()).ToArray ()", InsertRequired(expr)); - Assert.AreEqual("(from a in b select a.c ()).ToArray ()", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(from a in b select a.c ()).ToArray ()")); + Assert.That(InsertReadable(expr), Is.EqualTo("(from a in b select a.c ()).ToArray ()")); } [Test] @@ -326,10 +326,10 @@ public void SumOfQueries() query.Clone() ); - Assert.AreEqual("(from a in b select a) + " + - "from a in b select a", InsertRequired(expr)); - Assert.AreEqual("(from a in b select a) + " + - "(from a in b select a)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(from a in b select a) + " + + "from a in b select a")); + Assert.That(InsertReadable(expr), Is.EqualTo("(from a in b select a) + " + + "(from a in b select a)")); } [Test] @@ -350,8 +350,8 @@ public void QueryInTypeTest() Type = new PrimitiveType("int") }; - Assert.AreEqual("(from a in b select a) is int", InsertRequired(expr)); - Assert.AreEqual("(from a in b select a) is int", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(from a in b select a) is int")); + Assert.That(InsertReadable(expr), Is.EqualTo("(from a in b select a) is int")); } [Test] @@ -365,8 +365,8 @@ public void PrePost() ) ); - Assert.AreEqual("++a++", InsertRequired(expr)); - Assert.AreEqual("++(a++)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("++a++")); + Assert.That(InsertReadable(expr), Is.EqualTo("++(a++)")); } [Test] @@ -380,8 +380,8 @@ public void PostPre() ) ); - Assert.AreEqual("(++a)++", InsertRequired(expr)); - Assert.AreEqual("(++a)++", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(++a)++")); + Assert.That(InsertReadable(expr), Is.EqualTo("(++a)++")); } [Test] @@ -397,8 +397,8 @@ public void Logical1() new IdentifierExpression("c") ); - Assert.AreEqual("a && b && c", InsertRequired(expr)); - Assert.AreEqual("a && b && c", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a && b && c")); + Assert.That(InsertReadable(expr), Is.EqualTo("a && b && c")); } [Test] @@ -414,8 +414,8 @@ public void Logical2() ) ); - Assert.AreEqual("a && (b && c)", InsertRequired(expr)); - Assert.AreEqual("a && (b && c)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a && (b && c)")); + Assert.That(InsertReadable(expr), Is.EqualTo("a && (b && c)")); } [Test] @@ -431,8 +431,8 @@ public void Logical3() ) ); - Assert.AreEqual("a || b && c", InsertRequired(expr)); - Assert.AreEqual("a || (b && c)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a || b && c")); + Assert.That(InsertReadable(expr), Is.EqualTo("a || (b && c)")); } [Test] @@ -448,8 +448,8 @@ public void Logical4() ) ); - Assert.AreEqual("a && (b || c)", InsertRequired(expr)); - Assert.AreEqual("a && (b || c)", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("a && (b || c)")); + Assert.That(InsertReadable(expr), Is.EqualTo("a && (b || c)")); } [Test] @@ -463,8 +463,8 @@ public void ArrayCreationInIndexer() Arguments = { new PrimitiveExpression(0) } }; - Assert.AreEqual("(new int[1]) [0]", InsertRequired(expr)); - Assert.AreEqual("(new int[1]) [0]", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("(new int[1]) [0]")); + Assert.That(InsertReadable(expr), Is.EqualTo("(new int[1]) [0]")); } [Test] @@ -481,8 +481,8 @@ public void ArrayCreationWithInitializerInIndexer() Arguments = { new PrimitiveExpression(0) } }; - Assert.AreEqual("new int[1] { 42 } [0]", InsertRequired(expr)); - Assert.AreEqual("(new int[1] { 42 }) [0]", InsertReadable(expr)); + Assert.That(InsertRequired(expr), Is.EqualTo("new int[1] { 42 } [0]")); + Assert.That(InsertReadable(expr), Is.EqualTo("(new int[1] { 42 }) [0]")); } } } diff --git a/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs b/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs index ed8488fa43..48dda98649 100644 --- a/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs @@ -70,8 +70,8 @@ public void CustomPdbId() var metadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); var generatedPdbId = new BlobContentId(metadataReader.DebugMetadataHeader.Id); - Assert.AreEqual(expectedPdbId.Guid, generatedPdbId.Guid); - Assert.AreEqual(expectedPdbId.Stamp, generatedPdbId.Stamp); + Assert.That(generatedPdbId.Guid, Is.EqualTo(expectedPdbId.Guid)); + Assert.That(generatedPdbId.Stamp, Is.EqualTo(expectedPdbId.Stamp)); } } @@ -95,8 +95,8 @@ public void ProgressReporting() totalFiles = progress.TotalUnits; } - Assert.AreEqual(progress.TotalUnits, totalFiles); - Assert.AreEqual(progress.UnitsCompleted, lastFilesWritten + 1); + Assert.That(totalFiles, Is.EqualTo(progress.TotalUnits)); + Assert.That(lastFilesWritten + 1, Is.EqualTo(progress.UnitsCompleted)); lastFilesWritten = progress.UnitsCompleted; }; @@ -111,7 +111,7 @@ public void ProgressReporting() var generatedPdbId = new BlobContentId(metadataReader.DebugMetadataHeader.Id); } - Assert.AreEqual(totalFiles, lastFilesWritten); + Assert.That(lastFilesWritten, Is.EqualTo(totalFiles)); } private class TestProgressReporter : IProgress diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index c341835e0e..4fe48369dd 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -46,7 +46,7 @@ public void AllFilesHaveTests() || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) { var testName = file.Name.Split('.')[0]; - Assert.Contains(testName, testNames); + Assert.That(testNames, Has.Member(testName)); } } } diff --git a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs index c92f49c574..df78e9bc1b 100644 --- a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs +++ b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs @@ -57,8 +57,8 @@ public void VerifyVersion(int version, string expectedVersion) var targetFramework = new TargetFramework(identifier: null, version, profile: null); // Assert - Assert.AreEqual(version, targetFramework.VersionNumber); - Assert.AreEqual(expectedVersion, targetFramework.VersionString); + Assert.That(targetFramework.VersionNumber, Is.EqualTo(version)); + Assert.That(targetFramework.VersionString, Is.EqualTo(expectedVersion)); } [Test] @@ -71,8 +71,8 @@ public void VerifyPortableLibrary() var targetFramework = new TargetFramework(identifier, 100, profile: null); // Assert - Assert.IsTrue(targetFramework.IsPortableClassLibrary); - Assert.AreEqual(identifier, targetFramework.Identifier); + Assert.That(targetFramework.IsPortableClassLibrary); + Assert.That(targetFramework.Identifier, Is.EqualTo(identifier)); } [Test] @@ -87,8 +87,8 @@ public void VerifyIdentifierAndProfile( var targetFramework = new TargetFramework(identifier, 100, profile); // Assert - Assert.AreEqual(identifier, targetFramework.Identifier); - Assert.AreEqual(profile, targetFramework.Profile); + Assert.That(targetFramework.Identifier, Is.EqualTo(identifier)); + Assert.That(targetFramework.Profile, Is.EqualTo(profile)); } [TestCase(null, 350, "net35")] @@ -117,7 +117,7 @@ public void VerifyMoniker(string identifier, int version, string expectedMoniker var targetFramework = new TargetFramework(identifier, version, profile: null); // Assert - Assert.AreEqual(expectedMoniker, targetFramework.Moniker); + Assert.That(targetFramework.Moniker, Is.EqualTo(expectedMoniker)); } } } diff --git a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs index 3a378e2374..3043c92466 100644 --- a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs +++ b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs @@ -212,7 +212,7 @@ async Task RunInternal(string dir, string fileToRoundtrip, Action testAc File.Copy(file, Path.Combine(outputDir, relFile)); } } - Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}"); + Assert.That(projectFile, Is.Not.Null, $"Could not find {fileToRoundtrip}"); await Compile(projectFile, outputDir); testAction(outputDir); @@ -289,8 +289,8 @@ static async Task RunTest(string outputDir, string fileToTest) class TestProjectDecompiler : WholeProjectDecompiler { - public TestProjectDecompiler(Guid projecGuid, IAssemblyResolver resolver, AssemblyReferenceClassifier assemblyReferenceClassifier, DecompilerSettings settings) - : base(settings, projecGuid, resolver, assemblyReferenceClassifier, debugInfoProvider: null) + public TestProjectDecompiler(Guid projectGuid, IAssemblyResolver resolver, AssemblyReferenceClassifier assemblyReferenceClassifier, DecompilerSettings settings) + : base(settings, projectGuid, resolver, null, assemblyReferenceClassifier, debugInfoProvider: null) { } } diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs index a6687124c5..8484cd2665 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs @@ -70,34 +70,34 @@ Conversion ExplicitConversion(Type from, Type to) [Test] public void IdentityConversions() { - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(char), typeof(char))); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(string), typeof(string))); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(object))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(char))); + Assert.That(ImplicitConversion(typeof(char), typeof(char)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(string), typeof(string)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(object), typeof(object)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(bool), typeof(char)), Is.EqualTo(C.None)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.Dynamic, SpecialType.Dynamic)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.UnknownType, SpecialType.UnknownType)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SpecialType.NullType, SpecialType.NullType)); + Assert.That(conversions.ImplicitConversion(SpecialType.Dynamic, SpecialType.Dynamic), Is.EqualTo(C.IdentityConversion)); + Assert.That(conversions.ImplicitConversion(SpecialType.UnknownType, SpecialType.UnknownType), Is.EqualTo(C.IdentityConversion)); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, SpecialType.NullType), Is.EqualTo(C.IdentityConversion)); } [Test] public void DynamicIdentityConversions() { - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(dynamic))); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(dynamic), typeof(object))); + Assert.That(ImplicitConversion(typeof(object), typeof(dynamic)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(dynamic), typeof(object)), Is.EqualTo(C.IdentityConversion)); } [Test] public void ComplexDynamicIdentityConversions() { - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List), typeof(List))); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List), typeof(List))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(List))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(List))); + Assert.That(ImplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.None)); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List[]>), typeof(List[]>))); - Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List[]>), typeof(List[]>))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(List[,]>), typeof(List[]>))); + Assert.That(ImplicitConversion(typeof(List[]>), typeof(List[]>)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(List[]>), typeof(List[]>)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ImplicitConversion(typeof(List[,]>), typeof(List[]>)), Is.EqualTo(C.None)); } [Test] @@ -105,40 +105,38 @@ public void TupleIdentityConversions() { var intType = compilation.FindType(typeof(int)); var stringType = compilation.FindType(typeof(string)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion( + Assert.That(conversions.ImplicitConversion( new TupleType(compilation, ImmutableArray.Create(intType, stringType), ImmutableArray.Create("a", "b")), - new TupleType(compilation, ImmutableArray.Create(intType, stringType), ImmutableArray.Create("a", "c")))); + new TupleType(compilation, ImmutableArray.Create(intType, stringType), ImmutableArray.Create("a", "c"))), Is.EqualTo(C.IdentityConversion)); - Assert.AreEqual(C.None, conversions.ImplicitConversion( + Assert.That(conversions.ImplicitConversion( new TupleType(compilation, ImmutableArray.Create(intType, stringType), ImmutableArray.Create("a", "b")), - new TupleType(compilation, ImmutableArray.Create(stringType, intType), ImmutableArray.Create("a", "b")))); + new TupleType(compilation, ImmutableArray.Create(stringType, intType), ImmutableArray.Create("a", "b"))), Is.EqualTo(C.None)); } [Test] public void TupleConversions() { - Assert.AreEqual( - C.TupleConversion(ImmutableArray.Create(C.ImplicitNumericConversion, C.ImplicitReferenceConversion)), - ImplicitConversion(typeof((int, string)), typeof((long, object)))); + Assert.That( + ImplicitConversion(typeof((int, string)), typeof((long, object))), Is.EqualTo(C.TupleConversion(ImmutableArray.Create(C.ImplicitNumericConversion, C.ImplicitReferenceConversion)))); - Assert.AreEqual( - C.TupleConversion(ImmutableArray.Create(C.ImplicitNumericConversion)), - ImplicitConversion(typeof(ValueTuple), typeof(ValueTuple))); + Assert.That( + ImplicitConversion(typeof(ValueTuple), typeof(ValueTuple)), Is.EqualTo(C.TupleConversion(ImmutableArray.Create(C.ImplicitNumericConversion)))); } [Test] public void PrimitiveConversions() { - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(char), typeof(ushort))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(byte), typeof(char))); - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(int), typeof(long))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(long), typeof(int))); - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(int), typeof(float))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(float))); - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(float), typeof(double))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(float), typeof(decimal))); - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(char), typeof(long))); - Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(uint), typeof(long))); + Assert.That(ImplicitConversion(typeof(char), typeof(ushort)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ImplicitConversion(typeof(byte), typeof(char)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int), typeof(long)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ImplicitConversion(typeof(long), typeof(int)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int), typeof(float)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ImplicitConversion(typeof(bool), typeof(float)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(float), typeof(double)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ImplicitConversion(typeof(float), typeof(decimal)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(char), typeof(long)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ImplicitConversion(typeof(uint), typeof(long)), Is.EqualTo(C.ImplicitNumericConversion)); } [Test] @@ -147,64 +145,64 @@ public void EnumerationConversion() ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0); ResolveResult one = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1); C implicitEnumerationConversion = C.EnumerationConversion(true, false); - Assert.AreEqual(implicitEnumerationConversion, conversions.ImplicitConversion(zero, compilation.FindType(typeof(StringComparison)))); - Assert.AreEqual(C.None, conversions.ImplicitConversion(one, compilation.FindType(typeof(StringComparison)))); + Assert.That(conversions.ImplicitConversion(zero, compilation.FindType(typeof(StringComparison))), Is.EqualTo(implicitEnumerationConversion)); + Assert.That(conversions.ImplicitConversion(one, compilation.FindType(typeof(StringComparison))), Is.EqualTo(C.None)); } [Test] public void NullableConversions() { - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(char), typeof(ushort?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(byte), typeof(char?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(int), typeof(long?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(long), typeof(int?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(int), typeof(float?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(float?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(float), typeof(double?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(float), typeof(decimal?))); + Assert.That(ImplicitConversion(typeof(char), typeof(ushort?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(byte), typeof(char?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int), typeof(long?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(long), typeof(int?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int), typeof(float?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(bool), typeof(float?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(float), typeof(double?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(float), typeof(decimal?)), Is.EqualTo(C.None)); } [Test] public void NullableConversions2() { - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(char?), typeof(ushort?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(byte?), typeof(char?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(int?), typeof(long?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(long?), typeof(int?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(int?), typeof(float?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(bool?), typeof(float?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ImplicitConversion(typeof(float?), typeof(double?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(float?), typeof(decimal?))); + Assert.That(ImplicitConversion(typeof(char?), typeof(ushort?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(byte?), typeof(char?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int?), typeof(long?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(long?), typeof(int?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int?), typeof(float?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(bool?), typeof(float?)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(float?), typeof(double?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ImplicitConversion(typeof(float?), typeof(decimal?)), Is.EqualTo(C.None)); } [Test] public void NullLiteralConversions() { - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(int?))); - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(char?))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(Null), typeof(int))); - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(object))); - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(dynamic))); - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(string))); - Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(int[]))); + Assert.That(ImplicitConversion(typeof(Null), typeof(int?)), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(ImplicitConversion(typeof(Null), typeof(char?)), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(ImplicitConversion(typeof(Null), typeof(int)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(Null), typeof(object)), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(ImplicitConversion(typeof(Null), typeof(dynamic)), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(ImplicitConversion(typeof(Null), typeof(string)), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(ImplicitConversion(typeof(Null), typeof(int[])), Is.EqualTo(C.NullLiteralConversion)); } [Test] public void SimpleReferenceConversions() { - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(object))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(BitArray), typeof(ICollection))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(IList), typeof(IEnumerable))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(object), typeof(string))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(ICollection), typeof(BitArray))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(IEnumerable), typeof(IList))); + Assert.That(ImplicitConversion(typeof(string), typeof(object)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(BitArray), typeof(ICollection)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(IList), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(object), typeof(string)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(ICollection), typeof(BitArray)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(IEnumerable), typeof(IList)), Is.EqualTo(C.None)); } [Test] public void ConversionToDynamic() { - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(dynamic))); - Assert.AreEqual(C.BoxingConversion, ImplicitConversion(typeof(int), typeof(dynamic))); + Assert.That(ImplicitConversion(typeof(string), typeof(dynamic)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(int), typeof(dynamic)), Is.EqualTo(C.BoxingConversion)); } [Test] @@ -213,177 +211,164 @@ public void ConversionFromDynamic() // There is no conversion from the type 'dynamic' to other types (except the identity conversion to object). // Such conversions only exists from dynamic expression. // This is an important distinction for type inference (see TypeInferenceTests.IEnumerableCovarianceWithDynamic) - Assert.AreEqual(C.None, ImplicitConversion(typeof(dynamic), typeof(string))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(dynamic), typeof(int))); + Assert.That(ImplicitConversion(typeof(dynamic), typeof(string)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(dynamic), typeof(int)), Is.EqualTo(C.None)); var dynamicRR = new ResolveResult(SpecialType.Dynamic); - Assert.AreEqual(C.ImplicitDynamicConversion, conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(string)))); - Assert.AreEqual(C.ImplicitDynamicConversion, conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(int)))); + Assert.That(conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(string))), Is.EqualTo(C.ImplicitDynamicConversion)); + Assert.That(conversions.ImplicitConversion(dynamicRR, compilation.FindType(typeof(int))), Is.EqualTo(C.ImplicitDynamicConversion)); } [Test] public void ParameterizedTypeConversions() { - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(List), typeof(ICollection))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(IList), typeof(ICollection))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(ICollection))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(IList), typeof(ICollection))); + Assert.That(ImplicitConversion(typeof(List), typeof(ICollection)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(IList), typeof(ICollection)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(List), typeof(ICollection)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(IList), typeof(ICollection)), Is.EqualTo(C.None)); } [Test] public void ArrayConversions() { - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(object[]))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[,]), typeof(object[,]))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(string[]), typeof(object[,]))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(object[]), typeof(string[]))); + Assert.That(ImplicitConversion(typeof(string[]), typeof(object[])), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(string[,]), typeof(object[,])), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(string[]), typeof(object[,])), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(object[]), typeof(string[])), Is.EqualTo(C.None)); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(IList))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(string[,]), typeof(IList))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(IList))); + Assert.That(ImplicitConversion(typeof(string[]), typeof(IList)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(string[,]), typeof(IList)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(string[]), typeof(IList)), Is.EqualTo(C.ImplicitReferenceConversion)); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(Array))); - Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(ICloneable))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(Array), typeof(string[]))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(object), typeof(object[]))); + Assert.That(ImplicitConversion(typeof(string[]), typeof(Array)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(string[]), typeof(ICloneable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(Array), typeof(string[])), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(object), typeof(object[])), Is.EqualTo(C.None)); } [Test] public void VarianceConversions() { - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.AreEqual(C.None, - ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.AreEqual(C.None, - ImplicitConversion(typeof(ICollection), typeof(ICollection))); - - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(Comparer), typeof(IComparer))); - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(Comparer), typeof(IComparer))); - Assert.AreEqual(C.None, - ImplicitConversion(typeof(Comparer), typeof(Comparer))); - - Assert.AreEqual(C.None, - ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.ImplicitReferenceConversion, - ImplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.None, - ImplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.None, - ImplicitConversion(typeof(Func), typeof(Func))); + Assert.That(ImplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(ICollection), typeof(ICollection)), Is.EqualTo(C.None)); + + Assert.That(ImplicitConversion(typeof(Comparer), typeof(IComparer)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(Comparer), typeof(IComparer)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(Comparer), typeof(Comparer)), Is.EqualTo(C.None)); + + Assert.That(ImplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + + Assert.That(ImplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ImplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.None)); } [Test] public void ImplicitPointerConversion() { - Assert.AreEqual(C.ImplicitPointerConversion, ImplicitConversion(typeof(Null), typeof(int*))); - Assert.AreEqual(C.ImplicitPointerConversion, ImplicitConversion(typeof(int*), typeof(void*))); + Assert.That(ImplicitConversion(typeof(Null), typeof(int*)), Is.EqualTo(C.ImplicitPointerConversion)); + Assert.That(ImplicitConversion(typeof(int*), typeof(void*)), Is.EqualTo(C.ImplicitPointerConversion)); } [Test] public void NoConversionFromPointerTypeToObject() { - Assert.AreEqual(C.None, ImplicitConversion(typeof(int*), typeof(object))); - Assert.AreEqual(C.None, ImplicitConversion(typeof(int*), typeof(dynamic))); + Assert.That(ImplicitConversion(typeof(int*), typeof(object)), Is.EqualTo(C.None)); + Assert.That(ImplicitConversion(typeof(int*), typeof(dynamic)), Is.EqualTo(C.None)); } [Test] public void ConversionToNInt() { // Test based on the table in https://github.com/dotnet/csharplang/blob/master/proposals/native-integers.md - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(nint))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(void*), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(short), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(ushort), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(int), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(uint), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(long), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(ulong), typeof(nint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(char), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(float), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(decimal), typeof(nint))); - Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(IntPtr), typeof(nint))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(UIntPtr), typeof(nint))); + Assert.That(ExplicitConversion(typeof(object), typeof(nint)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(void*), typeof(nint)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(sbyte), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(byte), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(short), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(ushort), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(uint), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(long), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(ulong), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(char), typeof(nint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(float), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(double), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(decimal), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(IntPtr), typeof(nint)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ExplicitConversion(typeof(UIntPtr), typeof(nint)), Is.EqualTo(C.None)); } [Test] public void ConversionToNUInt() { // Test based on the table in https://github.com/dotnet/csharplang/blob/master/proposals/native-integers.md - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(nuint))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(void*), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(nuint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(short), typeof(nuint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(ushort), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(int), typeof(nuint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(uint), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(long), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(ulong), typeof(nuint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(char), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(float), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(decimal), typeof(nuint))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IntPtr), typeof(nuint))); - Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(UIntPtr), typeof(nuint))); + Assert.That(ExplicitConversion(typeof(object), typeof(nuint)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(void*), typeof(nuint)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(sbyte), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(byte), typeof(nuint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(short), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(ushort), typeof(nuint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(uint), typeof(nuint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(long), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(ulong), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(char), typeof(nuint)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(float), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(double), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(decimal), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(IntPtr), typeof(nuint)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(UIntPtr), typeof(nuint)), Is.EqualTo(C.IdentityConversion)); } [Test] public void ConversionFromNInt() { // Test based on the table in https://github.com/dotnet/csharplang/blob/master/proposals/native-integers.md - Assert.AreEqual(C.BoxingConversion, ExplicitConversion(typeof(nint), typeof(object))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(nint), typeof(void*))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(nuint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(sbyte))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(byte))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(short))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(ushort))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(int))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(uint))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(long))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(ulong))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(char))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(float))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(double))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nint), typeof(decimal))); - Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(nint), typeof(IntPtr))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(nint), typeof(UIntPtr))); + Assert.That(ExplicitConversion(typeof(nint), typeof(object)), Is.EqualTo(C.BoxingConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(void*)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(nuint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(sbyte)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(byte)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(short)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(ushort)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(int)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(uint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(long)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(ulong)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(char)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(float)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(double)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(decimal)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(IntPtr)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ExplicitConversion(typeof(nint), typeof(UIntPtr)), Is.EqualTo(C.None)); } [Test] public void ConversionFromNUInt() { // Test based on the table in https://github.com/dotnet/csharplang/blob/master/proposals/native-integers.md - Assert.AreEqual(C.BoxingConversion, ExplicitConversion(typeof(nuint), typeof(object))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(nuint), typeof(void*))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(nint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(sbyte))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(byte))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(short))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(ushort))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(int))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(uint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(long))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(ulong))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(char))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(float))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(double))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(nuint), typeof(decimal))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(nuint), typeof(IntPtr))); - Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(nuint), typeof(UIntPtr))); + Assert.That(ExplicitConversion(typeof(nuint), typeof(object)), Is.EqualTo(C.BoxingConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(void*)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(nint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(sbyte)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(byte)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(short)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(ushort)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(int)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(uint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(long)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(ulong)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(char)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(float)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(double)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(decimal)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(IntPtr)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(UIntPtr)), Is.EqualTo(C.IdentityConversion)); } @@ -391,29 +376,29 @@ public void ConversionFromNUInt() public void NIntEnumConversion() { var explicitEnumConversion = C.EnumerationConversion(isImplicit: false, isLifted: false); - Assert.AreEqual(explicitEnumConversion, ExplicitConversion(typeof(nint), typeof(StringComparison))); - Assert.AreEqual(explicitEnumConversion, ExplicitConversion(typeof(nuint), typeof(StringComparison))); - Assert.AreEqual(explicitEnumConversion, ExplicitConversion(typeof(StringComparison), typeof(nint))); - Assert.AreEqual(explicitEnumConversion, ExplicitConversion(typeof(StringComparison), typeof(nuint))); + Assert.That(ExplicitConversion(typeof(nint), typeof(StringComparison)), Is.EqualTo(explicitEnumConversion)); + Assert.That(ExplicitConversion(typeof(nuint), typeof(StringComparison)), Is.EqualTo(explicitEnumConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(nint)), Is.EqualTo(explicitEnumConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(nuint)), Is.EqualTo(explicitEnumConversion)); } [Test] public void IntegerLiteralToNIntConversions() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(nint))); - Assert.IsTrue(IntegerLiteralConversion(-1, typeof(nint))); - Assert.IsFalse(IntegerLiteralConversion(uint.MaxValue, typeof(nint))); - Assert.IsFalse(IntegerLiteralConversion(long.MaxValue, typeof(nint))); + Assert.That(IntegerLiteralConversion(0, typeof(nint))); + Assert.That(IntegerLiteralConversion(-1, typeof(nint))); + Assert.That(!IntegerLiteralConversion(uint.MaxValue, typeof(nint))); + Assert.That(!IntegerLiteralConversion(long.MaxValue, typeof(nint))); } [Test] public void IntegerLiteralToNUIntConversions() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(nuint))); - Assert.IsFalse(IntegerLiteralConversion(-1, typeof(nuint))); - Assert.IsTrue(IntegerLiteralConversion(uint.MaxValue, typeof(nuint))); - Assert.IsFalse(IntegerLiteralConversion(long.MaxValue, typeof(nuint))); + Assert.That(IntegerLiteralConversion(0, typeof(nuint))); + Assert.That(!IntegerLiteralConversion(-1, typeof(nuint))); + Assert.That(IntegerLiteralConversion(uint.MaxValue, typeof(nuint))); + Assert.That(!IntegerLiteralConversion(long.MaxValue, typeof(nuint))); } [Test] @@ -423,16 +408,16 @@ public void UnconstrainedTypeParameter() ITypeParameter t2 = new DefaultTypeParameter(compilation, SymbolKind.TypeDefinition, 1, "T2"); ITypeParameter tm = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "TM"); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, t), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, SpecialType.Dynamic), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))), Is.EqualTo(C.None)); - Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(t, t)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t2, t)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, t2)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, tm)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(tm, t)); + Assert.That(conversions.ImplicitConversion(t, t), Is.EqualTo(C.IdentityConversion)); + Assert.That(conversions.ImplicitConversion(t2, t), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, t2), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, tm), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(tm, t), Is.EqualTo(C.None)); } [Test] @@ -440,10 +425,10 @@ public void TypeParameterWithReferenceTypeConstraint() { ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.TypeDefinition, 0, "T", hasReferenceTypeConstraint: true); - Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SpecialType.NullType, t)); - Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); - Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, t), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, SpecialType.Dynamic), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))), Is.EqualTo(C.None)); } [Test] @@ -451,10 +436,10 @@ public void TypeParameterWithValueTypeConstraint() { ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.TypeDefinition, 0, "T", hasValueTypeConstraint: true); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic)); - Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, t), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, SpecialType.Dynamic), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))), Is.EqualTo(C.BoxingConversion)); } [Test] @@ -463,20 +448,14 @@ public void TypeParameterWithClassConstraint() ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.TypeDefinition, 0, "T", constraints: new[] { compilation.FindType(typeof(StringComparer)) }); - Assert.AreEqual(C.NullLiteralConversion, - conversions.ImplicitConversion(SpecialType.NullType, t)); - Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); - Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, SpecialType.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); - Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, compilation.FindType(typeof(StringComparer)))); - Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); - Assert.AreEqual(C.ImplicitReferenceConversion, - conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer)))); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, t), Is.EqualTo(C.NullLiteralConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, SpecialType.Dynamic), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(StringComparer))), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer))), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer))), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer))), Is.EqualTo(C.ImplicitReferenceConversion)); } [Test] @@ -485,26 +464,22 @@ public void TypeParameterWithInterfaceConstraint() ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.TypeDefinition, 0, "T", constraints: new[] { compilation.FindType(typeof(IList)) }); - Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t)); - Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object))); - Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, SpecialType.Dynamic)); - Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType)))); - Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, compilation.FindType(typeof(IList)))); - Assert.AreEqual(C.BoxingConversion, - conversions.ImplicitConversion(t, compilation.FindType(typeof(IEnumerable)))); + Assert.That(conversions.ImplicitConversion(SpecialType.NullType, t), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, SpecialType.Dynamic), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))), Is.EqualTo(C.None)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(IList))), Is.EqualTo(C.BoxingConversion)); + Assert.That(conversions.ImplicitConversion(t, compilation.FindType(typeof(IEnumerable))), Is.EqualTo(C.BoxingConversion)); } [Test] public void UserDefinedImplicitConversion() { Conversion c = ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset)); - Assert.IsTrue(c.IsImplicit && c.IsUserDefined); - Assert.AreEqual("System.DateTimeOffset.op_Implicit", c.Method.FullName); + Assert.That(c.IsImplicit && c.IsUserDefined); + Assert.That(c.Method.FullName, Is.EqualTo("System.DateTimeOffset.op_Implicit")); - Assert.AreEqual(C.None, ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime))); + Assert.That(ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime)), Is.EqualTo(C.None)); } [Test] @@ -512,14 +487,14 @@ public void UserDefinedImplicitNullableConversion() { // User-defined conversion followed by nullable conversion Conversion c = ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset?)); - Assert.IsTrue(c.IsValid && c.IsUserDefined); - Assert.IsFalse(c.IsLifted); + Assert.That(c.IsValid && c.IsUserDefined); + Assert.That(!c.IsLifted); // Lifted user-defined conversion c = ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset?)); - Assert.IsTrue(c.IsValid && c.IsUserDefined && c.IsLifted); + Assert.That(c.IsValid && c.IsUserDefined && c.IsLifted); // User-defined conversion doesn't drop the nullability c = ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset)); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } bool IntegerLiteralConversion(object value, Type to) @@ -533,71 +508,71 @@ bool IntegerLiteralConversion(object value, Type to) [Test] public void IntegerLiteralToEnumConversions() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization))); - Assert.IsTrue(IntegerLiteralConversion(0L, typeof(LoaderOptimization))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization?))); - Assert.IsFalse(IntegerLiteralConversion(0, typeof(string))); - Assert.IsFalse(IntegerLiteralConversion(1, typeof(LoaderOptimization))); + Assert.That(IntegerLiteralConversion(0, typeof(LoaderOptimization))); + Assert.That(IntegerLiteralConversion(0L, typeof(LoaderOptimization))); + Assert.That(IntegerLiteralConversion(0, typeof(LoaderOptimization?))); + Assert.That(!IntegerLiteralConversion(0, typeof(string))); + Assert.That(!IntegerLiteralConversion(1, typeof(LoaderOptimization))); } [Test] public void ImplicitConstantExpressionConversion() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(int))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(ushort))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(sbyte))); + Assert.That(IntegerLiteralConversion(0, typeof(int))); + Assert.That(IntegerLiteralConversion(0, typeof(ushort))); + Assert.That(IntegerLiteralConversion(0, typeof(sbyte))); - Assert.IsTrue(IntegerLiteralConversion(-1, typeof(int))); - Assert.IsFalse(IntegerLiteralConversion(-1, typeof(ushort))); - Assert.IsTrue(IntegerLiteralConversion(-1, typeof(sbyte))); + Assert.That(IntegerLiteralConversion(-1, typeof(int))); + Assert.That(!IntegerLiteralConversion(-1, typeof(ushort))); + Assert.That(IntegerLiteralConversion(-1, typeof(sbyte))); - Assert.IsTrue(IntegerLiteralConversion(200, typeof(int))); - Assert.IsTrue(IntegerLiteralConversion(200, typeof(ushort))); - Assert.IsFalse(IntegerLiteralConversion(200, typeof(sbyte))); + Assert.That(IntegerLiteralConversion(200, typeof(int))); + Assert.That(IntegerLiteralConversion(200, typeof(ushort))); + Assert.That(!IntegerLiteralConversion(200, typeof(sbyte))); } [Test] public void ImplicitLongConstantExpressionConversion() { - Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int))); - Assert.IsFalse(IntegerLiteralConversion(0L, typeof(short))); - Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long))); - Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong))); + Assert.That(!IntegerLiteralConversion(0L, typeof(int))); + Assert.That(!IntegerLiteralConversion(0L, typeof(short))); + Assert.That(IntegerLiteralConversion(0L, typeof(long))); + Assert.That(IntegerLiteralConversion(0L, typeof(ulong))); - Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long))); - Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong))); + Assert.That(IntegerLiteralConversion(-1L, typeof(long))); + Assert.That(!IntegerLiteralConversion(-1L, typeof(ulong))); } [Test] public void ImplicitConstantExpressionConversionToNullable() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(uint?))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(short?))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(byte?))); + Assert.That(IntegerLiteralConversion(0, typeof(uint?))); + Assert.That(IntegerLiteralConversion(0, typeof(short?))); + Assert.That(IntegerLiteralConversion(0, typeof(byte?))); - Assert.IsFalse(IntegerLiteralConversion(-1, typeof(uint?))); - Assert.IsTrue(IntegerLiteralConversion(-1, typeof(short?))); - Assert.IsFalse(IntegerLiteralConversion(-1, typeof(byte?))); + Assert.That(!IntegerLiteralConversion(-1, typeof(uint?))); + Assert.That(IntegerLiteralConversion(-1, typeof(short?))); + Assert.That(!IntegerLiteralConversion(-1, typeof(byte?))); - Assert.IsTrue(IntegerLiteralConversion(200, typeof(uint?))); - Assert.IsTrue(IntegerLiteralConversion(200, typeof(short?))); - Assert.IsTrue(IntegerLiteralConversion(200, typeof(byte?))); + Assert.That(IntegerLiteralConversion(200, typeof(uint?))); + Assert.That(IntegerLiteralConversion(200, typeof(short?))); + Assert.That(IntegerLiteralConversion(200, typeof(byte?))); - Assert.IsFalse(IntegerLiteralConversion(0L, typeof(uint?))); - Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long?))); - Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong?))); + Assert.That(!IntegerLiteralConversion(0L, typeof(uint?))); + Assert.That(IntegerLiteralConversion(0L, typeof(long?))); + Assert.That(IntegerLiteralConversion(0L, typeof(ulong?))); - Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long?))); - Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong?))); + Assert.That(IntegerLiteralConversion(-1L, typeof(long?))); + Assert.That(!IntegerLiteralConversion(-1L, typeof(ulong?))); } [Test] public void ImplicitConstantExpressionConversionNumberInterfaces() { - Assert.IsTrue(IntegerLiteralConversion(0, typeof(IFormattable))); - Assert.IsTrue(IntegerLiteralConversion(0, typeof(IComparable))); - Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); - Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); + Assert.That(IntegerLiteralConversion(0, typeof(IFormattable))); + Assert.That(IntegerLiteralConversion(0, typeof(IComparable))); + Assert.That(!IntegerLiteralConversion(0, typeof(IComparable))); + Assert.That(!IntegerLiteralConversion(0, typeof(IComparable))); } int BetterConversion(Type s, Type t1, Type t2) @@ -620,39 +595,39 @@ int BetterConversion(object value, Type t1, Type t2) [Test] public void BetterConversion() { - Assert.AreEqual(1, BetterConversion(typeof(string), typeof(string), typeof(object))); - Assert.AreEqual(2, BetterConversion(typeof(string), typeof(object), typeof(IComparable))); - Assert.AreEqual(0, BetterConversion(typeof(string), typeof(IEnumerable), typeof(IComparable))); + Assert.That(BetterConversion(typeof(string), typeof(string), typeof(object)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(string), typeof(object), typeof(IComparable)), Is.EqualTo(2)); + Assert.That(BetterConversion(typeof(string), typeof(IEnumerable), typeof(IComparable)), Is.EqualTo(0)); } [Test] public void BetterPrimitiveConversion() { - Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(long))); - Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(uint))); - Assert.AreEqual(2, BetterConversion(typeof(ushort), typeof(uint), typeof(int))); - Assert.AreEqual(1, BetterConversion(typeof(char), typeof(short), typeof(int))); - Assert.AreEqual(1, BetterConversion(typeof(char), typeof(ushort), typeof(int))); - Assert.AreEqual(1, BetterConversion(typeof(sbyte), typeof(long), typeof(ulong))); - Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ushort), typeof(short))); + Assert.That(BetterConversion(typeof(short), typeof(int), typeof(long)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(short), typeof(int), typeof(uint)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(ushort), typeof(uint), typeof(int)), Is.EqualTo(2)); + Assert.That(BetterConversion(typeof(char), typeof(short), typeof(int)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(char), typeof(ushort), typeof(int)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(sbyte), typeof(long), typeof(ulong)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(byte), typeof(ushort), typeof(short)), Is.EqualTo(2)); - Assert.AreEqual(1, BetterConversion(1, typeof(sbyte), typeof(byte))); - Assert.AreEqual(2, BetterConversion(1, typeof(ushort), typeof(sbyte))); + Assert.That(BetterConversion(1, typeof(sbyte), typeof(byte)), Is.EqualTo(1)); + Assert.That(BetterConversion(1, typeof(ushort), typeof(sbyte)), Is.EqualTo(2)); } [Test] public void BetterNullableConversion() { - Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(int), typeof(uint?))); - Assert.AreEqual(0, BetterConversion(typeof(byte?), typeof(int?), typeof(uint?))); - Assert.AreEqual(1, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint?))); - Assert.AreEqual(2, BetterConversion(typeof(byte?), typeof(ulong?), typeof(uint?))); - Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint))); - Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(int))); - Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ulong?), typeof(uint))); - Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ulong?), typeof(int))); - Assert.AreEqual(2, BetterConversion(typeof(ushort?), typeof(long?), typeof(int?))); - Assert.AreEqual(0, BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?))); + Assert.That(BetterConversion(typeof(byte), typeof(int), typeof(uint?)), Is.EqualTo(0)); + Assert.That(BetterConversion(typeof(byte?), typeof(int?), typeof(uint?)), Is.EqualTo(0)); + Assert.That(BetterConversion(typeof(byte), typeof(ushort?), typeof(uint?)), Is.EqualTo(1)); + Assert.That(BetterConversion(typeof(byte?), typeof(ulong?), typeof(uint?)), Is.EqualTo(2)); + Assert.That(BetterConversion(typeof(byte), typeof(ushort?), typeof(uint)), Is.EqualTo(0)); + Assert.That(BetterConversion(typeof(byte), typeof(ushort?), typeof(int)), Is.EqualTo(0)); + Assert.That(BetterConversion(typeof(byte), typeof(ulong?), typeof(uint)), Is.EqualTo(2)); + Assert.That(BetterConversion(typeof(byte), typeof(ulong?), typeof(int)), Is.EqualTo(0)); + Assert.That(BetterConversion(typeof(ushort?), typeof(long?), typeof(int?)), Is.EqualTo(2)); + Assert.That(BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?)), Is.EqualTo(0)); } /* TODO: we should probably revive these tests somehow @@ -678,7 +653,7 @@ public void ExpansiveInheritance() IType type1 = new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.Double) }); IType type2 = new ParameterizedType(resolvedA, new[] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) }); - Assert.IsFalse(conversions.ImplicitConversion(type1, type2).IsValid); + Assert.That(!conversions.ImplicitConversion(type1, type2).IsValid); } [Test] @@ -776,9 +751,9 @@ class Test { public static void M() {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsFalse(c.DelegateCapturesFirstArgument); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); + Assert.That(!c.DelegateCapturesFirstArgument); Assert.IsNotNull(c.Method); } @@ -794,9 +769,9 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsTrue(c.DelegateCapturesFirstArgument); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); + Assert.That(c.DelegateCapturesFirstArgument); Assert.IsNotNull(c.Method); } @@ -810,8 +785,8 @@ class Test { public static object M(int argument) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -824,8 +799,8 @@ class Test { public static int M(int argument) {} }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(!c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -838,8 +813,8 @@ class Test { public static string M(int argument) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -852,8 +827,8 @@ class Test { public static void M(ref object o) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -866,8 +841,8 @@ class Test { public static void M(ref dynamic o) {} }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(!c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -880,7 +855,7 @@ class Test { public static void M(out object o) {} }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -893,7 +868,7 @@ class Test { public static void M(object o) {} }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -906,7 +881,7 @@ class Test { public static void M(out object o) {} }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -919,8 +894,8 @@ class Test { public static void M(object o) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -933,8 +908,8 @@ class Test { public static void M(dynamic o) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -947,8 +922,8 @@ class Test { public static void M(object o) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); } @@ -963,7 +938,7 @@ public static void M(dynamic o) {} }"; var c = GetConversion(program); //Assert.IsFrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsMethodGroupConversion); } [Test] @@ -977,8 +952,8 @@ static void M(object x) {} static void M(string x = null) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); Assert.AreEqual("System.String", c.Method.Parameters.Single().Type.FullName); } @@ -993,8 +968,8 @@ static void M(object x) {} static void M(string x, string y = null) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName); } @@ -1009,8 +984,8 @@ static void M(object x) {} static void M(params string[] x) {} }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName); } @@ -1029,9 +1004,9 @@ void F() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsTrue(c.DelegateCapturesFirstArgument); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); + Assert.That(c.DelegateCapturesFirstArgument); } [Test] @@ -1048,9 +1023,9 @@ void F() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsFalse(c.DelegateCapturesFirstArgument); + Assert.That(c.IsValid); + Assert.That(c.IsMethodGroupConversion); + Assert.That(!c.DelegateCapturesFirstArgument); } [Test] @@ -1064,7 +1039,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1079,7 +1054,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1093,7 +1068,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1107,7 +1082,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1122,7 +1097,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1136,7 +1111,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); + Assert.That(c.IsValid); } [Test] @@ -1152,8 +1127,8 @@ static void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); } [Test] @@ -1170,8 +1145,8 @@ static void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); } @@ -1189,9 +1164,9 @@ static void M(S? s) { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); - Assert.IsTrue(c.IsLifted); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); + Assert.That(c.IsLifted); } [Test] @@ -1208,8 +1183,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("i", c.Method.Parameters[0].Name); } @@ -1227,8 +1202,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("ui", c.Method.Parameters[0].Name); } @@ -1246,7 +1221,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -1263,8 +1238,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("i", c.Method.Parameters[0].Name); } @@ -1282,8 +1257,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("us", c.Method.Parameters[0].Name); } @@ -1301,7 +1276,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -1320,7 +1295,7 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); + Assert.That(!c.IsValid); } [Test] @@ -1337,9 +1312,9 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); - Assert.IsFalse(c.IsLifted); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); + Assert.That(!c.IsLifted); Assert.AreEqual("ni", c.Method.Parameters[0].Name); } @@ -1357,8 +1332,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("ui", c.Method.Parameters[0].Name); } @@ -1376,8 +1351,8 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("ui", c.Method.Parameters[0].Name); } @@ -1396,8 +1371,8 @@ public static void Main(string[] args) } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("System.Int16", c.Method.ReturnType.FullName); } @@ -1416,8 +1391,8 @@ public static void Main(string[] args) } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("System.Int16", c.Method.ReturnType.FullName); } @@ -1436,8 +1411,8 @@ public static void Main(string[] args) } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("s", c.Method.Parameters[0].Name); } @@ -1456,8 +1431,8 @@ static void Main() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("i", c.Method.Parameters[0].Name); } @@ -1476,8 +1451,8 @@ static void Main() { } }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(!c.IsValid); + Assert.That(c.IsUserDefined); } [Test] @@ -1494,8 +1469,8 @@ static void Main() { } }"; var c = GetConversion(program); - Assert.IsFalse(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(!c.IsValid); + Assert.That(c.IsUserDefined); } [Test] @@ -1513,8 +1488,8 @@ static void Main() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsUserDefined); + Assert.That(c.IsValid); + Assert.That(c.IsUserDefined); Assert.AreEqual("i", c.Method.Parameters[0].Name); } @@ -1537,7 +1512,7 @@ static void Main() { }"; var rr = Resolve(program); - Assert.IsFalse(rr.IsError); + Assert.That(!rr.IsError); Assert.AreEqual("str", rr.Member.Parameters[0].Name); } @@ -1566,8 +1541,8 @@ static void Main() { }"; var c = GetConversion(program); - Assert.IsTrue(c.IsUserDefined); - Assert.IsFalse(c.IsValid); + Assert.That(c.IsUserDefined); + Assert.That(!c.IsValid); } [Test] @@ -1584,11 +1559,11 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.ConversionBeforeUserDefinedOperator.IsImplicit); - Assert.IsTrue(c.ConversionBeforeUserDefinedOperator.IsNumericConversion); - Assert.IsTrue(c.ConversionBeforeUserDefinedOperator.IsValid); - Assert.IsTrue(c.ConversionAfterUserDefinedOperator.IsIdentityConversion); + Assert.That(c.IsValid); + Assert.That(c.ConversionBeforeUserDefinedOperator.IsImplicit); + Assert.That(c.ConversionBeforeUserDefinedOperator.IsNumericConversion); + Assert.That(c.ConversionBeforeUserDefinedOperator.IsValid); + Assert.That(c.ConversionAfterUserDefinedOperator.IsIdentityConversion); } [Test] @@ -1604,11 +1579,11 @@ public void M() { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.ConversionBeforeUserDefinedOperator.IsIdentityConversion); - Assert.IsTrue(c.ConversionAfterUserDefinedOperator.IsImplicit); - Assert.IsTrue(c.ConversionAfterUserDefinedOperator.IsNumericConversion); - Assert.IsTrue(c.ConversionAfterUserDefinedOperator.IsValid); + Assert.That(c.IsValid); + Assert.That(c.ConversionBeforeUserDefinedOperator.IsIdentityConversion); + Assert.That(c.ConversionAfterUserDefinedOperator.IsImplicit); + Assert.That(c.ConversionAfterUserDefinedOperator.IsNumericConversion); + Assert.That(c.ConversionAfterUserDefinedOperator.IsValid); } [Test] @@ -1627,9 +1602,9 @@ public static implicit operator JsNumber3(int d) { } }"; var c = GetConversion(program); - Assert.IsTrue(c.IsValid); - Assert.IsTrue(c.IsImplicit); - Assert.IsFalse(c.IsExplicit); + Assert.That(c.IsValid); + Assert.That(c.IsImplicit); + Assert.That(!c.IsExplicit); Assert.AreEqual(Conversion.IdentityConversion, c.ConversionBeforeUserDefinedOperator); Assert.AreEqual(Conversion.IdentityConversion, c.ConversionAfterUserDefinedOperator); } diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs b/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs index f2bb2b4403..0abed50b61 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs @@ -58,11 +58,11 @@ Conversion ExplicitConversion(Type from, Type to) [Test] public void PointerConversion() { - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(int*), typeof(short))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(short), typeof(void*))); + Assert.That(ExplicitConversion(typeof(int*), typeof(short)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(short), typeof(void*)), Is.EqualTo(C.ExplicitPointerConversion)); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(void*), typeof(int*))); - Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(long*), typeof(byte*))); + Assert.That(ExplicitConversion(typeof(void*), typeof(int*)), Is.EqualTo(C.ExplicitPointerConversion)); + Assert.That(ExplicitConversion(typeof(long*), typeof(byte*)), Is.EqualTo(C.ExplicitPointerConversion)); } [Test] @@ -70,60 +70,60 @@ public void ConversionFromDynamic() { // Explicit dynamic conversion is for resolve results only; // otherwise it's an explicit reference / unboxing conversion - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic), typeof(string))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(dynamic), typeof(int))); + Assert.That(ExplicitConversion(typeof(dynamic), typeof(string)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(dynamic), typeof(int)), Is.EqualTo(C.UnboxingConversion)); var dynamicRR = new ResolveResult(SpecialType.Dynamic); - Assert.AreEqual(C.ExplicitDynamicConversion, conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(string)))); - Assert.AreEqual(C.ExplicitDynamicConversion, conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(int)))); + Assert.That(conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(string))), Is.EqualTo(C.ExplicitDynamicConversion)); + Assert.That(conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(int))), Is.EqualTo(C.ExplicitDynamicConversion)); } [Test] public void NumericConversions() { - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(uint))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(char))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(char))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(sbyte))); + Assert.That(ExplicitConversion(typeof(sbyte), typeof(uint)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(sbyte), typeof(char)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(byte), typeof(char)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(byte), typeof(sbyte)), Is.EqualTo(C.ExplicitNumericConversion)); // if an implicit conversion exists, ExplicitConversion() should return that - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(int))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(float))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(decimal))); - Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(decimal), typeof(double))); - Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(int), typeof(decimal))); + Assert.That(ExplicitConversion(typeof(byte), typeof(int)), Is.EqualTo(C.ImplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(double), typeof(float)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(double), typeof(decimal)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(decimal), typeof(double)), Is.EqualTo(C.ExplicitNumericConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(decimal)), Is.EqualTo(C.ImplicitNumericConversion)); - Assert.AreEqual(C.None, ExplicitConversion(typeof(bool), typeof(int))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(int), typeof(bool))); + Assert.That(ExplicitConversion(typeof(bool), typeof(int)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(int), typeof(bool)), Is.EqualTo(C.None)); } [Test] public void EnumerationConversions() { var explicitEnumerationConversion = C.EnumerationConversion(false, false); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(sbyte), typeof(StringComparison))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(char), typeof(StringComparison))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(int), typeof(StringComparison))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(decimal), typeof(StringComparison))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(char))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(int))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(decimal))); - Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions))); + Assert.That(ExplicitConversion(typeof(sbyte), typeof(StringComparison)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(char), typeof(StringComparison)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(StringComparison)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(decimal), typeof(StringComparison)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(char)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(int)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(decimal)), Is.EqualTo(explicitEnumerationConversion)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions)), Is.EqualTo(explicitEnumerationConversion)); } [Test] public void NullableConversion_BasedOnIdentityConversion() { - Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(ArraySegment?), typeof(ArraySegment?))); - Assert.AreEqual(C.ImplicitNullableConversion, ExplicitConversion(typeof(ArraySegment), typeof(ArraySegment?))); - Assert.AreEqual(C.ExplicitNullableConversion, ExplicitConversion(typeof(ArraySegment?), typeof(ArraySegment))); + Assert.That(ExplicitConversion(typeof(ArraySegment?), typeof(ArraySegment?)), Is.EqualTo(C.IdentityConversion)); + Assert.That(ExplicitConversion(typeof(ArraySegment), typeof(ArraySegment?)), Is.EqualTo(C.ImplicitNullableConversion)); + Assert.That(ExplicitConversion(typeof(ArraySegment?), typeof(ArraySegment)), Is.EqualTo(C.ExplicitNullableConversion)); } [Test] public void NullableConversion_BasedOnImplicitNumericConversion() { - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(long?))); - Assert.AreEqual(C.ImplicitLiftedNumericConversion, ExplicitConversion(typeof(int), typeof(long?))); - Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(long))); + Assert.That(ExplicitConversion(typeof(int?), typeof(long?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(long?)), Is.EqualTo(C.ImplicitLiftedNumericConversion)); + Assert.That(ExplicitConversion(typeof(int?), typeof(long)), Is.EqualTo(C.ExplicitLiftedNumericConversion)); } [Test] @@ -131,160 +131,160 @@ public void NullableConversion_BasedOnImplicitEnumerationConversion() { ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0); ResolveResult one = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1); - Assert.AreEqual(C.EnumerationConversion(true, true), conversions.ExplicitConversion(zero, compilation.FindType(typeof(StringComparison?)))); - Assert.AreEqual(C.EnumerationConversion(false, true), conversions.ExplicitConversion(one, compilation.FindType(typeof(StringComparison?)))); + Assert.That(conversions.ExplicitConversion(zero, compilation.FindType(typeof(StringComparison?))), Is.EqualTo(C.EnumerationConversion(true, true))); + Assert.That(conversions.ExplicitConversion(one, compilation.FindType(typeof(StringComparison?))), Is.EqualTo(C.EnumerationConversion(false, true))); } [Test] public void NullableConversion_BasedOnExplicitNumericConversion() { - Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(short?))); - Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int), typeof(short?))); - Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(short))); + Assert.That(ExplicitConversion(typeof(int?), typeof(short?)), Is.EqualTo(C.ExplicitLiftedNumericConversion)); + Assert.That(ExplicitConversion(typeof(int), typeof(short?)), Is.EqualTo(C.ExplicitLiftedNumericConversion)); + Assert.That(ExplicitConversion(typeof(int?), typeof(short)), Is.EqualTo(C.ExplicitLiftedNumericConversion)); } [Test] public void NullableConversion_BasedOnExplicitEnumerationConversion() { C c = C.EnumerationConversion(false, true); // c = explicit lifted enumeration conversion - Assert.AreEqual(c, ExplicitConversion(typeof(int?), typeof(StringComparison?))); - Assert.AreEqual(c, ExplicitConversion(typeof(int), typeof(StringComparison?))); - Assert.AreEqual(c, ExplicitConversion(typeof(int?), typeof(StringComparison))); + Assert.That(ExplicitConversion(typeof(int?), typeof(StringComparison?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(int), typeof(StringComparison?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(int?), typeof(StringComparison)), Is.EqualTo(c)); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(int?))); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison), typeof(int?))); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(int))); + Assert.That(ExplicitConversion(typeof(StringComparison?), typeof(int?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(int?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(StringComparison?), typeof(int)), Is.EqualTo(c)); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions?))); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions?))); - Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions))); + Assert.That(ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions?)), Is.EqualTo(c)); + Assert.That(ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions)), Is.EqualTo(c)); } [Test] public void ExplicitReferenceConversion_SealedClass() { - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object), typeof(string))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(string))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(string))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(string))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string), typeof(IEnumerable))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(string), typeof(IEnumerable))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(string), typeof(IEnumerable))); + Assert.That(ExplicitConversion(typeof(object), typeof(string)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(string)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(string)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(string)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(string), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(string), typeof(IEnumerable)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(string), typeof(IEnumerable)), Is.EqualTo(C.None)); } [Test] public void ExplicitReferenceConversion_NonSealedClass() { - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object), typeof(List))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(List))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(List))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(List))); + Assert.That(ExplicitConversion(typeof(object), typeof(List)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(List)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(List)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(List)), Is.EqualTo(C.ExplicitReferenceConversion)); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.That(ExplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(List), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); - Assert.AreEqual(C.None, ExplicitConversion(typeof(List), typeof(List))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(List), typeof(List))); + Assert.That(ExplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(List), typeof(List)), Is.EqualTo(C.None)); } [Test] public void ExplicitReferenceConversion_Interfaces() { - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(IConvertible))); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(IConvertible)), Is.EqualTo(C.ExplicitReferenceConversion)); } [Test] public void ExplicitReferenceConversion_Arrays() { - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object[]), typeof(string[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic[]), typeof(string[]))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(object[,]))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(int[]))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(short[]), typeof(int[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Array), typeof(int[]))); + Assert.That(ExplicitConversion(typeof(object[]), typeof(string[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(dynamic[]), typeof(string[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(object[]), typeof(object[,])), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(object[]), typeof(int[])), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(short[]), typeof(int[])), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Array), typeof(int[])), Is.EqualTo(C.ExplicitReferenceConversion)); } [Test] public void ExplicitReferenceConversion_InterfaceToArray() { - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(ICloneable), typeof(int[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(string[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(string[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(object[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(dynamic[]))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable), typeof(int[]))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(object[,]))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(object[]))); + Assert.That(ExplicitConversion(typeof(ICloneable), typeof(int[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(string[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(string[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(object[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(dynamic[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(int[])), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(object[,])), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(object[])), Is.EqualTo(C.None)); } [Test] public void ExplicitReferenceConversion_ArrayToInterface() { - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(int[]), typeof(ICloneable))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string[]), typeof(IEnumerable))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string[]), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object[]), typeof(IEnumerable))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic[]), typeof(IEnumerable))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(int[]), typeof(IEnumerable))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(object[,]), typeof(IEnumerable))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(IEnumerable))); + Assert.That(ExplicitConversion(typeof(int[]), typeof(ICloneable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(string[]), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(string[]), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(object[]), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(dynamic[]), typeof(IEnumerable)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(int[]), typeof(IEnumerable)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(object[,]), typeof(IEnumerable)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(object[]), typeof(IEnumerable)), Is.EqualTo(C.None)); } [Test] public void ExplicitReferenceConversion_Delegates() { - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(MulticastDelegate), typeof(Action))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Delegate), typeof(Action))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(ICloneable), typeof(Action))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(System.Threading.ThreadStart), typeof(Action))); + Assert.That(ExplicitConversion(typeof(MulticastDelegate), typeof(Action)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(Delegate), typeof(Action)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(ICloneable), typeof(Action)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(System.Threading.ThreadStart), typeof(Action)), Is.EqualTo(C.None)); } [Test] public void ExplicitReferenceConversion_GenericDelegates() { - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(Action), typeof(Action))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action), typeof(Action))); + Assert.That(ExplicitConversion(typeof(Action), typeof(Action)), Is.EqualTo(C.ImplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(Action), typeof(Action)), Is.EqualTo(C.ExplicitReferenceConversion)); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(Func), typeof(Func))); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.ImplicitReferenceConversion)); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action), typeof(Action))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Action), typeof(Action))); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action), typeof(Action>))); + Assert.That(ExplicitConversion(typeof(Action), typeof(Action)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(Action), typeof(Action)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Action), typeof(Action>)), Is.EqualTo(C.ExplicitReferenceConversion)); - Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Func), typeof(Func))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Func), typeof(Func>))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Func), typeof(Func>))); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.ExplicitReferenceConversion)); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func>)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Func), typeof(Func>)), Is.EqualTo(C.None)); } [Test] public void UnboxingConversion() { - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(int))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(decimal))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(ValueType), typeof(int))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(IFormattable), typeof(int))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(int))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(Enum), typeof(StringComparison))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Enum), typeof(int))); + Assert.That(ExplicitConversion(typeof(object), typeof(int)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(object), typeof(decimal)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(ValueType), typeof(int)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(IFormattable), typeof(int)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(int)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Enum), typeof(StringComparison)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(Enum), typeof(int)), Is.EqualTo(C.None)); } [Test] public void LiftedUnboxingConversion() { - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(int?))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(decimal?))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(ValueType), typeof(int?))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(IFormattable), typeof(int?))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable), typeof(int?))); - Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(Enum), typeof(StringComparison?))); - Assert.AreEqual(C.None, ExplicitConversion(typeof(Enum), typeof(int?))); + Assert.That(ExplicitConversion(typeof(object), typeof(int?)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(object), typeof(decimal?)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(ValueType), typeof(int?)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(IFormattable), typeof(int?)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(IEnumerable), typeof(int?)), Is.EqualTo(C.None)); + Assert.That(ExplicitConversion(typeof(Enum), typeof(StringComparison?)), Is.EqualTo(C.UnboxingConversion)); + Assert.That(ExplicitConversion(typeof(Enum), typeof(int?)), Is.EqualTo(C.None)); } /* TODO: we should probably revive these tests somehow @@ -477,8 +477,8 @@ public void M() { C1 c1 = $(C1)c2$; } }"); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("op_Explicit", rr.Conversion.Method.Name); } @@ -496,8 +496,8 @@ void Run(B b) { T t = $(T)b$; } }"); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("B", rr.Input.Type.Name); } @@ -513,10 +513,10 @@ void Run(T t) { int x = $(int)t$; } }"); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); // even though the user-defined conversion is implicit, the combined conversion is explicit - Assert.IsTrue(rr.Conversion.IsExplicit); + Assert.That(rr.Conversion.IsExplicit); } [Test] @@ -534,8 +534,8 @@ void Run(B b) { T t = $(T)b$; } }"); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("b", rr.Conversion.Method.Parameters.Single().Name); } @@ -553,8 +553,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name); } @@ -572,8 +572,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name); } @@ -591,8 +591,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name); } @@ -610,7 +610,7 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsFalse(rr.Conversion.IsValid); + Assert.That(!rr.Conversion.IsValid); } [Test] @@ -627,8 +627,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name); } @@ -646,8 +646,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("us", rr.Conversion.Method.Parameters[0].Name); } @@ -665,8 +665,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name); } @@ -684,7 +684,7 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsFalse(rr.Conversion.IsValid); + Assert.That(!rr.Conversion.IsValid); } [Test] @@ -703,7 +703,7 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsFalse(rr.Conversion.IsValid); + Assert.That(!rr.Conversion.IsValid); } [Test] @@ -719,9 +719,9 @@ public void M(int? i) { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); - Assert.IsTrue(rr.Conversion.IsLifted); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsLifted); } [Test] @@ -737,9 +737,9 @@ public void M(int i) { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); - Assert.IsFalse(rr.Conversion.IsLifted); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); + Assert.That(!rr.Conversion.IsLifted); } [Test] @@ -756,9 +756,9 @@ public void M(int? i) { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); - Assert.IsFalse(rr.Conversion.IsLifted); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); + Assert.That(!rr.Conversion.IsLifted); Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name); } @@ -776,9 +776,9 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); - Assert.IsFalse(rr.Conversion.IsLifted); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); + Assert.That(!rr.Conversion.IsLifted); Assert.AreEqual("ni", rr.Conversion.Method.Parameters[0].Name); } @@ -796,8 +796,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name); } @@ -815,8 +815,8 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name); } @@ -833,10 +833,10 @@ public void M(int? i) { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); - Assert.IsTrue(rr.Conversion.IsLifted); - Assert.IsTrue(rr.Input is LocalResolveResult); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsLifted); + Assert.That(rr.Input is LocalResolveResult); } [Test] @@ -854,8 +854,8 @@ public static void Main(string[] args) } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("System.Int16", rr.Conversion.Method.ReturnType.FullName); } @@ -874,8 +874,8 @@ public static void Main(string[] args) } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("s", rr.Conversion.Method.Parameters[0].Name); } @@ -893,8 +893,8 @@ static void Main() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.IsUserDefined); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.IsUserDefined); Assert.AreEqual("ci", rr.Conversion.Method.Parameters[0].Name); } @@ -912,11 +912,11 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsValid); - Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsExplicit); - Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsNumericConversion); - Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsIdentityConversion); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.ConversionBeforeUserDefinedOperator.IsValid); + Assert.That(rr.Conversion.ConversionBeforeUserDefinedOperator.IsExplicit); + Assert.That(rr.Conversion.ConversionBeforeUserDefinedOperator.IsNumericConversion); + Assert.That(rr.Conversion.ConversionAfterUserDefinedOperator.IsIdentityConversion); } [Test] @@ -932,11 +932,11 @@ public void M() { } }"; var rr = Resolve(program); - Assert.IsTrue(rr.Conversion.IsValid); - Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsIdentityConversion); - Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsValid); - Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsExplicit); - Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsNumericConversion); + Assert.That(rr.Conversion.IsValid); + Assert.That(rr.Conversion.ConversionBeforeUserDefinedOperator.IsIdentityConversion); + Assert.That(rr.Conversion.ConversionAfterUserDefinedOperator.IsValid); + Assert.That(rr.Conversion.ConversionAfterUserDefinedOperator.IsExplicit); + Assert.That(rr.Conversion.ConversionAfterUserDefinedOperator.IsNumericConversion); }*/ } } diff --git a/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs index 5a72ad5b2c..cabe83281b 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs @@ -86,10 +86,10 @@ public void PreferIntOverUInt() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(ushort))); var c1 = MakeMethod(typeof(int)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint)))); - Assert.IsFalse(r.IsAmbiguous); - Assert.AreSame(c1, r.BestCandidate); + Assert.That(r.AddCandidate(c1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(MakeMethod(typeof(uint))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(!r.IsAmbiguous); + Assert.That(r.BestCandidate, Is.SameAs(c1)); } [Test] @@ -98,66 +98,66 @@ public void PreferUIntOverLong_FromIntLiteral() ResolveResult[] args = { new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1) }; OverloadResolution r = new OverloadResolution(compilation, args); var c1 = MakeMethod(typeof(uint)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(long)))); - Assert.IsFalse(r.IsAmbiguous); - Assert.AreSame(c1, r.BestCandidate); + Assert.That(r.AddCandidate(c1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(MakeMethod(typeof(long))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(!r.IsAmbiguous); + Assert.That(r.BestCandidate, Is.SameAs(c1)); } [Test] public void NullableIntAndNullableUIntIsAmbiguous() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(ushort?))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(int?)))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint?)))); - Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); + Assert.That(r.AddCandidate(MakeMethod(typeof(int?))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(MakeMethod(typeof(uint?))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateErrors, Is.EqualTo(OverloadResolutionErrors.AmbiguousMatch)); // then adding a matching overload solves the ambiguity: - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(ushort?)))); - Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); - Assert.IsNull(r.BestCandidateAmbiguousWith); + Assert.That(r.AddCandidate(MakeMethod(typeof(ushort?))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateErrors, Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateAmbiguousWith, Is.Null); } [Test] public void ParamsMethodMatchesEmptyArgumentList() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList()); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); - Assert.IsTrue(r.BestCandidateIsExpandedForm); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int[]))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateIsExpandedForm); } [Test] public void ParamsMethodMatchesOneArgumentInExpandedForm() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); - Assert.IsTrue(r.BestCandidateIsExpandedForm); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int[]))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateIsExpandedForm); } [Test] public void ParamsMethodMatchesInUnexpandedForm() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int[]))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); - Assert.IsFalse(r.BestCandidateIsExpandedForm); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int[]))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(!r.BestCandidateIsExpandedForm); } [Test] public void LessArgumentsPassedToParamsIsBetter() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int), typeof(int), typeof(int))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int), typeof(int[])))); - Assert.IsFalse(r.IsAmbiguous); - Assert.AreEqual(2, r.BestCandidate.Parameters.Count); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int[]))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int), typeof(int[]))), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(!r.IsAmbiguous); + Assert.That(r.BestCandidate.Parameters.Count, Is.EqualTo(2)); } [Test] public void CallInvalidParamsDeclaration() { OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int[,]))); - Assert.AreEqual(OverloadResolutionErrors.ArgumentTypeMismatch, r.AddCandidate(MakeParamsMethod(typeof(int)))); - Assert.IsFalse(r.BestCandidateIsExpandedForm); + Assert.That(r.AddCandidate(MakeParamsMethod(typeof(int))), Is.EqualTo(OverloadResolutionErrors.ArgumentTypeMismatch)); + Assert.That(!r.BestCandidateIsExpandedForm); } [Test] @@ -167,10 +167,10 @@ public void PreferMethodWithoutOptionalParameters() var m2 = MakeMethod(1); OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList()); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); - Assert.IsFalse(r.IsAmbiguous); - Assert.AreSame(m1, r.BestCandidate); + Assert.That(r.AddCandidate(m1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(m2), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(!r.IsAmbiguous); + Assert.That(r.BestCandidate, Is.SameAs(m1)); } [Test] @@ -186,22 +186,22 @@ public void SkeetEvilOverloadResolution() // Call: Foo(); OverloadResolution o; o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int)) }); - Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM1)); - Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2)); - Assert.AreSame(resolvedM1, o.BestCandidate); + Assert.That(o.AddCandidate(resolvedM1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(o.AddCandidate(resolvedM2), Is.EqualTo(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint)); + Assert.That(o.BestCandidate, Is.SameAs(resolvedM1)); // Call: Foo(); o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(string)) }); - Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1)); - Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM2)); - Assert.AreSame(resolvedM2, o.BestCandidate); + Assert.That(o.AddCandidate(resolvedM1), Is.EqualTo(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint)); + Assert.That(o.AddCandidate(resolvedM2), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(o.BestCandidate, Is.SameAs(resolvedM2)); // Call: Foo(); o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int?)) }); - Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1)); - Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2)); - Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM3)); - Assert.AreSame(resolvedM3, o.BestCandidate); + Assert.That(o.AddCandidate(resolvedM1), Is.EqualTo(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint)); + Assert.That(o.AddCandidate(resolvedM2), Is.EqualTo(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint)); + Assert.That(o.AddCandidate(resolvedM3), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(o.BestCandidate, Is.SameAs(resolvedM3)); } class SkeetEvilOverloadResolutionTestCase @@ -276,10 +276,10 @@ public void BetterConversionByLambdaReturnValue() }; OverloadResolution r = new OverloadResolution(compilation, args); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); - Assert.AreSame(m2, r.BestCandidate); - Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); + Assert.That(r.AddCandidate(m1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(m2), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidate, Is.SameAs(m2)); + Assert.That(r.BestCandidateErrors, Is.EqualTo(OverloadResolutionErrors.None)); } [Test] @@ -294,10 +294,10 @@ public void BetterConversionByLambdaReturnValue_ExpressionTree() }; OverloadResolution r = new OverloadResolution(compilation, args); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); - Assert.AreSame(m2, r.BestCandidate); - Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); + Assert.That(r.AddCandidate(m1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(m2), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidate, Is.SameAs(m2)); + Assert.That(r.BestCandidateErrors, Is.EqualTo(OverloadResolutionErrors.None)); } [Test] @@ -312,9 +312,9 @@ public void Lambda_DelegateAndExpressionTreeOverloadsAreAmbiguous() }; OverloadResolution r = new OverloadResolution(compilation, args); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); - Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); + Assert.That(r.AddCandidate(m1), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.AddCandidate(m2), Is.EqualTo(OverloadResolutionErrors.None)); + Assert.That(r.BestCandidateErrors, Is.EqualTo(OverloadResolutionErrors.AmbiguousMatch)); } [Test, Ignore("Overload Resolution bug")] @@ -329,10 +329,10 @@ public void BetterFunctionMemberIsNotTransitive() OverloadResolution r = new OverloadResolution(compilation, args); foreach (var method in container.GetMethods(m => m.Name == "Method")) { - Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(method)); + Assert.That(r.AddCandidate(method), Is.EqualTo(OverloadResolutionErrors.None)); } - Assert.AreEqual(container.GetMethods(m => m.Name == "Method").Last(), r.BestCandidate); + Assert.That(r.BestCandidate, Is.EqualTo(container.GetMethods(m => m.Name == "Method").Last())); } class BetterFunctionMemberIsNotTransitiveTestCase diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index cbcb2635fa..856c02028e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -1444,7 +1444,11 @@ public static void Issue1745(string aaa) public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey key) { +#if NET40 || !ROSLYN key = (ConsoleKey)0; +#else + key = ConsoleKey.None; +#endif switch (x) { case "A": @@ -1457,7 +1461,11 @@ public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey ke key = ConsoleKey.C; break; } +#if NET40 || !ROSLYN return key != (ConsoleKey)0; +#else + return key != ConsoleKey.None; +#endif } public static void Issue1767(string s) diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs index 3686dbfcf4..75e6959642 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs @@ -36,8 +36,8 @@ public unsafe class ReflectionHelperTests void TestFindType(Type type) { IType t = compilation.FindType(type); - Assert.IsNotNull(t, type.FullName); - Assert.AreEqual(type.FullName, t.ReflectionName); + Assert.That(t, Is.Not.Null, type.FullName); + Assert.That(t.ReflectionName, Is.EqualTo(type.FullName)); } [Test] @@ -73,83 +73,70 @@ public void TestGetInnerClassInGenericClass2() [Test] public void TestToTypeReferenceInnerClass() { - Assert.AreEqual("System.Environment+SpecialFolder", - compilation.FindType(typeof(Environment.SpecialFolder)).ReflectionName); + Assert.That(compilation.FindType(typeof(Environment.SpecialFolder)).ReflectionName, Is.EqualTo("System.Environment+SpecialFolder")); } [Test] public void TestToTypeReferenceUnboundGenericClass() { - Assert.AreEqual("System.Action`1", - compilation.FindType(typeof(Action<>)).ReflectionName); - Assert.AreEqual("System.Action`2", - compilation.FindType(typeof(Action<,>)).ReflectionName); + Assert.That(compilation.FindType(typeof(Action<>)).ReflectionName, Is.EqualTo("System.Action`1")); + Assert.That(compilation.FindType(typeof(Action<,>)).ReflectionName, Is.EqualTo("System.Action`2")); } [Test] public void TestToTypeReferenceBoundGenericClass() { - Assert.AreEqual("System.Action`1[[System.String]]", - compilation.FindType(typeof(Action)).ReflectionName); - Assert.AreEqual("System.Action`2[[System.Int32],[System.Int16]]", - compilation.FindType(typeof(Action)).ReflectionName); + Assert.That(compilation.FindType(typeof(Action)).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); + Assert.That(compilation.FindType(typeof(Action)).ReflectionName, Is.EqualTo("System.Action`2[[System.Int32],[System.Int16]]")); } [Test] public void TestToTypeReferenceNullableType() { - Assert.AreEqual("System.Nullable`1[[System.Int32]]", - compilation.FindType(typeof(int?)).ReflectionName); + Assert.That(compilation.FindType(typeof(int?)).ReflectionName, Is.EqualTo("System.Nullable`1[[System.Int32]]")); } [Test] public void TestToTypeReferenceInnerClassInUnboundGenericType() { - Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection", - compilation.FindType(typeof(Dictionary<,>.ValueCollection)).ReflectionName); + Assert.That(compilation.FindType(typeof(Dictionary<,>.ValueCollection)).ReflectionName, Is.EqualTo("System.Collections.Generic.Dictionary`2+ValueCollection")); } [Test] public void TestToTypeReferenceInnerClassInBoundGenericType() { - Assert.AreEqual("System.Collections.Generic.Dictionary`2+KeyCollection[[System.String],[System.Int32]]", - compilation.FindType(typeof(Dictionary.KeyCollection)).ReflectionName); + Assert.That(compilation.FindType(typeof(Dictionary.KeyCollection)).ReflectionName, Is.EqualTo("System.Collections.Generic.Dictionary`2+KeyCollection[[System.String],[System.Int32]]")); } [Test] public void TestToTypeReferenceArrayType() { - Assert.AreEqual(typeof(int[]).FullName, - compilation.FindType(typeof(int[])).ReflectionName); + Assert.That(compilation.FindType(typeof(int[])).ReflectionName, Is.EqualTo(typeof(int[]).FullName)); } [Test] public void TestToTypeReferenceMultidimensionalArrayType() { - Assert.AreEqual(typeof(int[,]).FullName, - compilation.FindType(typeof(int[,])).ReflectionName); + Assert.That(compilation.FindType(typeof(int[,])).ReflectionName, Is.EqualTo(typeof(int[,]).FullName)); } [Test] public void TestToTypeReferenceJaggedMultidimensionalArrayType() { - Assert.AreEqual(typeof(int[,][,,]).FullName, - compilation.FindType(typeof(int[,][,,])).ReflectionName); + Assert.That(compilation.FindType(typeof(int[,][,,])).ReflectionName, Is.EqualTo(typeof(int[,][,,]).FullName)); } [Test] public void TestToTypeReferencePointerType() { - Assert.AreEqual(typeof(int*).FullName, - compilation.FindType(typeof(int*)).ReflectionName); + Assert.That(compilation.FindType(typeof(int*)).ReflectionName, Is.EqualTo(typeof(int*).FullName)); } [Test] public void TestToTypeReferenceByReferenceType() { - Assert.AreEqual(typeof(int).MakeByRefType().FullName, - compilation.FindType(typeof(int).MakeByRefType()).ReflectionName); + Assert.That(compilation.FindType(typeof(int).MakeByRefType()).ReflectionName, Is.EqualTo(typeof(int).MakeByRefType().FullName)); } [Test] @@ -159,43 +146,43 @@ public void TestToTypeReferenceGenericType() ITypeReference parameterType = convertAllInfo.GetParameters()[0].ParameterType.ToTypeReference(); // Converter[[`0],[``0]] // cannot resolve generic types without knowing the parent entity: IType resolvedWithoutEntity = parameterType.Resolve(new SimpleTypeResolveContext(compilation)); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", resolvedWithoutEntity.ReflectionName); - Assert.IsNull(((ITypeParameter)((ParameterizedType)resolvedWithoutEntity).GetTypeArgument(0)).Owner); + Assert.That(resolvedWithoutEntity.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); + Assert.That(((ITypeParameter)((ParameterizedType)resolvedWithoutEntity).GetTypeArgument(0)).Owner, Is.Null); // now try with parent entity: IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single(); IType resolvedWithEntity = parameterType.Resolve(new SimpleTypeResolveContext(convertAll)); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", resolvedWithEntity.ReflectionName); - Assert.AreSame(convertAll.DeclaringTypeDefinition, ((ITypeParameter)((ParameterizedType)resolvedWithEntity).GetTypeArgument(0)).Owner); + Assert.That(resolvedWithEntity.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); + Assert.That(((ITypeParameter)((ParameterizedType)resolvedWithEntity).GetTypeArgument(0)).Owner, Is.SameAs(convertAll.DeclaringTypeDefinition)); } [Test] public void ParseReflectionName() { var context = new SimpleTypeResolveContext(compilation.MainModule); - Assert.AreEqual("System.Int32", ReflectionHelper.ParseReflectionName("System.Int32").Resolve(context).ReflectionName); - Assert.AreEqual("System.Int32&", ReflectionHelper.ParseReflectionName("System.Int32&").Resolve(context).ReflectionName); - Assert.AreEqual("System.Int32*&", ReflectionHelper.ParseReflectionName("System.Int32*&").Resolve(context).ReflectionName); - Assert.AreEqual("System.Int32", ReflectionHelper.ParseReflectionName(typeof(int).AssemblyQualifiedName).Resolve(context).ReflectionName); - Assert.AreEqual("System.Action`1[[System.String]]", ReflectionHelper.ParseReflectionName("System.Action`1[[System.String]]").Resolve(context).ReflectionName); - Assert.AreEqual("System.Action`1[[System.String]]", ReflectionHelper.ParseReflectionName("System.Action`1[[System.String, mscorlib]]").Resolve(context).ReflectionName); - Assert.AreEqual("System.Int32[,,][,]", ReflectionHelper.ParseReflectionName(typeof(int[,][,,]).AssemblyQualifiedName).Resolve(context).ReflectionName); - Assert.AreEqual("System.Environment+SpecialFolder", ReflectionHelper.ParseReflectionName("System.Environment+SpecialFolder").Resolve(context).ReflectionName); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32").Resolve(context).ReflectionName, Is.EqualTo("System.Int32")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32&").Resolve(context).ReflectionName, Is.EqualTo("System.Int32&")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32*&").Resolve(context).ReflectionName, Is.EqualTo("System.Int32*&")); + Assert.That(ReflectionHelper.ParseReflectionName(typeof(int).AssemblyQualifiedName).Resolve(context).ReflectionName, Is.EqualTo("System.Int32")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String]]").Resolve(context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String, mscorlib]]").Resolve(context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); + Assert.That(ReflectionHelper.ParseReflectionName(typeof(int[,][,,]).AssemblyQualifiedName).Resolve(context).ReflectionName, Is.EqualTo("System.Int32[,,][,]")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Environment+SpecialFolder").Resolve(context).ReflectionName, Is.EqualTo("System.Environment+SpecialFolder")); } [Test] public void ParseOpenGenericReflectionName() { ITypeReference typeRef = ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]"); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", typeRef.Resolve(new SimpleTypeResolveContext(compilation.MainModule)).ReflectionName); + Assert.That(typeRef.Resolve(new SimpleTypeResolveContext(compilation.MainModule)).ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single(); - Assert.AreEqual("System.Converter`2[[`0],[``0]]", typeRef.Resolve(new SimpleTypeResolveContext(convertAll)).ReflectionName); + Assert.That(typeRef.Resolve(new SimpleTypeResolveContext(convertAll)).ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); } [Test] public void ArrayOfTypeParameter() { var context = new SimpleTypeResolveContext(compilation.MainModule); - Assert.AreEqual("`0[,]", ReflectionHelper.ParseReflectionName("`0[,]").Resolve(context).ReflectionName); + Assert.That(ReflectionHelper.ParseReflectionName("`0[,]").Resolve(context).ReflectionName, Is.EqualTo("`0[,]")); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index b6346f0fde..b27a1ecc5c 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; +using ICSharpCode.Decompiler.Util; using NUnit.Framework; @@ -81,16 +82,16 @@ protected ITypeDefinition GetTypeDefinition(Type type) public void SimplePublicClassTest() { ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); - Assert.AreEqual(typeof(SimplePublicClass).Name, c.Name); - Assert.AreEqual(typeof(SimplePublicClass).FullName, c.FullName); - Assert.AreEqual(typeof(SimplePublicClass).Namespace, c.Namespace); - Assert.AreEqual(typeof(SimplePublicClass).FullName, c.ReflectionName); + Assert.That(c.Name, Is.EqualTo(typeof(SimplePublicClass).Name)); + Assert.That(c.FullName, Is.EqualTo(typeof(SimplePublicClass).FullName)); + Assert.That(c.Namespace, Is.EqualTo(typeof(SimplePublicClass).Namespace)); + Assert.That(c.ReflectionName, Is.EqualTo(typeof(SimplePublicClass).FullName)); - Assert.AreEqual(Accessibility.Public, c.Accessibility); - Assert.IsFalse(c.IsAbstract); - Assert.IsFalse(c.IsSealed); - Assert.IsFalse(c.IsStatic); - Assert.IsFalse(c.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(c.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!c.IsAbstract); + Assert.That(!c.IsSealed); + Assert.That(!c.IsStatic); + Assert.That(!c.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -99,17 +100,17 @@ public void SimplePublicClassMethodTest() ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); IMethod method = c.Methods.Single(m => m.Name == "Method"); - Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Method", method.FullName); - Assert.AreSame(c, method.DeclaringType); - Assert.AreEqual(Accessibility.Public, method.Accessibility); - Assert.AreEqual(SymbolKind.Method, method.SymbolKind); - Assert.IsFalse(method.IsVirtual); - Assert.IsFalse(method.IsStatic); - Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(0, method.GetAttributes().Count()); - Assert.IsTrue(method.HasBody); - Assert.IsNull(method.AccessorOwner); - Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(method.FullName, Is.EqualTo(typeof(SimplePublicClass).FullName + ".Method")); + Assert.That(method.DeclaringType, Is.SameAs(c)); + Assert.That(method.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(method.SymbolKind, Is.EqualTo(SymbolKind.Method)); + Assert.That(!method.IsVirtual); + Assert.That(!method.IsStatic); + Assert.That(method.Parameters.Count, Is.EqualTo(0)); + Assert.That(method.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(method.HasBody); + Assert.That(method.AccessorOwner, Is.Null); + Assert.That(!method.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -118,17 +119,17 @@ public void SimplePublicClassCtorTest() ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); IMethod method = c.Methods.Single(m => m.IsConstructor); - Assert.AreEqual(typeof(SimplePublicClass).FullName + "..ctor", method.FullName); - Assert.AreSame(c, method.DeclaringType); - Assert.AreEqual(Accessibility.Public, method.Accessibility); - Assert.AreEqual(SymbolKind.Constructor, method.SymbolKind); - Assert.IsFalse(method.IsVirtual); - Assert.IsFalse(method.IsStatic); - Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(0, method.GetAttributes().Count()); - Assert.IsTrue(method.HasBody); - Assert.IsNull(method.AccessorOwner); - Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(method.FullName, Is.EqualTo(typeof(SimplePublicClass).FullName + "..ctor")); + Assert.That(method.DeclaringType, Is.SameAs(c)); + Assert.That(method.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(method.SymbolKind, Is.EqualTo(SymbolKind.Constructor)); + Assert.That(!method.IsVirtual); + Assert.That(!method.IsStatic); + Assert.That(method.Parameters.Count, Is.EqualTo(0)); + Assert.That(method.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(method.HasBody); + Assert.That(method.AccessorOwner, Is.Null); + Assert.That(!method.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -137,26 +138,26 @@ public void SimplePublicClassDtorTest() ITypeDefinition c = GetTypeDefinition(typeof(SimplePublicClass)); IMethod method = c.Methods.Single(m => m.IsDestructor); - Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Finalize", method.FullName); - Assert.AreSame(c, method.DeclaringType); - Assert.AreEqual(Accessibility.Protected, method.Accessibility); - Assert.AreEqual(SymbolKind.Destructor, method.SymbolKind); - Assert.IsFalse(method.IsVirtual); - Assert.IsFalse(method.IsStatic); - Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(1, method.GetAttributes().Count()); - Assert.IsTrue(method.HasBody); - Assert.IsNull(method.AccessorOwner); - Assert.IsFalse(method.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(method.FullName, Is.EqualTo(typeof(SimplePublicClass).FullName + ".Finalize")); + Assert.That(method.DeclaringType, Is.SameAs(c)); + Assert.That(method.Accessibility, Is.EqualTo(Accessibility.Protected)); + Assert.That(method.SymbolKind, Is.EqualTo(SymbolKind.Destructor)); + Assert.That(!method.IsVirtual); + Assert.That(!method.IsStatic); + Assert.That(method.Parameters.Count, Is.EqualTo(0)); + Assert.That(method.GetAttributes().Count(), Is.EqualTo(1)); + Assert.That(method.HasBody); + Assert.That(method.AccessorOwner, Is.Null); + Assert.That(!method.HasAttribute(KnownAttribute.SpecialName)); } [Test] public void DynamicType() { ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); - Assert.AreEqual(SpecialType.Dynamic, testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType); - Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().ReturnType); - Assert.AreEqual(0, testClass.Properties.Single().GetAttributes().Count()); + Assert.That(testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType, Is.EqualTo(SpecialType.Dynamic)); + Assert.That(testClass.Properties.Single().ReturnType, Is.EqualTo(SpecialType.Dynamic)); + Assert.That(testClass.Properties.Single().GetAttributes().Count(), Is.EqualTo(0)); } [Test] @@ -165,26 +166,26 @@ public void DynamicTypeInGenerics() ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); - Assert.AreEqual("System.Collections.Generic.List`1[[dynamic]]", m1.ReturnType.ReflectionName); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic[]],[System.Object]]", m1.Parameters[0].Type.ReflectionName); + Assert.That(m1.ReturnType.ReflectionName, Is.EqualTo("System.Collections.Generic.List`1[[dynamic]]")); + Assert.That(m1.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Object],[dynamic[]],[System.Object]]")); IMethod m2 = testClass.Methods.Single(me => me.Name == "DynamicGenerics2"); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]", m2.Parameters[0].Type.ReflectionName); + Assert.That(m2.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Object],[dynamic],[System.Object]]")); IMethod m3 = testClass.Methods.Single(me => me.Name == "DynamicGenerics3"); - Assert.AreEqual("System.Action`3[[System.Int32],[dynamic],[System.Object]]", m3.Parameters[0].Type.ReflectionName); + Assert.That(m3.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Int32],[dynamic],[System.Object]]")); IMethod m4 = testClass.Methods.Single(me => me.Name == "DynamicGenerics4"); - Assert.AreEqual("System.Action`3[[System.Int32[]],[dynamic],[System.Object]]", m4.Parameters[0].Type.ReflectionName); + Assert.That(m4.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Int32[]],[dynamic],[System.Object]]")); IMethod m5 = testClass.Methods.Single(me => me.Name == "DynamicGenerics5"); - Assert.AreEqual("System.Action`3[[System.Int32*[]],[dynamic],[System.Object]]", m5.Parameters[0].Type.ReflectionName); + Assert.That(m5.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Int32*[]],[dynamic],[System.Object]]")); IMethod m6 = testClass.Methods.Single(me => me.Name == "DynamicGenerics6"); - Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]&", m6.Parameters[0].Type.ReflectionName); + Assert.That(m6.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Object],[dynamic],[System.Object]]&")); IMethod m7 = testClass.Methods.Single(me => me.Name == "DynamicGenerics7"); - Assert.AreEqual("System.Action`3[[System.Int32[][,]],[dynamic],[System.Object]]", m7.Parameters[0].Type.ReflectionName); + Assert.That(m7.Parameters[0].Type.ReflectionName, Is.EqualTo("System.Action`3[[System.Int32[][,]],[dynamic],[System.Object]]")); } [Test] @@ -192,7 +193,7 @@ public void DynamicParameterHasNoAttributes() { ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); - Assert.AreEqual(0, m1.Parameters[0].GetAttributes().Count()); + Assert.That(m1.Parameters[0].GetAttributes().Count(), Is.EqualTo(0)); } [Test] @@ -200,23 +201,23 @@ public void AssemblyAttribute() { var attributes = compilation.MainModule.GetAssemblyAttributes().ToList(); var typeTest = attributes.Single(a => a.AttributeType.FullName == typeof(TypeTestAttribute).FullName); - Assert.AreEqual(3, typeTest.FixedArguments.Length); + Assert.That(typeTest.FixedArguments.Length, Is.EqualTo(3)); // first argument is (int)42 - Assert.AreEqual(42, (int)typeTest.FixedArguments[0].Value); + Assert.That((int)typeTest.FixedArguments[0].Value, Is.EqualTo(42)); // second argument is typeof(System.Action<>) var ty = (IType)typeTest.FixedArguments[1].Value; - Assert.IsFalse(ty is ParameterizedType); // rt must not be constructed - it's just an unbound type - Assert.AreEqual("System.Action", ty.FullName); - Assert.AreEqual(1, ty.TypeParameterCount); + Assert.That(ty is ParameterizedType, Is.False); // rt must not be constructed - it's just an unbound type + Assert.That(ty.FullName, Is.EqualTo("System.Action")); + Assert.That(ty.TypeParameterCount, Is.EqualTo(1)); // third argument is typeof(IDictionary>) var crt = (ParameterizedType)typeTest.FixedArguments[2].Value; - Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); - Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); + Assert.That(crt.FullName, Is.EqualTo("System.Collections.Generic.IDictionary")); + Assert.That(crt.TypeArguments[0].FullName, Is.EqualTo("System.String")); // we know the name for TestAttribute, but not necessarily the namespace, as NUnit is not in the compilation - Assert.AreEqual("System.Collections.Generic.IList", crt.TypeArguments[1].FullName); + Assert.That(crt.TypeArguments[1].FullName, Is.EqualTo("System.Collections.Generic.IList")); var testAttributeType = ((ParameterizedType)crt.TypeArguments[1]).TypeArguments.Single(); - Assert.AreEqual("TestAttribute", testAttributeType.Name); - Assert.AreEqual(TypeKind.Unknown, testAttributeType.Kind); + Assert.That(testAttributeType.Name, Is.EqualTo("TestAttribute")); + Assert.That(testAttributeType.Kind, Is.EqualTo(TypeKind.Unknown)); // (more accurately, we know the namespace and reflection name if the type was loaded by cecil, // but not if we parsed it from C#) } @@ -226,18 +227,18 @@ public void TypeForwardedTo_Attribute() { var attributes = compilation.MainModule.GetAssemblyAttributes().ToList(); var forwardAttribute = attributes.Single(a => a.AttributeType.FullName == typeof(TypeForwardedToAttribute).FullName); - Assert.AreEqual(1, forwardAttribute.FixedArguments.Length); + Assert.That(forwardAttribute.FixedArguments.Length, Is.EqualTo(1)); var rt = (IType)forwardAttribute.FixedArguments[0].Value; - Assert.AreEqual("System.Func`2", rt.ReflectionName); + Assert.That(rt.ReflectionName, Is.EqualTo("System.Func`2")); } [Test] public void TestClassTypeParameters() { var testClass = GetTypeDefinition(typeof(GenericClass<,>)); - Assert.AreEqual(SymbolKind.TypeDefinition, testClass.TypeParameters[0].OwnerType); - Assert.AreEqual(SymbolKind.TypeDefinition, testClass.TypeParameters[1].OwnerType); - Assert.AreSame(testClass.TypeParameters[1], testClass.TypeParameters[0].DirectBaseTypes.First()); + Assert.That(testClass.TypeParameters[0].OwnerType, Is.EqualTo(SymbolKind.TypeDefinition)); + Assert.That(testClass.TypeParameters[1].OwnerType, Is.EqualTo(SymbolKind.TypeDefinition)); + Assert.That(testClass.TypeParameters[0].DirectBaseTypes.First(), Is.SameAs(testClass.TypeParameters[1])); } [Test] @@ -246,13 +247,13 @@ public void TestMethod() var testClass = GetTypeDefinition(typeof(GenericClass<,>)); IMethod m = testClass.Methods.Single(me => me.Name == "TestMethod"); - Assert.AreEqual("K", m.TypeParameters[0].Name); - Assert.AreEqual("V", m.TypeParameters[1].Name); - Assert.AreEqual(SymbolKind.Method, m.TypeParameters[0].OwnerType); - Assert.AreEqual(SymbolKind.Method, m.TypeParameters[1].OwnerType); + Assert.That(m.TypeParameters[0].Name, Is.EqualTo("K")); + Assert.That(m.TypeParameters[1].Name, Is.EqualTo("V")); + Assert.That(m.TypeParameters[0].OwnerType, Is.EqualTo(SymbolKind.Method)); + Assert.That(m.TypeParameters[1].OwnerType, Is.EqualTo(SymbolKind.Method)); - Assert.AreEqual("System.IComparable`1[[``1]]", m.TypeParameters[0].DirectBaseTypes.First().ReflectionName); - Assert.AreSame(m.TypeParameters[0], m.TypeParameters[1].DirectBaseTypes.First()); + Assert.That(m.TypeParameters[0].DirectBaseTypes.First().ReflectionName, Is.EqualTo("System.IComparable`1[[``1]]")); + Assert.That(m.TypeParameters[1].DirectBaseTypes.First(), Is.SameAs(m.TypeParameters[0])); } [Test] @@ -261,16 +262,16 @@ public void GetIndex() var testClass = GetTypeDefinition(typeof(GenericClass<,>)); IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex"); - Assert.AreEqual("T", m.TypeParameters[0].Name); - Assert.AreEqual(SymbolKind.Method, m.TypeParameters[0].OwnerType); - Assert.AreSame(m, m.TypeParameters[0].Owner); + Assert.That(m.TypeParameters[0].Name, Is.EqualTo("T")); + Assert.That(m.TypeParameters[0].OwnerType, Is.EqualTo(SymbolKind.Method)); + Assert.That(m.TypeParameters[0].Owner, Is.SameAs(m)); ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First(); - Assert.AreEqual("IEquatable", constraint.Name); - Assert.AreEqual(1, constraint.TypeParameterCount); - Assert.AreEqual(1, constraint.TypeArguments.Count); - Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]); - Assert.AreSame(m.TypeParameters[0], m.Parameters[0].Type); + Assert.That(constraint.Name, Is.EqualTo("IEquatable")); + Assert.That(constraint.TypeParameterCount, Is.EqualTo(1)); + Assert.That(constraint.TypeArguments.Count, Is.EqualTo(1)); + Assert.That(constraint.TypeArguments[0], Is.SameAs(m.TypeParameters[0])); + Assert.That(m.Parameters[0].Type, Is.SameAs(m.TypeParameters[0])); } [Test] @@ -283,16 +284,16 @@ public void GetIndexSpecializedTypeParameter() null )); - Assert.AreEqual("T", m.TypeParameters[0].Name); - Assert.AreEqual(SymbolKind.Method, m.TypeParameters[0].OwnerType); - Assert.AreSame(m, m.TypeParameters[0].Owner); + Assert.That(m.TypeParameters[0].Name, Is.EqualTo("T")); + Assert.That(m.TypeParameters[0].OwnerType, Is.EqualTo(SymbolKind.Method)); + Assert.That(m.TypeParameters[0].Owner, Is.SameAs(m)); ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First(); - Assert.AreEqual("IEquatable", constraint.Name); - Assert.AreEqual(1, constraint.TypeParameterCount); - Assert.AreEqual(1, constraint.TypeArguments.Count); - Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]); - Assert.AreSame(m.TypeParameters[0], m.Parameters[0].Type); + Assert.That(constraint.Name, Is.EqualTo("IEquatable")); + Assert.That(constraint.TypeParameterCount, Is.EqualTo(1)); + Assert.That(constraint.TypeArguments.Count, Is.EqualTo(1)); + Assert.That(constraint.TypeArguments[0], Is.SameAs(m.TypeParameters[0])); + Assert.That(m.Parameters[0].Type, Is.SameAs(m.TypeParameters[0])); } [Test] @@ -318,7 +319,7 @@ public void GetIndexDoubleSpecialization() new[] { compilation.FindType(KnownTypeCode.String), compilation.FindType(KnownTypeCode.Int32) }, new[] { compilation.FindType(KnownTypeCode.Int32) } )); - Assert.AreEqual(m12, m2); + Assert.That(m2, Is.EqualTo(m12)); } [Test] @@ -326,18 +327,18 @@ public void SpecializedMethod_AccessorOwner() { // NRefactory bug #143 - Accessor Owner throws null reference exception in some cases now var method = compilation.FindType(typeof(GenericClass)).GetMethods(m => m.Name == "GetIndex").Single(); - Assert.IsNull(method.AccessorOwner); + Assert.That(method.AccessorOwner, Is.Null); } [Test] public void Specialized_GetIndex_ToMemberReference() { var method = compilation.FindType(typeof(GenericClass)).GetMethods(m => m.Name == "GetIndex").Single(); - Assert.AreSame(method.TypeParameters[0], method.Parameters[0].Type); - Assert.AreSame(method, method.TypeParameters[0].Owner); - Assert.IsInstanceOf(method); - //Assert.IsFalse(method.IsParameterized); // the method itself is not specialized - Assert.AreEqual(method.TypeParameters, method.TypeArguments); + Assert.That(method.Parameters[0].Type, Is.SameAs(method.TypeParameters[0])); + Assert.That(method.TypeParameters[0].Owner, Is.SameAs(method)); + Assert.That(method, Is.InstanceOf()); + //Assert.That(!method.IsParameterized); // the method itself is not specialized + Assert.That(method.TypeArguments, Is.EqualTo(method.TypeParameters)); } [Test] @@ -347,23 +348,23 @@ public void Specialized_GetIndex_SpecializeWithIdentityHasNoEffect() IType[] methodTypeArguments = { DummyTypeParameter.GetMethodTypeParameter(0) }; var method = genericClass.GetMethods(methodTypeArguments, m => m.Name == "GetIndex").Single(); // GenericClass.GetIndex() - Assert.AreSame(method, method.TypeParameters[0].Owner); - Assert.AreNotEqual(method.TypeParameters[0], method.TypeArguments[0]); - Assert.IsNull(((ITypeParameter)method.TypeArguments[0]).Owner); + Assert.That(method.TypeParameters[0].Owner, Is.SameAs(method)); + Assert.That(method.TypeArguments[0], Is.Not.EqualTo(method.TypeParameters[0])); + Assert.That(((ITypeParameter)method.TypeArguments[0]).Owner, Is.Null); // Now apply identity substitution: var method2 = method.Specialize(TypeParameterSubstitution.Identity); - Assert.AreSame(method2, method2.TypeParameters[0].Owner); - Assert.AreNotEqual(method2.TypeParameters[0], method2.TypeArguments[0]); - Assert.IsNull(((ITypeParameter)method2.TypeArguments[0]).Owner); + Assert.That(method2.TypeParameters[0].Owner, Is.SameAs(method2)); + Assert.That(method2.TypeArguments[0], Is.Not.EqualTo(method2.TypeParameters[0])); + Assert.That(((ITypeParameter)method2.TypeArguments[0]).Owner, Is.Null); - Assert.AreEqual(method, method2); + Assert.That(method2, Is.EqualTo(method)); } [Test] public void GenericEnum() { var testClass = GetTypeDefinition(typeof(GenericClass<,>.NestedEnum)); - Assert.AreEqual(2, testClass.TypeParameterCount); + Assert.That(testClass.TypeParameterCount, Is.EqualTo(2)); } [Test] @@ -372,7 +373,7 @@ public void FieldInGenericClassWithNestedEnumType() var testClass = GetTypeDefinition(typeof(GenericClass<,>)); var enumClass = GetTypeDefinition(typeof(GenericClass<,>.NestedEnum)); var field = testClass.Fields.Single(f => f.Name == "EnumField"); - Assert.AreEqual(new ParameterizedType(enumClass, testClass.TypeParameters), field.ReturnType); + Assert.That(field.ReturnType, Is.EqualTo(new ParameterizedType(enumClass, testClass.TypeParameters))); } [Test] @@ -380,7 +381,7 @@ public void GenericEnumMemberReturnType() { var enumClass = GetTypeDefinition(typeof(GenericClass<,>.NestedEnum)); var field = enumClass.Fields.Single(f => f.Name == "EnumMember"); - Assert.AreEqual(new ParameterizedType(enumClass, enumClass.TypeParameters), field.ReturnType); + Assert.That(field.ReturnType, Is.EqualTo(new ParameterizedType(enumClass, enumClass.TypeParameters))); } [Test] @@ -388,11 +389,11 @@ public void PropertyWithProtectedSetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithProtectedSetter"); - Assert.IsTrue(p.CanGet); - Assert.IsTrue(p.CanSet); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.AreEqual(Accessibility.Protected, p.Setter.Accessibility); + Assert.That(p.CanGet); + Assert.That(p.CanSet); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Protected)); } [Test] @@ -400,15 +401,15 @@ public void PropertyWithPrivateSetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithPrivateSetter"); - Assert.IsTrue(p.CanGet); - Assert.IsTrue(p.CanSet); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.AreEqual(Accessibility.Private, p.Setter.Accessibility); - Assert.IsTrue(p.Getter.HasBody); - Assert.IsFalse(p.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsFalse(p.Getter.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsFalse(p.Setter.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(p.CanGet); + Assert.That(p.CanSet); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Private)); + Assert.That(p.Getter.HasBody); + Assert.That(!p.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(!p.Getter.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(!p.Setter.HasAttribute(KnownAttribute.SpecialName)); } [Test] @@ -416,12 +417,12 @@ public void PropertyWithPrivateGetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithPrivateGetter"); - Assert.IsTrue(p.CanGet); - Assert.IsTrue(p.CanSet); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(Accessibility.Private, p.Getter.Accessibility); - Assert.AreEqual(Accessibility.Public, p.Setter.Accessibility); - Assert.IsTrue(p.Getter.HasBody); + Assert.That(p.CanGet); + Assert.That(p.CanSet); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Private)); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.HasBody); } [Test] @@ -429,11 +430,11 @@ public void PropertyWithoutSetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithoutSetter"); - Assert.IsTrue(p.CanGet); - Assert.IsFalse(p.CanSet); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.IsNull(p.Setter); + Assert.That(p.CanGet); + Assert.That(!p.CanSet); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter, Is.Null); } [Test] @@ -441,8 +442,8 @@ public void Indexer() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); - Assert.AreEqual("Item", p.Name); - Assert.AreEqual(new[] { "index" }, p.Parameters.Select(x => x.Name).ToArray()); + Assert.That(p.Name, Is.EqualTo("Item")); + Assert.That(p.Parameters.Select(x => x.Name).ToArray(), Is.EqualTo(new[] { "index" })); } [Test] @@ -450,13 +451,13 @@ public void IndexerGetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); - Assert.IsTrue(p.CanGet); - Assert.AreEqual(SymbolKind.Accessor, p.Getter.SymbolKind); - Assert.AreEqual("get_Item", p.Getter.Name); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.AreEqual(new[] { "index" }, p.Getter.Parameters.Select(x => x.Name).ToArray()); - Assert.AreEqual("System.String", p.Getter.ReturnType.ReflectionName); - Assert.AreEqual(p, p.Getter.AccessorOwner); + Assert.That(p.CanGet); + Assert.That(p.Getter.SymbolKind, Is.EqualTo(SymbolKind.Accessor)); + Assert.That(p.Getter.Name, Is.EqualTo("get_Item")); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.Parameters.Select(x => x.Name).ToArray(), Is.EqualTo(new[] { "index" })); + Assert.That(p.Getter.ReturnType.ReflectionName, Is.EqualTo("System.String")); + Assert.That(p.Getter.AccessorOwner, Is.EqualTo(p)); } [Test] @@ -464,12 +465,12 @@ public void IndexerSetter() { var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); - Assert.IsTrue(p.CanSet); - Assert.AreEqual(SymbolKind.Accessor, p.Setter.SymbolKind); - Assert.AreEqual("set_Item", p.Setter.Name); - Assert.AreEqual(Accessibility.Public, p.Setter.Accessibility); - Assert.AreEqual(new[] { "index", "value" }, p.Setter.Parameters.Select(x => x.Name).ToArray()); - Assert.AreEqual(TypeKind.Void, p.Setter.ReturnType.Kind); + Assert.That(p.CanSet); + Assert.That(p.Setter.SymbolKind, Is.EqualTo(SymbolKind.Accessor)); + Assert.That(p.Setter.Name, Is.EqualTo("set_Item")); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter.Parameters.Select(x => x.Name).ToArray(), Is.EqualTo(new[] { "index", "value" })); + Assert.That(p.Setter.ReturnType.Kind, Is.EqualTo(TypeKind.Void)); } [Test] @@ -477,19 +478,19 @@ public void GenericPropertyGetter() { var type = compilation.FindType(typeof(GenericClass)); var prop = type.GetProperties(p => p.Name == "Property").Single(); - Assert.AreEqual("System.String", prop.Getter.ReturnType.ReflectionName); - Assert.IsTrue(prop.Getter.IsAccessor); - Assert.AreEqual(prop, prop.Getter.AccessorOwner); + Assert.That(prop.Getter.ReturnType.ReflectionName, Is.EqualTo("System.String")); + Assert.That(prop.Getter.IsAccessor); + Assert.That(prop.Getter.AccessorOwner, Is.EqualTo(prop)); } [Test] public void EnumTest() { var e = GetTypeDefinition(typeof(MyEnum)); - Assert.AreEqual(TypeKind.Enum, e.Kind); - Assert.AreEqual(false, e.IsReferenceType); - Assert.AreEqual("System.Int16", e.EnumUnderlyingType.ReflectionName); - Assert.AreEqual(new[] { "System.Enum" }, e.DirectBaseTypes.Select(t => t.ReflectionName).ToArray()); + Assert.That(e.Kind, Is.EqualTo(TypeKind.Enum)); + Assert.That(e.IsReferenceType, Is.EqualTo(false)); + Assert.That(e.EnumUnderlyingType.ReflectionName, Is.EqualTo("System.Int16")); + Assert.That(e.DirectBaseTypes.Select(t => t.ReflectionName).ToArray(), Is.EqualTo(new[] { "System.Enum" })); } [Test] @@ -498,39 +499,39 @@ public void EnumFieldsTest() var e = GetTypeDefinition(typeof(MyEnum)); IField valueField = e.Fields.First(); IField[] fields = e.Fields.Skip(1).ToArray(); - Assert.AreEqual(5, fields.Length); + Assert.That(fields.Length, Is.EqualTo(5)); - Assert.AreEqual("value__", valueField.Name); - Assert.AreEqual(GetTypeDefinition(typeof(short)), valueField.Type); - Assert.AreEqual(Accessibility.Public, valueField.Accessibility); - Assert.AreEqual(null, valueField.GetConstantValue()); - Assert.IsFalse(valueField.IsConst); - Assert.IsFalse(valueField.IsStatic); + Assert.That(valueField.Name, Is.EqualTo("value__")); + Assert.That(valueField.Type, Is.EqualTo(GetTypeDefinition(typeof(short)))); + Assert.That(valueField.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(valueField.GetConstantValue(), Is.EqualTo(null)); + Assert.That(!valueField.IsConst); + Assert.That(!valueField.IsStatic); foreach (IField f in fields) { - Assert.IsTrue(f.IsStatic); - Assert.IsTrue(f.IsConst); - Assert.AreEqual(Accessibility.Public, f.Accessibility); - Assert.AreSame(e, f.Type); - Assert.AreEqual(typeof(short), f.GetConstantValue().GetType()); + Assert.That(f.IsStatic); + Assert.That(f.IsConst); + Assert.That(f.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(f.Type, Is.SameAs(e)); + Assert.That(f.GetConstantValue().GetType(), Is.EqualTo(typeof(short))); } - Assert.AreEqual("First", fields[0].Name); - Assert.AreEqual(0, fields[0].GetConstantValue()); + Assert.That(fields[0].Name, Is.EqualTo("First")); + Assert.That(fields[0].GetConstantValue(), Is.EqualTo(0)); - Assert.AreEqual("Second", fields[1].Name); - Assert.AreSame(e, fields[1].Type); - Assert.AreEqual(1, fields[1].GetConstantValue()); + Assert.That(fields[1].Name, Is.EqualTo("Second")); + Assert.That(fields[1].Type, Is.SameAs(e)); + Assert.That(fields[1].GetConstantValue(), Is.EqualTo(1)); - Assert.AreEqual("Flag1", fields[2].Name); - Assert.AreEqual(0x10, fields[2].GetConstantValue()); + Assert.That(fields[2].Name, Is.EqualTo("Flag1")); + Assert.That(fields[2].GetConstantValue(), Is.EqualTo(0x10)); - Assert.AreEqual("Flag2", fields[3].Name); - Assert.AreEqual(0x20, fields[3].GetConstantValue()); + Assert.That(fields[3].Name, Is.EqualTo("Flag2")); + Assert.That(fields[3].GetConstantValue(), Is.EqualTo(0x20)); - Assert.AreEqual("CombinedFlags", fields[4].Name); - Assert.AreEqual(0x30, fields[4].GetConstantValue()); + Assert.That(fields[4].Name, Is.EqualTo("CombinedFlags")); + Assert.That(fields[4].GetConstantValue(), Is.EqualTo(0x30)); } [Test] @@ -539,14 +540,12 @@ public void GetNestedTypesFromBaseClassTest() ITypeDefinition d = GetTypeDefinition(typeof(Derived<,>)); IType pBase = d.DirectBaseTypes.Single(); - Assert.AreEqual(typeof(Base<>).FullName + "[[`1]]", pBase.ReflectionName); + Assert.That(pBase.ReflectionName, Is.EqualTo(typeof(Base<>).FullName + "[[`1]]")); // Base[`1].GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } - Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, - pBase.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); + Assert.That(pBase.GetNestedTypes().Select(n => n.ReflectionName).ToArray(), Is.EqualTo(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" })); // Derived.GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } - Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, - d.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); + Assert.That(d.GetNestedTypes().Select(n => n.ReflectionName).ToArray(), Is.EqualTo(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" })); // This is 'leaking' the type parameter from B as is usual when retrieving any members from an unbound type. } @@ -555,8 +554,7 @@ public void ParameterizedTypeGetNestedTypesFromBaseClassTest() { // Derived[string,int].GetNestedTypes() = { Base`1+Nested`1[int, unbound] } var d = compilation.FindType(typeof(Derived)); - Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[System.Int32],[]]" }, - d.GetNestedTypes().Select(n => n.ReflectionName).ToArray()); + Assert.That(d.GetNestedTypes().Select(n => n.ReflectionName).ToArray(), Is.EqualTo(new[] { typeof(Base<>.Nested<>).FullName + "[[System.Int32],[]]" })); } [Test] @@ -564,12 +562,11 @@ public void ConstraintsOnOverrideAreInherited() { ITypeDefinition d = GetTypeDefinition(typeof(Derived<,>)); ITypeParameter tp = d.Methods.Single(m => m.Name == "GenericMethodWithConstraints").TypeParameters.Single(); - Assert.AreEqual("Y", tp.Name); - Assert.IsFalse(tp.HasValueTypeConstraint); - Assert.IsFalse(tp.HasReferenceTypeConstraint); - Assert.IsTrue(tp.HasDefaultConstructorConstraint); - Assert.AreEqual(new string[] { "System.Collections.Generic.IComparer`1[[`1]]", "System.Object" }, - tp.DirectBaseTypes.Select(t => t.ReflectionName).ToArray()); + Assert.That(tp.Name, Is.EqualTo("Y")); + Assert.That(!tp.HasValueTypeConstraint); + Assert.That(!tp.HasReferenceTypeConstraint); + Assert.That(tp.HasDefaultConstructorConstraint); + Assert.That(tp.DirectBaseTypes.Select(t => t.ReflectionName).ToArray(), Is.EqualTo(new string[] { "System.Collections.Generic.IComparer`1[[`1]]", "System.Object" })); } [Test] @@ -577,16 +574,16 @@ public void DtorInDerivedClass() { ITypeDefinition c = GetTypeDefinition(typeof(Derived<,>)); IMethod method = c.Methods.Single(m => m.IsDestructor); - Assert.AreEqual(c.FullName + ".Finalize", method.FullName); - Assert.AreSame(c, method.DeclaringType); - Assert.AreEqual(Accessibility.Protected, method.Accessibility); - Assert.AreEqual(SymbolKind.Destructor, method.SymbolKind); - Assert.IsFalse(method.IsVirtual); - Assert.IsFalse(method.IsStatic); - Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(0, method.GetAttributes().Count()); - Assert.IsTrue(method.HasBody); - Assert.IsNull(method.AccessorOwner); + Assert.That(method.FullName, Is.EqualTo(c.FullName + ".Finalize")); + Assert.That(method.DeclaringType, Is.SameAs(c)); + Assert.That(method.Accessibility, Is.EqualTo(Accessibility.Protected)); + Assert.That(method.SymbolKind, Is.EqualTo(SymbolKind.Destructor)); + Assert.That(!method.IsVirtual); + Assert.That(!method.IsStatic); + Assert.That(method.Parameters.Count, Is.EqualTo(0)); + Assert.That(method.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(method.HasBody); + Assert.That(method.AccessorOwner, Is.Null); } [Test] @@ -594,102 +591,102 @@ public void PrivateFinalizeMethodIsNotADtor() { ITypeDefinition c = GetTypeDefinition(typeof(TypeTestAttribute)); IMethod method = c.Methods.Single(m => m.Name == "Finalize"); - Assert.AreEqual(c.FullName + ".Finalize", method.FullName); - Assert.AreSame(c, method.DeclaringType); - Assert.AreEqual(Accessibility.Private, method.Accessibility); - Assert.AreEqual(SymbolKind.Method, method.SymbolKind); - Assert.IsFalse(method.IsVirtual); - Assert.IsFalse(method.IsStatic); - Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(0, method.GetAttributes().Count()); - Assert.IsTrue(method.HasBody); - Assert.IsNull(method.AccessorOwner); + Assert.That(method.FullName, Is.EqualTo(c.FullName + ".Finalize")); + Assert.That(method.DeclaringType, Is.SameAs(c)); + Assert.That(method.Accessibility, Is.EqualTo(Accessibility.Private)); + Assert.That(method.SymbolKind, Is.EqualTo(SymbolKind.Method)); + Assert.That(!method.IsVirtual); + Assert.That(!method.IsStatic); + Assert.That(method.Parameters.Count, Is.EqualTo(0)); + Assert.That(method.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(method.HasBody); + Assert.That(method.AccessorOwner, Is.Null); } [Test] public void DefaultConstructorAddedToStruct() { var ctors = compilation.FindType(typeof(MyStructWithCtor)).GetConstructors(); - Assert.AreEqual(2, ctors.Count()); - Assert.IsFalse(ctors.Any(c => c.IsStatic)); - Assert.IsTrue(ctors.All(c => c.ReturnType.Kind == TypeKind.Void)); - Assert.IsTrue(ctors.All(c => c.Accessibility == Accessibility.Public)); + Assert.That(ctors.Count(), Is.EqualTo(2)); + Assert.That(!ctors.Any(c => c.IsStatic)); + Assert.That(ctors.All(c => c.ReturnType.Kind == TypeKind.Void)); + Assert.That(ctors.All(c => c.Accessibility == Accessibility.Public)); } [Test] public void NoDefaultConstructorAddedToStruct() { var ctors = compilation.FindType(typeof(MyStructWithDefaultCtor)).GetConstructors(); - Assert.AreEqual(1, ctors.Count()); - Assert.IsFalse(ctors.Any(c => c.IsStatic)); - Assert.IsTrue(ctors.All(c => c.ReturnType.Kind == TypeKind.Void)); - Assert.IsTrue(ctors.All(c => c.Accessibility == Accessibility.Public)); + Assert.That(ctors.Count(), Is.EqualTo(1)); + Assert.That(!ctors.Any(c => c.IsStatic)); + Assert.That(ctors.All(c => c.ReturnType.Kind == TypeKind.Void)); + Assert.That(ctors.All(c => c.Accessibility == Accessibility.Public)); } [Test] public void NoDefaultConstructorAddedToClass() { var ctors = compilation.FindType(typeof(MyClassWithCtor)).GetConstructors(); - Assert.AreEqual(Accessibility.Private, ctors.Single().Accessibility); - Assert.AreEqual(1, ctors.Single().Parameters.Count); + Assert.That(ctors.Single().Accessibility, Is.EqualTo(Accessibility.Private)); + Assert.That(ctors.Single().Parameters.Count, Is.EqualTo(1)); } [Test] public void DefaultConstructorOnAbstractClassIsProtected() { var ctors = compilation.FindType(typeof(AbstractClass)).GetConstructors(); - Assert.AreEqual(0, ctors.Single().Parameters.Count); - Assert.AreEqual(Accessibility.Protected, ctors.Single().Accessibility); + Assert.That(ctors.Single().Parameters.Count, Is.EqualTo(0)); + Assert.That(ctors.Single().Accessibility, Is.EqualTo(Accessibility.Protected)); } [Test] public void SerializableAttribute() { IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).GetAttributes().Single(); - Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.FullName); + Assert.That(attr.AttributeType.FullName, Is.EqualTo("System.SerializableAttribute")); } [Test] public void NonSerializedAttribute() { IField field = GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); - Assert.AreEqual("System.NonSerializedAttribute", field.GetAttributes().Single().AttributeType.FullName); + Assert.That(field.GetAttributes().Single().AttributeType.FullName, Is.EqualTo("System.NonSerializedAttribute")); } [Test] public void ExplicitStructLayoutAttribute() { IAttribute attr = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).GetAttributes().Single(); - Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.FullName); + Assert.That(attr.AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.StructLayoutAttribute")); var arg1 = attr.FixedArguments.Single(); - Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName); - Assert.AreEqual((int)LayoutKind.Explicit, arg1.Value); + Assert.That(arg1.Type.FullName, Is.EqualTo("System.Runtime.InteropServices.LayoutKind")); + Assert.That(arg1.Value, Is.EqualTo((int)LayoutKind.Explicit)); var arg2 = attr.NamedArguments[0]; - Assert.AreEqual("CharSet", arg2.Name); - Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Type.FullName); - Assert.AreEqual((int)CharSet.Unicode, arg2.Value); + Assert.That(arg2.Name, Is.EqualTo("CharSet")); + Assert.That(arg2.Type.FullName, Is.EqualTo("System.Runtime.InteropServices.CharSet")); + Assert.That(arg2.Value, Is.EqualTo((int)CharSet.Unicode)); var arg3 = attr.NamedArguments[1]; - Assert.AreEqual("Pack", arg3.Name); - Assert.AreEqual("System.Int32", arg3.Type.FullName); - Assert.AreEqual(8, arg3.Value); + Assert.That(arg3.Name, Is.EqualTo("Pack")); + Assert.That(arg3.Type.FullName, Is.EqualTo("System.Int32")); + Assert.That(arg3.Value, Is.EqualTo(8)); } [Test] public void FieldOffsetAttribute() { IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName); + Assert.That(field.GetAttributes().Single().AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.FieldOffsetAttribute")); var arg = field.GetAttributes().Single().FixedArguments.Single(); - Assert.AreEqual("System.Int32", arg.Type.FullName); - Assert.AreEqual(0, arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.Int32")); + Assert.That(arg.Value, Is.EqualTo(0)); field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName); + Assert.That(field.GetAttributes().Single().AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.FieldOffsetAttribute")); arg = field.GetAttributes().Single().FixedArguments.Single(); - Assert.AreEqual("System.Int32", arg.Type.FullName); - Assert.AreEqual(100, arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.Int32")); + Assert.That(arg.Value, Is.EqualTo(100)); } [Test] @@ -697,9 +694,9 @@ public void DllImportAttribute() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute dllImport = method.GetAttributes().Single(); - Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName); - Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value); - Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value); + Assert.That(dllImport.AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.DllImportAttribute")); + Assert.That(dllImport.FixedArguments[0].Value, Is.EqualTo("unmanaged.dll")); + Assert.That(dllImport.NamedArguments.Single().Value, Is.EqualTo((int)CharSet.Unicode)); } [Test] @@ -707,9 +704,9 @@ public void DllImportAttributeWithPreserveSigFalse() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DoNotPreserveSig"); IAttribute dllImport = method.GetAttributes().Single(); - Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName); - Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value); - Assert.AreEqual(false, dllImport.NamedArguments.Single().Value); + Assert.That(dllImport.AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.DllImportAttribute")); + Assert.That(dllImport.FixedArguments[0].Value, Is.EqualTo("unmanaged.dll")); + Assert.That(dllImport.NamedArguments.Single().Value, Is.EqualTo(false)); } [Test] @@ -717,20 +714,20 @@ public void PreserveSigAttribute() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "PreserveSigAsAttribute"); IAttribute preserveSig = method.GetAttributes().Single(); - Assert.AreEqual("System.Runtime.InteropServices.PreserveSigAttribute", preserveSig.AttributeType.FullName); - Assert.IsTrue(preserveSig.FixedArguments.Length == 0); - Assert.IsTrue(preserveSig.NamedArguments.Length == 0); + Assert.That(preserveSig.AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.PreserveSigAttribute")); + Assert.That(preserveSig.FixedArguments.Length == 0); + Assert.That(preserveSig.NamedArguments.Length == 0); } [Test] public void InOutParametersOnRefMethod() { IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); - Assert.AreEqual(ReferenceKind.Ref, p.ReferenceKind); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.Ref)); var attr = p.GetAttributes().ToList(); - Assert.AreEqual(2, attr.Count); - Assert.AreEqual("System.Runtime.InteropServices.InAttribute", attr[0].AttributeType.FullName); - Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", attr[1].AttributeType.FullName); + Assert.That(attr.Count, Is.EqualTo(2)); + Assert.That(attr[0].AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.InAttribute")); + Assert.That(attr[1].AttributeType.FullName, Is.EqualTo("System.Runtime.InteropServices.OutAttribute")); } [Test] @@ -738,70 +735,70 @@ public void MarshalAsAttributeOnMethod() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute marshalAs = method.GetReturnTypeAttributes().Single(); - Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.FixedArguments.Single().Value); + Assert.That(marshalAs.FixedArguments.Single().Value, Is.EqualTo((int)UnmanagedType.Bool)); } [Test] public void MethodWithOutParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.Out, p.ReferenceKind); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.Out)); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.Type.Kind == TypeKind.ByReference); } [Test] public void MethodWithRefParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithRefParameter").Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.Ref, p.ReferenceKind); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.Ref)); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.Type.Kind == TypeKind.ByReference); } [Test] public void MethodWithInParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithInParameter").Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.In, p.ReferenceKind); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.In)); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.Type.Kind == TypeKind.ByReference); } [Test] public void MethodWithParamsArray() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsTrue(p.IsParams); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.IsTrue(p.Type.Kind == TypeKind.Array); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(p.IsParams); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.Type.Kind == TypeKind.Array); } [Test] public void MethodWithOptionalParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.AreEqual(4, p.GetConstantValue()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.GetConstantValue(), Is.EqualTo(4)); } [Test] public void MethodWithExplicitOptionalParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithExplicitOptionalParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsFalse(p.HasConstantValueInSignature); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(!p.HasConstantValueInSignature); // explicit optional parameter appears in type system if it's read from C#, but not when read from IL //Assert.AreEqual(1, p.GetAttributes().Count()); } @@ -810,103 +807,103 @@ public void MethodWithExplicitOptionalParameter() public void MethodWithEnumOptionalParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithEnumOptionalParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.GetConstantValue()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.GetConstantValue(), Is.EqualTo((int)StringComparison.OrdinalIgnoreCase)); } [Test] public void MethodWithOptionalNullableParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(0, p.GetAttributes().Count()); - Assert.IsNull(p.GetConstantValue()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(p.GetConstantValue(), Is.Null); } [Test] public void MethodWithOptionalLongParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalLongParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(1L, p.GetConstantValue()); - Assert.AreEqual(typeof(long), p.GetConstantValue().GetType()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetConstantValue(), Is.EqualTo(1L)); + Assert.That(p.GetConstantValue().GetType(), Is.EqualTo(typeof(long))); } [Test] public void MethodWithOptionalNullableLongParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalNullableLongParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(1L, p.GetConstantValue()); - Assert.AreEqual(typeof(long), p.GetConstantValue().GetType()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetConstantValue(), Is.EqualTo(1L)); + Assert.That(p.GetConstantValue().GetType(), Is.EqualTo(typeof(long))); } [Test] public void MethodWithOptionalDecimalParameter() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalDecimalParameter").Parameters.Single(); - Assert.IsTrue(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.IsTrue(p.HasConstantValueInSignature); - Assert.AreEqual(1M, p.GetConstantValue()); - Assert.AreEqual(typeof(decimal), p.GetConstantValue().GetType()); + Assert.That(p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.HasConstantValueInSignature); + Assert.That(p.GetConstantValue(), Is.EqualTo(1M)); + Assert.That(p.GetConstantValue().GetType(), Is.EqualTo(typeof(decimal))); } [Test] public void VarArgsMethod() { IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "VarArgsMethod").Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.AreEqual(TypeKind.ArgList, p.Type.Kind); - Assert.AreEqual("", p.Name); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.Type.Kind, Is.EqualTo(TypeKind.ArgList)); + Assert.That(p.Name, Is.EqualTo("")); } [Test] public void VarArgsCtor() { IParameter p = GetTypeDefinition(typeof(VarArgsCtor)).Methods.Single(m => m.IsConstructor).Parameters.Single(); - Assert.IsFalse(p.IsOptional); - Assert.AreEqual(ReferenceKind.None, p.ReferenceKind); - Assert.IsFalse(p.IsParams); - Assert.AreEqual(TypeKind.ArgList, p.Type.Kind); - Assert.AreEqual("", p.Name); + Assert.That(!p.IsOptional); + Assert.That(p.ReferenceKind, Is.EqualTo(ReferenceKind.None)); + Assert.That(!p.IsParams); + Assert.That(p.Type.Kind, Is.EqualTo(TypeKind.ArgList)); + Assert.That(p.Name, Is.EqualTo("")); } [Test] public void GenericDelegate_Variance() { ITypeDefinition type = GetTypeDefinition(typeof(GenericDelegate<,>)); - Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance); - Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance); + Assert.That(type.TypeParameters[0].Variance, Is.EqualTo(VarianceModifier.Contravariant)); + Assert.That(type.TypeParameters[1].Variance, Is.EqualTo(VarianceModifier.Covariant)); - Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].DirectBaseTypes.FirstOrDefault()); + Assert.That(type.TypeParameters[0].DirectBaseTypes.FirstOrDefault(), Is.SameAs(type.TypeParameters[1])); } [Test] public void GenericDelegate_ReferenceTypeConstraints() { ITypeDefinition type = GetTypeDefinition(typeof(GenericDelegate<,>)); - Assert.IsFalse(type.TypeParameters[0].HasReferenceTypeConstraint); - Assert.IsTrue(type.TypeParameters[1].HasReferenceTypeConstraint); + Assert.That(!type.TypeParameters[0].HasReferenceTypeConstraint); + Assert.That(type.TypeParameters[1].HasReferenceTypeConstraint); - Assert.IsNull(type.TypeParameters[0].IsReferenceType); - Assert.AreEqual(true, type.TypeParameters[1].IsReferenceType); + Assert.That(type.TypeParameters[0].IsReferenceType, Is.Null); + Assert.That(type.TypeParameters[1].IsReferenceType, Is.EqualTo(true)); } [Test] @@ -914,9 +911,9 @@ public void GenericDelegate_GetInvokeMethod() { IType type = compilation.FindType(typeof(GenericDelegate)); IMethod m = type.GetDelegateInvokeMethod(); - Assert.AreEqual("Invoke", m.Name); - Assert.AreEqual("System.Object", m.ReturnType.FullName); - Assert.AreEqual("System.String", m.Parameters[0].Type.FullName); + Assert.That(m.Name, Is.EqualTo("Invoke")); + Assert.That(m.ReturnType.FullName, Is.EqualTo("System.Object")); + Assert.That(m.Parameters[0].Type.FullName, Is.EqualTo("System.String")); } [Test] @@ -924,14 +921,14 @@ public void ComInterfaceTest() { ITypeDefinition type = GetTypeDefinition(typeof(IAssemblyEnum)); // [ComImport] - Assert.AreEqual(1, type.GetAttributes().Count(a => a.AttributeType.FullName == typeof(ComImportAttribute).FullName)); + Assert.That(type.GetAttributes().Count(a => a.AttributeType.FullName == typeof(ComImportAttribute).FullName), Is.EqualTo(1)); IMethod m = type.Methods.Single(); - Assert.AreEqual("GetNextAssembly", m.Name); - Assert.AreEqual(Accessibility.Public, m.Accessibility); - Assert.IsTrue(m.IsAbstract); - Assert.IsFalse(m.IsVirtual); - Assert.IsFalse(m.IsSealed); + Assert.That(m.Name, Is.EqualTo("GetNextAssembly")); + Assert.That(m.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(m.IsAbstract); + Assert.That(!m.IsVirtual); + Assert.That(!m.IsSealed); } [Test] @@ -943,9 +940,9 @@ public void InnerClassInGenericClassIsReferencedUsingParameterizedType() IField field3 = type.Fields.Single(f => f.Name == "Field3"); // types must be self-parameterized - Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]", field1.Type.ReflectionName); - Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]", field2.Type.ReflectionName); - Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]]]", field3.Type.ReflectionName); + Assert.That(field1.Type.ReflectionName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]")); + Assert.That(field2.Type.ReflectionName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]")); + Assert.That(field3.Type.ReflectionName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1+Inner[[`0]]]]")); } [Test] @@ -953,67 +950,67 @@ public void FlagsOnInterfaceMembersAreCorrect() { ITypeDefinition type = GetTypeDefinition(typeof(IInterfaceWithProperty)); var p = type.Properties.Single(); - Assert.AreEqual(false, p.IsIndexer); - Assert.AreEqual(true, p.IsAbstract); - Assert.AreEqual(true, p.IsOverridable); - Assert.AreEqual(false, p.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(true, p.Getter.IsAbstract); - Assert.AreEqual(true, p.Getter.IsOverridable); - Assert.AreEqual(false, p.Getter.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.AreEqual(false, p.Getter.HasBody); - Assert.AreEqual(true, p.Setter.IsAbstract); - Assert.AreEqual(true, p.Setter.IsOverridable); - Assert.AreEqual(false, p.Setter.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Setter.Accessibility); - Assert.AreEqual(false, p.Setter.HasBody); + Assert.That(p.IsIndexer, Is.EqualTo(false)); + Assert.That(p.IsAbstract, Is.EqualTo(true)); + Assert.That(p.IsOverridable, Is.EqualTo(true)); + Assert.That(p.IsOverride, Is.EqualTo(false)); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.IsAbstract, Is.EqualTo(true)); + Assert.That(p.Getter.IsOverridable, Is.EqualTo(true)); + Assert.That(p.Getter.IsOverride, Is.EqualTo(false)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.HasBody, Is.EqualTo(false)); + Assert.That(p.Setter.IsAbstract, Is.EqualTo(true)); + Assert.That(p.Setter.IsOverridable, Is.EqualTo(true)); + Assert.That(p.Setter.IsOverride, Is.EqualTo(false)); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter.HasBody, Is.EqualTo(false)); type = GetTypeDefinition(typeof(IInterfaceWithIndexers)); p = type.Properties.Single(x => x.Parameters.Count == 2); - Assert.AreEqual(true, p.IsIndexer); - Assert.AreEqual(true, p.IsAbstract); - Assert.AreEqual(true, p.IsOverridable); - Assert.AreEqual(false, p.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Accessibility); - Assert.AreEqual(true, p.Getter.IsAbstract); - Assert.AreEqual(true, p.Getter.IsOverridable); - Assert.AreEqual(false, p.Getter.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); - Assert.AreEqual(true, p.Setter.IsAbstract); - Assert.AreEqual(true, p.Setter.IsOverridable); - Assert.AreEqual(false, p.Setter.IsOverride); - Assert.AreEqual(Accessibility.Public, p.Setter.Accessibility); + Assert.That(p.IsIndexer, Is.EqualTo(true)); + Assert.That(p.IsAbstract, Is.EqualTo(true)); + Assert.That(p.IsOverridable, Is.EqualTo(true)); + Assert.That(p.IsOverride, Is.EqualTo(false)); + Assert.That(p.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Getter.IsAbstract, Is.EqualTo(true)); + Assert.That(p.Getter.IsOverridable, Is.EqualTo(true)); + Assert.That(p.Getter.IsOverride, Is.EqualTo(false)); + Assert.That(p.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(p.Setter.IsAbstract, Is.EqualTo(true)); + Assert.That(p.Setter.IsOverridable, Is.EqualTo(true)); + Assert.That(p.Setter.IsOverride, Is.EqualTo(false)); + Assert.That(p.Setter.Accessibility, Is.EqualTo(Accessibility.Public)); type = GetTypeDefinition(typeof(IHasEvent)); var e = type.Events.Single(); - Assert.AreEqual(true, e.IsAbstract); - Assert.AreEqual(true, e.IsOverridable); - Assert.AreEqual(false, e.IsOverride); - Assert.AreEqual(Accessibility.Public, e.Accessibility); - Assert.AreEqual(true, e.AddAccessor.IsAbstract); - Assert.AreEqual(true, e.AddAccessor.IsOverridable); - Assert.AreEqual(false, e.AddAccessor.IsOverride); - Assert.AreEqual(Accessibility.Public, e.AddAccessor.Accessibility); - Assert.AreEqual(true, e.RemoveAccessor.IsAbstract); - Assert.AreEqual(true, e.RemoveAccessor.IsOverridable); - Assert.AreEqual(false, e.RemoveAccessor.IsOverride); - Assert.AreEqual(Accessibility.Public, e.RemoveAccessor.Accessibility); + Assert.That(e.IsAbstract, Is.EqualTo(true)); + Assert.That(e.IsOverridable, Is.EqualTo(true)); + Assert.That(e.IsOverride, Is.EqualTo(false)); + Assert.That(e.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(e.AddAccessor.IsAbstract, Is.EqualTo(true)); + Assert.That(e.AddAccessor.IsOverridable, Is.EqualTo(true)); + Assert.That(e.AddAccessor.IsOverride, Is.EqualTo(false)); + Assert.That(e.AddAccessor.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(e.RemoveAccessor.IsAbstract, Is.EqualTo(true)); + Assert.That(e.RemoveAccessor.IsOverridable, Is.EqualTo(true)); + Assert.That(e.RemoveAccessor.IsOverride, Is.EqualTo(false)); + Assert.That(e.RemoveAccessor.Accessibility, Is.EqualTo(Accessibility.Public)); type = GetTypeDefinition(typeof(IDisposable)); var m = type.Methods.Single(); - Assert.AreEqual(true, m.IsAbstract); - Assert.AreEqual(true, m.IsOverridable); - Assert.AreEqual(false, m.IsOverride); - Assert.AreEqual(Accessibility.Public, m.Accessibility); + Assert.That(m.IsAbstract, Is.EqualTo(true)); + Assert.That(m.IsOverridable, Is.EqualTo(true)); + Assert.That(m.IsOverride, Is.EqualTo(false)); + Assert.That(m.Accessibility, Is.EqualTo(Accessibility.Public)); } [Test] public void InnerClassInGenericClass_TypeParameterOwner() { ITypeDefinition type = GetTypeDefinition(typeof(OuterGeneric<>.Inner)); - Assert.AreSame(type.DeclaringTypeDefinition.TypeParameters[0], type.TypeParameters[0]); - Assert.AreSame(type.DeclaringTypeDefinition, type.TypeParameters[0].Owner); + Assert.That(type.TypeParameters[0], Is.SameAs(type.DeclaringTypeDefinition.TypeParameters[0])); + Assert.That(type.TypeParameters[0].Owner, Is.SameAs(type.DeclaringTypeDefinition)); } [Test] @@ -1021,7 +1018,7 @@ public void InnerClassInGenericClass_ReferencesTheOuterClass_Field() { ITypeDefinition type = GetTypeDefinition(typeof(OuterGeneric<>.Inner)); IField f = type.Fields.Single(); - Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1[[`0]]", f.Type.ReflectionName); + Assert.That(f.Type.ReflectionName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1[[`0]]")); } [Test] @@ -1029,14 +1026,14 @@ public void InnerClassInGenericClass_ReferencesTheOuterClass_Parameter() { ITypeDefinition type = GetTypeDefinition(typeof(OuterGeneric<>.Inner)); IParameter p = type.Methods.Single(m => m.IsConstructor).Parameters.Single(); - Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1[[`0]]", p.Type.ReflectionName); + Assert.That(p.Type.ReflectionName, Is.EqualTo("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1[[`0]]")); } CustomAttributeTypedArgument GetParamsAttributeArgument(int index) { ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); var arr = (AttributeArray)type.GetAttributes().Single().FixedArguments.Single().Value; - Assert.AreEqual(5, arr.Length); + Assert.That(arr.Length, Is.EqualTo(5)); return arr[index]; } @@ -1044,16 +1041,16 @@ CustomAttributeTypedArgument GetParamsAttributeArgument(int index) public void ParamsAttribute_Integer() { var arg = GetParamsAttributeArgument(0); - Assert.AreEqual("System.Int32", arg.Type.FullName); - Assert.AreEqual(1, arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.Int32")); + Assert.That(arg.Value, Is.EqualTo(1)); } [Test] public void ParamsAttribute_Enum() { var arg = GetParamsAttributeArgument(1); - Assert.AreEqual("System.StringComparison", arg.Type.FullName); - Assert.AreEqual((int)StringComparison.CurrentCulture, arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.StringComparison")); + Assert.That(arg.Value, Is.EqualTo((int)StringComparison.CurrentCulture)); } [Test] @@ -1061,23 +1058,23 @@ public void ParamsAttribute_NullReference() { var arg = GetParamsAttributeArgument(2); //Assert.AreEqual("System.Object", arg.Type.FullName); - Assert.IsNull(arg.Value); + Assert.That(arg.Value, Is.Null); } [Test] public void ParamsAttribute_Double() { var arg = GetParamsAttributeArgument(3); - Assert.AreEqual("System.Double", arg.Type.FullName); - Assert.AreEqual(4.0, arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.Double")); + Assert.That(arg.Value, Is.EqualTo(4.0)); } [Test] public void ParamsAttribute_String() { var arg = GetParamsAttributeArgument(4); - Assert.AreEqual("System.String", arg.Type.FullName); - Assert.AreEqual("Test", arg.Value); + Assert.That(arg.Type.FullName, Is.EqualTo("System.String")); + Assert.That(arg.Value, Is.EqualTo("Test")); } [Test] @@ -1086,15 +1083,15 @@ public void ParamsAttribute_Property() ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); IProperty prop = type.Properties.Single(p => p.Name == "Property"); var attr = prop.GetAttributes().Single(); - Assert.AreEqual(type, attr.AttributeType); + Assert.That(attr.AttributeType, Is.EqualTo(type)); var elements = (AttributeArray)attr.FixedArguments.Single().Value; - Assert.AreEqual(0, elements.Length); + Assert.That(elements.Length, Is.EqualTo(0)); var namedArg = attr.NamedArguments.Single(); - Assert.AreEqual(prop.Name, namedArg.Name); + Assert.That(namedArg.Name, Is.EqualTo(prop.Name)); var arrayElements = (AttributeArray)namedArg.Value; - Assert.AreEqual(2, arrayElements.Length); + Assert.That(arrayElements.Length, Is.EqualTo(2)); } [Test] @@ -1102,8 +1099,8 @@ public void ParamsAttribute_Getter_ReturnType() { ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); IProperty prop = type.Properties.Single(p => p.Name == "Property"); - Assert.AreEqual(0, prop.Getter.GetAttributes().Count()); - Assert.AreEqual(1, prop.Getter.GetReturnTypeAttributes().Count()); + Assert.That(prop.Getter.GetAttributes().Count(), Is.EqualTo(0)); + Assert.That(prop.Getter.GetReturnTypeAttributes().Count(), Is.EqualTo(1)); } [Test] @@ -1111,8 +1108,8 @@ public void DoubleAttribute_ImplicitNumericConversion() { ITypeDefinition type = GetTypeDefinition(typeof(DoubleAttribute)); var arg = type.GetAttributes().Single().FixedArguments.Single(); - Assert.AreEqual("System.Double", arg.Type.ReflectionName); - Assert.AreEqual(1.0, arg.Value); + Assert.That(arg.Type.ReflectionName, Is.EqualTo("System.Double")); + Assert.That(arg.Value, Is.EqualTo(1.0)); } /* TS no longer provides implicitly implemented interface members. @@ -1135,24 +1132,24 @@ public void StaticityOfEventAccessors() // https://github.com/icsharpcode/NRefactory/issues/20 ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); var evt1 = type.Events.Single(e => e.Name == "Event1"); - Assert.IsTrue(evt1.IsStatic); - Assert.IsTrue(evt1.AddAccessor.IsStatic); - Assert.IsTrue(evt1.RemoveAccessor.IsStatic); + Assert.That(evt1.IsStatic); + Assert.That(evt1.AddAccessor.IsStatic); + Assert.That(evt1.RemoveAccessor.IsStatic); var evt2 = type.Events.Single(e => e.Name == "Event2"); - Assert.IsFalse(evt2.IsStatic); - Assert.IsFalse(evt2.AddAccessor.IsStatic); - Assert.IsFalse(evt2.RemoveAccessor.IsStatic); + Assert.That(!evt2.IsStatic); + Assert.That(!evt2.AddAccessor.IsStatic); + Assert.That(!evt2.RemoveAccessor.IsStatic); var evt3 = type.Events.Single(e => e.Name == "Event3"); - Assert.IsTrue(evt3.IsStatic); - Assert.IsTrue(evt3.AddAccessor.IsStatic); - Assert.IsTrue(evt3.RemoveAccessor.IsStatic); + Assert.That(evt3.IsStatic); + Assert.That(evt3.AddAccessor.IsStatic); + Assert.That(evt3.RemoveAccessor.IsStatic); var evt4 = type.Events.Single(e => e.Name == "Event4"); - Assert.IsFalse(evt4.IsStatic); - Assert.IsFalse(evt4.AddAccessor.IsStatic); - Assert.IsFalse(evt4.RemoveAccessor.IsStatic); + Assert.That(!evt4.IsStatic); + Assert.That(!evt4.AddAccessor.IsStatic); + Assert.That(!evt4.RemoveAccessor.IsStatic); } [Test] @@ -1161,24 +1158,24 @@ public void StaticityOfPropertyAccessors() // https://github.com/icsharpcode/NRefactory/issues/20 ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); var prop1 = type.Properties.Single(e => e.Name == "Prop1"); - Assert.IsTrue(prop1.IsStatic); - Assert.IsTrue(prop1.Getter.IsStatic); - Assert.IsTrue(prop1.Setter.IsStatic); + Assert.That(prop1.IsStatic); + Assert.That(prop1.Getter.IsStatic); + Assert.That(prop1.Setter.IsStatic); var prop2 = type.Properties.Single(e => e.Name == "Prop2"); - Assert.IsFalse(prop2.IsStatic); - Assert.IsFalse(prop2.Getter.IsStatic); - Assert.IsFalse(prop2.Setter.IsStatic); + Assert.That(!prop2.IsStatic); + Assert.That(!prop2.Getter.IsStatic); + Assert.That(!prop2.Setter.IsStatic); var prop3 = type.Properties.Single(e => e.Name == "Prop3"); - Assert.IsTrue(prop3.IsStatic); - Assert.IsTrue(prop3.Getter.IsStatic); - Assert.IsTrue(prop3.Setter.IsStatic); + Assert.That(prop3.IsStatic); + Assert.That(prop3.Getter.IsStatic); + Assert.That(prop3.Setter.IsStatic); var prop4 = type.Properties.Single(e => e.Name == "Prop4"); - Assert.IsFalse(prop4.IsStatic); - Assert.IsFalse(prop4.Getter.IsStatic); - Assert.IsFalse(prop4.Setter.IsStatic); + Assert.That(!prop4.IsStatic); + Assert.That(!prop4.Getter.IsStatic); + Assert.That(!prop4.Setter.IsStatic); } [Test] @@ -1187,8 +1184,8 @@ public void PropertyAccessorsHaveBody() ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); foreach (var prop in type.Properties) { - Assert.IsTrue(prop.Getter.HasBody, prop.Getter.Name); - Assert.IsTrue(prop.Setter.HasBody, prop.Setter.Name); + Assert.That(prop.Getter.HasBody, prop.Getter.Name); + Assert.That(prop.Setter.HasBody, prop.Setter.Name); } } @@ -1197,12 +1194,12 @@ public void EventAccessorNames() { ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); var customEvent = type.Events.Single(e => e.Name == "Event1"); - Assert.AreEqual("add_Event1", customEvent.AddAccessor.Name); - Assert.AreEqual("remove_Event1", customEvent.RemoveAccessor.Name); + Assert.That(customEvent.AddAccessor.Name, Is.EqualTo("add_Event1")); + Assert.That(customEvent.RemoveAccessor.Name, Is.EqualTo("remove_Event1")); var normalEvent = type.Events.Single(e => e.Name == "Event3"); - Assert.AreEqual("add_Event3", normalEvent.AddAccessor.Name); - Assert.AreEqual("remove_Event3", normalEvent.RemoveAccessor.Name); + Assert.That(normalEvent.AddAccessor.Name, Is.EqualTo("add_Event3")); + Assert.That(normalEvent.RemoveAccessor.Name, Is.EqualTo("remove_Event3")); } [Test] @@ -1211,8 +1208,8 @@ public void EventAccessorHaveBody() ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); foreach (var ev in type.Events) { - Assert.IsTrue(ev.AddAccessor.HasBody, ev.AddAccessor.Name); - Assert.IsTrue(ev.RemoveAccessor.HasBody, ev.RemoveAccessor.Name); + Assert.That(ev.AddAccessor.HasBody, ev.AddAccessor.Name); + Assert.That(ev.RemoveAccessor.HasBody, ev.RemoveAccessor.Name); } } @@ -1270,8 +1267,8 @@ public void ClassThatOverridesGetterOnly() { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatOverridesGetterOnly)); var prop = type.Properties.Single(p => p.Name == "Prop"); - Assert.AreEqual(Accessibility.Public, prop.Accessibility); - Assert.AreEqual(Accessibility.Public, prop.Getter.Accessibility); + Assert.That(prop.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(prop.Getter.Accessibility, Is.EqualTo(Accessibility.Public)); } [Test] @@ -1279,8 +1276,8 @@ public void ClassThatOverridesSetterOnly() { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatOverridesSetterOnly)); var prop = type.Properties.Single(p => p.Name == "Prop"); - Assert.AreEqual(Accessibility.Public, prop.Accessibility); - Assert.AreEqual(Accessibility.Protected, prop.Setter.Accessibility); + Assert.That(prop.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(prop.Setter.Accessibility, Is.EqualTo(Accessibility.Protected)); } /* TS no longer provides implicit interface impls @@ -1300,9 +1297,9 @@ public void PropertyThatImplementsInterfaceIsNotVirtual() { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsProperty)); var prop = type.Properties.Single(p => p.Name == "Prop"); - Assert.IsFalse(prop.IsVirtual); - Assert.IsFalse(prop.IsOverridable); - Assert.IsFalse(prop.IsSealed); + Assert.That(!prop.IsVirtual); + Assert.That(!prop.IsOverridable); + Assert.That(!prop.IsSealed); } [Test] @@ -1310,10 +1307,10 @@ public void Property_SealedOverride() { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatOverridesAndSealsVirtualProperty)); var prop = type.Properties.Single(p => p.Name == "Prop"); - Assert.IsFalse(prop.IsVirtual); - Assert.IsTrue(prop.IsOverride); - Assert.IsTrue(prop.IsSealed); - Assert.IsFalse(prop.IsOverridable); + Assert.That(!prop.IsVirtual); + Assert.That(prop.IsOverride); + Assert.That(prop.IsSealed); + Assert.That(!prop.IsOverridable); } /* The TS no longer provides implicit interface impls. @@ -1365,26 +1362,26 @@ public void ExplicitDisposableImplementation() { ITypeDefinition disposable = GetTypeDefinition(typeof(ExplicitDisposableImplementation)); IMethod method = disposable.Methods.Single(m => !m.IsConstructor); - Assert.IsTrue(method.IsExplicitInterfaceImplementation); - Assert.AreEqual("System.IDisposable.Dispose", method.ExplicitlyImplementedInterfaceMembers.Single().FullName); + Assert.That(method.IsExplicitInterfaceImplementation); + Assert.That(method.ExplicitlyImplementedInterfaceMembers.Single().FullName, Is.EqualTo("System.IDisposable.Dispose")); } [Test] public void ExplicitImplementationOfUnifiedMethods() { IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); - Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); + Assert.That(type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count(), Is.EqualTo(2)); foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { - Assert.AreEqual(1, method.ExplicitlyImplementedInterfaceMembers.Count(), method.ToString()); - Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName); + Assert.That(method.ExplicitlyImplementedInterfaceMembers.Count(), Is.EqualTo(1), method.ToString()); + Assert.That(method.Parameters.Single().Type.ReflectionName, Is.EqualTo("System.Int32")); IMethod interfaceMethod = (IMethod)method.ExplicitlyImplementedInterfaceMembers.Single(); - Assert.AreEqual("System.Int32", interfaceMethod.Parameters.Single().Type.ReflectionName); + Assert.That(interfaceMethod.Parameters.Single().Type.ReflectionName, Is.EqualTo("System.Int32")); var genericParamType = ((IMethod)method.MemberDefinition).Parameters.Single().Type; var interfaceGenericParamType = ((IMethod)interfaceMethod.MemberDefinition).Parameters.Single().Type; - Assert.AreEqual(TypeKind.TypeParameter, genericParamType.Kind); - Assert.AreEqual(TypeKind.TypeParameter, interfaceGenericParamType.Kind); - Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName); + Assert.That(genericParamType.Kind, Is.EqualTo(TypeKind.TypeParameter)); + Assert.That(interfaceGenericParamType.Kind, Is.EqualTo(TypeKind.TypeParameter)); + Assert.That(interfaceGenericParamType.ReflectionName, Is.EqualTo(genericParamType.ReflectionName)); } } @@ -1395,16 +1392,16 @@ public void ExplicitGenericInterfaceImplementation() IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface)); IMethod implMethod1 = impl.Methods.Single(m => !m.IsConstructor && !m.Parameters[1].IsRef); IMethod implMethod2 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].IsRef); - Assert.IsTrue(implMethod1.IsExplicitInterfaceImplementation); - Assert.IsTrue(implMethod2.IsExplicitInterfaceImplementation); + Assert.That(implMethod1.IsExplicitInterfaceImplementation); + Assert.That(implMethod2.IsExplicitInterfaceImplementation); IMethod interfaceMethod1 = (IMethod)implMethod1.ExplicitlyImplementedInterfaceMembers.Single(); - Assert.AreEqual(genericInterfaceOfString, interfaceMethod1.DeclaringType); - Assert.IsTrue(!interfaceMethod1.Parameters[1].IsRef); + Assert.That(interfaceMethod1.DeclaringType, Is.EqualTo(genericInterfaceOfString)); + Assert.That(!interfaceMethod1.Parameters[1].IsRef); IMethod interfaceMethod2 = (IMethod)implMethod2.ExplicitlyImplementedInterfaceMembers.Single(); - Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType); - Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef); + Assert.That(interfaceMethod2.DeclaringType, Is.EqualTo(genericInterfaceOfString)); + Assert.That(interfaceMethod2.Parameters[1].IsRef); } [Test] @@ -1422,9 +1419,9 @@ public void ExplicitlyImplementedPropertiesShouldHaveExplicitlyImplementedAccess { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsPropertyExplicitly)); var prop = type.Properties.Single(); - Assert.IsTrue(prop.IsExplicitInterfaceImplementation); - Assert.IsTrue(prop.Getter.IsExplicitInterfaceImplementation); - Assert.IsTrue(prop.Setter.IsExplicitInterfaceImplementation); + Assert.That(prop.IsExplicitInterfaceImplementation); + Assert.That(prop.Getter.IsExplicitInterfaceImplementation); + Assert.That(prop.Setter.IsExplicitInterfaceImplementation); } /* The TS no longer provides implicit interface impls. @@ -1484,9 +1481,9 @@ public void MembersDeclaredInDerivedInterfacesDoNotImplementBaseMembers() public void StaticClassTest() { ITypeDefinition type = GetTypeDefinition(typeof(StaticClass)); - Assert.IsTrue(type.IsAbstract); - Assert.IsTrue(type.IsSealed); - Assert.IsTrue(type.IsStatic); + Assert.That(type.IsAbstract); + Assert.That(type.IsSealed); + Assert.That(type.IsStatic); } [Test] @@ -1495,18 +1492,18 @@ public void ExtensionMethodTest() ITypeDefinition type = GetTypeDefinition(typeof(StaticClass)); var method = type.Methods.Single(m => m.Name == "Extension"); - Assert.IsTrue(method.IsStatic); - Assert.IsTrue(method.IsExtensionMethod); - Assert.IsNull(method.ReducedFrom); + Assert.That(method.IsStatic); + Assert.That(method.IsExtensionMethod); + Assert.That(method.ReducedFrom, Is.Null); - Assert.IsTrue(type.HasExtensionMethods); + Assert.That(type.HasExtensionMethods); } [Test] public void NoDefaultConstructorOnStaticClassTest() { ITypeDefinition type = GetTypeDefinition(typeof(StaticClass)); - Assert.AreEqual(0, type.GetConstructors().Count()); + Assert.That(type.GetConstructors().Count(), Is.EqualTo(0)); } [Test] @@ -1514,7 +1511,7 @@ public void IndexerNonDefaultName() { ITypeDefinition type = GetTypeDefinition(typeof(IndexerNonDefaultName)); var indexer = type.GetProperties(p => p.IsIndexer).Single(); - Assert.AreEqual("Foo", indexer.Name); + Assert.That(indexer.Name, Is.EqualTo("Foo")); } [Test] @@ -1522,28 +1519,28 @@ public void TestNullableDefaultParameter() { ITypeDefinition type = GetTypeDefinition(typeof(ClassWithMethodThatHasNullableDefaultParameter)); var method = type.GetMethods().Single(m => m.Name == "Foo"); - Assert.AreEqual(42, method.Parameters.Single().GetConstantValue()); + Assert.That(method.Parameters.Single().GetConstantValue(), Is.EqualTo(42)); } [Test] public void AccessibilityTests() { ITypeDefinition type = GetTypeDefinition(typeof(AccessibilityTest)); - Assert.AreEqual(Accessibility.Public, type.Methods.Single(m => m.Name == "Public").Accessibility); - Assert.AreEqual(Accessibility.Internal, type.Methods.Single(m => m.Name == "Internal").Accessibility); - Assert.AreEqual(Accessibility.ProtectedOrInternal, type.Methods.Single(m => m.Name == "ProtectedInternal").Accessibility); - Assert.AreEqual(Accessibility.ProtectedOrInternal, type.Methods.Single(m => m.Name == "InternalProtected").Accessibility); - Assert.AreEqual(Accessibility.Protected, type.Methods.Single(m => m.Name == "Protected").Accessibility); - Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "Private").Accessibility); - Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "None").Accessibility); + Assert.That(type.Methods.Single(m => m.Name == "Public").Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(type.Methods.Single(m => m.Name == "Internal").Accessibility, Is.EqualTo(Accessibility.Internal)); + Assert.That(type.Methods.Single(m => m.Name == "ProtectedInternal").Accessibility, Is.EqualTo(Accessibility.ProtectedOrInternal)); + Assert.That(type.Methods.Single(m => m.Name == "InternalProtected").Accessibility, Is.EqualTo(Accessibility.ProtectedOrInternal)); + Assert.That(type.Methods.Single(m => m.Name == "Protected").Accessibility, Is.EqualTo(Accessibility.Protected)); + Assert.That(type.Methods.Single(m => m.Name == "Private").Accessibility, Is.EqualTo(Accessibility.Private)); + Assert.That(type.Methods.Single(m => m.Name == "None").Accessibility, Is.EqualTo(Accessibility.Private)); } private void AssertConstantField(ITypeDefinition type, string name, T expected) { var f = type.GetFields().Single(x => x.Name == name); - Assert.IsTrue(f.IsConst); - Assert.AreEqual(expected, f.GetConstantValue()); - Assert.AreEqual(0, f.GetAttributes().Count()); + Assert.That(f.IsConst); + Assert.That(f.GetConstantValue(), Is.EqualTo(expected)); + Assert.That(f.GetAttributes().Count(), Is.EqualTo(0)); } [Test] @@ -1589,8 +1586,8 @@ public void ConstantEnumFromThisAssembly() { ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); IField field = type.Fields.Single(f => f.Name == "EnumFromThisAssembly"); - Assert.IsTrue(field.IsConst); - Assert.AreEqual((short)MyEnum.Second, field.GetConstantValue()); + Assert.That(field.IsConst); + Assert.That(field.GetConstantValue(), Is.EqualTo((short)MyEnum.Second)); } [Test] @@ -1598,8 +1595,8 @@ public void ConstantEnumFromAnotherAssembly() { ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); IField field = type.Fields.Single(f => f.Name == "EnumFromAnotherAssembly"); - Assert.IsTrue(field.IsConst); - Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, field.GetConstantValue()); + Assert.That(field.IsConst); + Assert.That(field.GetConstantValue(), Is.EqualTo((int)StringComparison.OrdinalIgnoreCase)); } [Test] @@ -1607,8 +1604,8 @@ public void DefaultOfEnum() { ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest)); IField field = type.Fields.Single(f => f.Name == "DefaultOfEnum"); - Assert.IsTrue(field.IsConst); - Assert.AreEqual((short)default(MyEnum), field.GetConstantValue()); + Assert.That(field.IsConst); + Assert.That(field.GetConstantValue(), Is.EqualTo((short)default(MyEnum))); } [Test] @@ -1620,41 +1617,41 @@ public void ExplicitImplementation() var methods = type.GetMethods(m => m.Name == "M" || m.Name.EndsWith(".M")).ToList(); var imethod = itype.GetMethods(m => m.Name == "M").Single(); Assert.That(methods.Select(m => m.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(methods.SelectMany(m => m.ExplicitlyImplementedInterfaceMembers).Single(), imethod); + Assert.That(imethod, Is.EqualTo(methods.SelectMany(m => m.ExplicitlyImplementedInterfaceMembers).Single())); var properties = type.GetProperties(p => p.Name == "P" || p.Name.EndsWith(".P")).ToList(); var iproperty = itype.GetProperties(m => m.Name == "P").Single(); Assert.That(properties.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iproperty); + Assert.That(iproperty, Is.EqualTo(properties.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(properties.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Getter); + Assert.That(iproperty.Getter, Is.EqualTo(properties.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(properties.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Setter); + Assert.That(iproperty.Setter, Is.EqualTo(properties.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single())); var indexers = type.GetProperties(p => p.Name == "Item" || p.Name.EndsWith(".Item")).ToList(); var iindexer = itype.GetProperties(m => m.Name == "Item").Single(); Assert.That(indexers.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iindexer); + Assert.That(iindexer, Is.EqualTo(indexers.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(indexers.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Getter); + Assert.That(iindexer.Getter, Is.EqualTo(indexers.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(indexers.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Setter); + Assert.That(iindexer.Setter, Is.EqualTo(indexers.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single())); var events = type.GetEvents(e => e.Name == "E" || e.Name.EndsWith(".E")).ToList(); var ievent = itype.GetEvents(m => m.Name == "E").Single(); Assert.That(events.Select(e => e.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.ExplicitlyImplementedInterfaceMembers).Single(), ievent); + Assert.That(ievent, Is.EqualTo(events.SelectMany(e => e.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(events.Select(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.AddAccessor); + Assert.That(ievent.AddAccessor, Is.EqualTo(events.SelectMany(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers).Single())); Assert.That(events.Select(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.RemoveAccessor); + Assert.That(ievent.RemoveAccessor, Is.EqualTo(events.SelectMany(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers).Single())); } [Test] public void MarshalTests() { ITypeDefinition c = compilation.FindType(typeof(IMarshalAsTests)).GetDefinition(); - Assert.AreEqual(1, c.GetMethods(m => m.Name == "GetCollectionByQuery2").Count()); + Assert.That(c.GetMethods(m => m.Name == "GetCollectionByQuery2").Count(), Is.EqualTo(1)); } @@ -1665,33 +1662,33 @@ public void AttributesUsingNestedMembers() var inner = type.GetNestedTypes().Single(t => t.Name == "Inner"); var myAttribute = type.GetNestedTypes().Single(t => t.Name == "MyAttribute"); var typeTypeTestAttr = type.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); - Assert.AreEqual(42, typeTypeTestAttr.FixedArguments[0].Value); - Assert.AreEqual(inner, typeTypeTestAttr.FixedArguments[1].Value); + Assert.That(typeTypeTestAttr.FixedArguments[0].Value, Is.EqualTo(42)); + Assert.That(typeTypeTestAttr.FixedArguments[1].Value, Is.EqualTo(inner)); var typeMyAttr = type.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); - Assert.AreEqual(myAttribute, typeMyAttr.AttributeType); + Assert.That(typeMyAttr.AttributeType, Is.EqualTo(myAttribute)); var prop = type.GetProperties().Single(p => p.Name == "P"); var propTypeTestAttr = prop.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); - Assert.AreEqual(42, propTypeTestAttr.FixedArguments[0].Value); - Assert.AreEqual(inner, propTypeTestAttr.FixedArguments[1].Value); + Assert.That(propTypeTestAttr.FixedArguments[0].Value, Is.EqualTo(42)); + Assert.That(propTypeTestAttr.FixedArguments[1].Value, Is.EqualTo(inner)); var propMyAttr = prop.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); - Assert.AreEqual(myAttribute, propMyAttr.AttributeType); + Assert.That(propMyAttr.AttributeType, Is.EqualTo(myAttribute)); var attributedInner = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner"); var innerTypeTestAttr = attributedInner.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); - Assert.AreEqual(42, innerTypeTestAttr.FixedArguments[0].Value); - Assert.AreEqual(inner, innerTypeTestAttr.FixedArguments[1].Value); + Assert.That(innerTypeTestAttr.FixedArguments[0].Value, Is.EqualTo(42)); + Assert.That(innerTypeTestAttr.FixedArguments[1].Value, Is.EqualTo(inner)); var innerMyAttr = attributedInner.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); - Assert.AreEqual(myAttribute, innerMyAttr.AttributeType); + Assert.That(innerMyAttr.AttributeType, Is.EqualTo(myAttribute)); var attributedInner2 = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner2"); var inner2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "Inner"); var myAttribute2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "MyAttribute"); var inner2TypeTestAttr = attributedInner2.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); - Assert.AreEqual(43, inner2TypeTestAttr.FixedArguments[0].Value); - Assert.AreEqual(inner2, inner2TypeTestAttr.FixedArguments[1].Value); + Assert.That(inner2TypeTestAttr.FixedArguments[0].Value, Is.EqualTo(43)); + Assert.That(inner2TypeTestAttr.FixedArguments[1].Value, Is.EqualTo(inner2)); var inner2MyAttr = attributedInner2.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); - Assert.AreEqual(myAttribute2, inner2MyAttr.AttributeType); + Assert.That(inner2MyAttr.AttributeType, Is.EqualTo(myAttribute2)); } [Test] @@ -1699,7 +1696,7 @@ public void ClassWithAttributeOnTypeParameter() { var tp = GetTypeDefinition(typeof(ClassWithAttributeOnTypeParameter<>)).TypeParameters.Single(); var attr = tp.GetAttributes().Single(); - Assert.AreEqual("DoubleAttribute", attr.AttributeType.Name); + Assert.That(attr.AttributeType.Name, Is.EqualTo("DoubleAttribute")); } [Test] @@ -1707,19 +1704,19 @@ public void InheritanceTest() { ITypeDefinition c = compilation.FindType(typeof(SystemException)).GetDefinition(); ITypeDefinition c2 = compilation.FindType(typeof(Exception)).GetDefinition(); - Assert.IsNotNull(c, "c is null"); - Assert.IsNotNull(c2, "c2 is null"); + Assert.That(c, Is.Not.Null, "c is null"); + Assert.That(c2, Is.Not.Null, "c2 is null"); //Assert.AreEqual(3, c.BaseTypes.Count); // Inherited interfaces are not reported by Cecil // which matches the behaviour of our C#/VB parsers - Assert.AreEqual("System.Exception", c.DirectBaseTypes.First().FullName); - Assert.AreSame(c2, c.DirectBaseTypes.First()); + Assert.That(c.DirectBaseTypes.First().FullName, Is.EqualTo("System.Exception")); + Assert.That(c.DirectBaseTypes.First(), Is.SameAs(c2)); string[] superTypes = c.GetAllBaseTypes().Select(t => t.ReflectionName).ToArray(); - Assert.AreEqual(new string[] { + Assert.That(superTypes, Is.EqualTo(new string[] { "System.Object", "System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception", "System.Exception", "System.SystemException" - }, superTypes); + })); } [Test] @@ -1728,8 +1725,8 @@ public void GenericPropertyTest() ITypeDefinition c = compilation.FindType(typeof(Comparer<>)).GetDefinition(); IProperty def = c.Properties.Single(p => p.Name == "Default"); ParameterizedType pt = (ParameterizedType)def.ReturnType; - Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName); - Assert.AreEqual(c.TypeParameters[0], pt.TypeArguments[0]); + Assert.That(pt.FullName, Is.EqualTo("System.Collections.Generic.Comparer")); + Assert.That(pt.TypeArguments[0], Is.EqualTo(c.TypeParameters[0])); } [Test] @@ -1737,17 +1734,17 @@ public void PointerTypeTest() { ITypeDefinition c = compilation.FindType(typeof(IntPtr)).GetDefinition(); IMethod toPointer = c.Methods.Single(p => p.Name == "ToPointer"); - Assert.AreEqual("System.Void*", toPointer.ReturnType.ReflectionName); - Assert.IsTrue(toPointer.ReturnType is PointerType); - Assert.AreEqual("System.Void", ((PointerType)toPointer.ReturnType).ElementType.FullName); + Assert.That(toPointer.ReturnType.ReflectionName, Is.EqualTo("System.Void*")); + Assert.That(toPointer.ReturnType is PointerType); + Assert.That(((PointerType)toPointer.ReturnType).ElementType.FullName, Is.EqualTo("System.Void")); } [Test] public void DateTimeDefaultConstructor() { ITypeDefinition c = compilation.FindType(typeof(DateTime)).GetDefinition(); - Assert.AreEqual(1, c.Methods.Count(m => m.IsConstructor && !m.IsStatic && m.Parameters.Count == 0)); - Assert.AreEqual(1, c.GetConstructors().Count(m => m.Parameters.Count == 0)); + Assert.That(c.Methods.Count(m => m.IsConstructor && !m.IsStatic && m.Parameters.Count == 0), Is.EqualTo(1)); + Assert.That(c.GetConstructors().Count(m => m.Parameters.Count == 0), Is.EqualTo(1)); } [Test] @@ -1755,49 +1752,49 @@ public void NoEncodingInfoDefaultConstructor() { ITypeDefinition c = compilation.FindType(typeof(EncodingInfo)).GetDefinition(); // EncodingInfo only has an internal constructor - Assert.IsFalse(c.Methods.Any(m => m.IsConstructor)); + Assert.That(!c.Methods.Any(m => m.IsConstructor)); // and no implicit ctor should be added: - Assert.AreEqual(0, c.GetConstructors().Count()); + Assert.That(c.GetConstructors().Count(), Is.EqualTo(0)); } [Test] public void StaticModifierTest() { ITypeDefinition c = compilation.FindType(typeof(Environment)).GetDefinition(); - Assert.IsNotNull(c, "System.Environment not found"); - Assert.IsTrue(c.IsAbstract, "class should be abstract"); - Assert.IsTrue(c.IsSealed, "class should be sealed"); - Assert.IsTrue(c.IsStatic, "class should be static"); + Assert.That(c, Is.Not.Null, "System.Environment not found"); + Assert.That(c.IsAbstract, "class should be abstract"); + Assert.That(c.IsSealed, "class should be sealed"); + Assert.That(c.IsStatic, "class should be static"); } [Test] public void InnerClassReferenceTest() { ITypeDefinition c = compilation.FindType(typeof(Environment)).GetDefinition(); - Assert.IsNotNull(c, "System.Environment not found"); + Assert.That(c, Is.Not.Null, "System.Environment not found"); IType rt = c.Methods.First(m => m.Name == "GetFolderPath").Parameters[0].Type; - Assert.AreSame(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"), rt); + Assert.That(rt, Is.SameAs(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"))); } [Test] public void NestedTypesTest() { ITypeDefinition c = compilation.FindType(typeof(Environment.SpecialFolder)).GetDefinition(); - Assert.IsNotNull(c, "c is null"); - Assert.AreEqual("System.Environment.SpecialFolder", c.FullName); - Assert.AreEqual("System.Environment+SpecialFolder", c.ReflectionName); + Assert.That(c, Is.Not.Null, "c is null"); + Assert.That(c.FullName, Is.EqualTo("System.Environment.SpecialFolder")); + Assert.That(c.ReflectionName, Is.EqualTo("System.Environment+SpecialFolder")); } [Test] public void VoidHasNoMembers() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); - Assert.IsNotNull(c, "System.Void not found"); - Assert.AreEqual(TypeKind.Void, c.Kind); - Assert.AreEqual(0, c.GetMethods().Count()); - Assert.AreEqual(0, c.GetProperties().Count()); - Assert.AreEqual(0, c.GetEvents().Count()); - Assert.AreEqual(0, c.GetFields().Count()); + Assert.That(c, Is.Not.Null, "System.Void not found"); + Assert.That(c.Kind, Is.EqualTo(TypeKind.Void)); + Assert.That(c.GetMethods().Count(), Is.EqualTo(0)); + Assert.That(c.GetProperties().Count(), Is.EqualTo(0)); + Assert.That(c.GetEvents().Count(), Is.EqualTo(0)); + Assert.That(c.GetFields().Count(), Is.EqualTo(0)); } [Test] @@ -1805,9 +1802,9 @@ public void Void_SerializableAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.SerializableAttribute"); - Assert.AreEqual(0, attr.Constructor.Parameters.Count); - Assert.AreEqual(0, attr.FixedArguments.Length); - Assert.AreEqual(0, attr.NamedArguments.Length); + Assert.That(attr.Constructor.Parameters.Count, Is.EqualTo(0)); + Assert.That(attr.FixedArguments.Length, Is.EqualTo(0)); + Assert.That(attr.NamedArguments.Length, Is.EqualTo(0)); } [Test] @@ -1815,12 +1812,12 @@ public void Void_StructLayoutAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.StructLayoutAttribute"); - Assert.AreEqual(1, attr.Constructor.Parameters.Count); - Assert.AreEqual(1, attr.FixedArguments.Length); - Assert.AreEqual(0, attr.FixedArguments[0].Value); - Assert.AreEqual(1, attr.NamedArguments.Length); - Assert.AreEqual("Size", attr.NamedArguments[0].Name); - Assert.AreEqual(1, attr.NamedArguments[0].Value); + Assert.That(attr.Constructor.Parameters.Count, Is.EqualTo(1)); + Assert.That(attr.FixedArguments.Length, Is.EqualTo(1)); + Assert.That(attr.FixedArguments[0].Value, Is.EqualTo(0)); + Assert.That(attr.NamedArguments.Length, Is.EqualTo(1)); + Assert.That(attr.NamedArguments[0].Name, Is.EqualTo("Size")); + Assert.That(attr.NamedArguments[0].Value, Is.EqualTo(1)); } [Test] @@ -1828,126 +1825,126 @@ public void Void_ComVisibleAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.ComVisibleAttribute"); - Assert.AreEqual(1, attr.Constructor.Parameters.Count); - Assert.AreEqual(1, attr.FixedArguments.Length); - Assert.AreEqual(true, attr.FixedArguments[0].Value); - Assert.AreEqual(0, attr.NamedArguments.Length); + Assert.That(attr.Constructor.Parameters.Count, Is.EqualTo(1)); + Assert.That(attr.FixedArguments.Length, Is.EqualTo(1)); + Assert.That(attr.FixedArguments[0].Value, Is.EqualTo(true)); + Assert.That(attr.NamedArguments.Length, Is.EqualTo(0)); } [Test] public void NestedClassInGenericClassTest() { ITypeDefinition dictionary = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); - Assert.IsNotNull(dictionary); + Assert.That(dictionary, Is.Not.Null); ITypeDefinition valueCollection = compilation.FindType(typeof(Dictionary<,>.ValueCollection)).GetDefinition(); - Assert.IsNotNull(valueCollection); + Assert.That(valueCollection, Is.Not.Null); var dictionaryRT = new ParameterizedType(dictionary, new[] { compilation.FindType(typeof(string)).GetDefinition(), compilation.FindType(typeof(int)).GetDefinition() }); IProperty valueProperty = dictionaryRT.GetProperties(p => p.Name == "Values").Single(); IType parameterizedValueCollection = valueProperty.ReturnType; - Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]", parameterizedValueCollection.ReflectionName); - Assert.AreSame(valueCollection, parameterizedValueCollection.GetDefinition()); + Assert.That(parameterizedValueCollection.ReflectionName, Is.EqualTo("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]")); + Assert.That(parameterizedValueCollection.GetDefinition(), Is.SameAs(valueCollection)); } [Test] public void ValueCollectionCountModifiers() { ITypeDefinition valueCollection = compilation.FindType(typeof(Dictionary<,>.ValueCollection)).GetDefinition(); - Assert.AreEqual(Accessibility.Public, valueCollection.Accessibility); - Assert.IsTrue(valueCollection.IsSealed); - Assert.IsFalse(valueCollection.IsAbstract); - Assert.IsFalse(valueCollection.IsStatic); + Assert.That(valueCollection.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(valueCollection.IsSealed); + Assert.That(!valueCollection.IsAbstract); + Assert.That(!valueCollection.IsStatic); IProperty count = valueCollection.Properties.Single(p => p.Name == "Count"); - Assert.AreEqual(Accessibility.Public, count.Accessibility); + Assert.That(count.Accessibility, Is.EqualTo(Accessibility.Public)); // It's sealed on the IL level; but in C# it's just a normal non-virtual method that happens to implement an interface - Assert.IsFalse(count.IsSealed); - Assert.IsFalse(count.IsVirtual); - Assert.IsFalse(count.IsAbstract); + Assert.That(!count.IsSealed); + Assert.That(!count.IsVirtual); + Assert.That(!count.IsAbstract); } [Test] public void MathAcosModifiers() { ITypeDefinition math = compilation.FindType(typeof(Math)).GetDefinition(); - Assert.AreEqual(Accessibility.Public, math.Accessibility); - Assert.IsTrue(math.IsSealed); - Assert.IsTrue(math.IsAbstract); - Assert.IsTrue(math.IsStatic); + Assert.That(math.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(math.IsSealed); + Assert.That(math.IsAbstract); + Assert.That(math.IsStatic); IMethod acos = math.Methods.Single(p => p.Name == "Acos"); - Assert.AreEqual(Accessibility.Public, acos.Accessibility); - Assert.IsTrue(acos.IsStatic); - Assert.IsFalse(acos.IsAbstract); - Assert.IsFalse(acos.IsSealed); - Assert.IsFalse(acos.IsVirtual); - Assert.IsFalse(acos.IsOverride); + Assert.That(acos.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(acos.IsStatic); + Assert.That(!acos.IsAbstract); + Assert.That(!acos.IsSealed); + Assert.That(!acos.IsVirtual); + Assert.That(!acos.IsOverride); } [Test] public void EncodingModifiers() { ITypeDefinition encoding = compilation.FindType(typeof(Encoding)).GetDefinition(); - Assert.AreEqual(Accessibility.Public, encoding.Accessibility); - Assert.IsFalse(encoding.IsSealed); - Assert.IsTrue(encoding.IsAbstract); + Assert.That(encoding.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!encoding.IsSealed); + Assert.That(encoding.IsAbstract); IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); - Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); - Assert.IsFalse(getDecoder.IsStatic); - Assert.IsFalse(getDecoder.IsAbstract); - Assert.IsFalse(getDecoder.IsSealed); - Assert.IsTrue(getDecoder.IsVirtual); - Assert.IsFalse(getDecoder.IsOverride); + Assert.That(getDecoder.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!getDecoder.IsStatic); + Assert.That(!getDecoder.IsAbstract); + Assert.That(!getDecoder.IsSealed); + Assert.That(getDecoder.IsVirtual); + Assert.That(!getDecoder.IsOverride); IMethod getMaxByteCount = encoding.Methods.Single(p => p.Name == "GetMaxByteCount"); - Assert.AreEqual(Accessibility.Public, getMaxByteCount.Accessibility); - Assert.IsFalse(getMaxByteCount.IsStatic); - Assert.IsTrue(getMaxByteCount.IsAbstract); - Assert.IsFalse(getMaxByteCount.IsSealed); - Assert.IsFalse(getMaxByteCount.IsVirtual); - Assert.IsFalse(getMaxByteCount.IsOverride); + Assert.That(getMaxByteCount.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!getMaxByteCount.IsStatic); + Assert.That(getMaxByteCount.IsAbstract); + Assert.That(!getMaxByteCount.IsSealed); + Assert.That(!getMaxByteCount.IsVirtual); + Assert.That(!getMaxByteCount.IsOverride); IProperty encoderFallback = encoding.Properties.Single(p => p.Name == "EncoderFallback"); - Assert.AreEqual(Accessibility.Public, encoderFallback.Accessibility); - Assert.IsFalse(encoderFallback.IsStatic); - Assert.IsFalse(encoderFallback.IsAbstract); - Assert.IsFalse(encoderFallback.IsSealed); - Assert.IsFalse(encoderFallback.IsVirtual); - Assert.IsFalse(encoderFallback.IsOverride); + Assert.That(encoderFallback.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!encoderFallback.IsStatic); + Assert.That(!encoderFallback.IsAbstract); + Assert.That(!encoderFallback.IsSealed); + Assert.That(!encoderFallback.IsVirtual); + Assert.That(!encoderFallback.IsOverride); } [Test] public void UnicodeEncodingModifiers() { ITypeDefinition encoding = compilation.FindType(typeof(UnicodeEncoding)).GetDefinition(); - Assert.AreEqual(Accessibility.Public, encoding.Accessibility); - Assert.IsFalse(encoding.IsSealed); - Assert.IsFalse(encoding.IsAbstract); + Assert.That(encoding.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!encoding.IsSealed); + Assert.That(!encoding.IsAbstract); IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); - Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); - Assert.IsFalse(getDecoder.IsStatic); - Assert.IsFalse(getDecoder.IsAbstract); - Assert.IsFalse(getDecoder.IsSealed); - Assert.IsFalse(getDecoder.IsVirtual); - Assert.IsTrue(getDecoder.IsOverride); + Assert.That(getDecoder.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!getDecoder.IsStatic); + Assert.That(!getDecoder.IsAbstract); + Assert.That(!getDecoder.IsSealed); + Assert.That(!getDecoder.IsVirtual); + Assert.That(getDecoder.IsOverride); } [Test] public void UTF32EncodingModifiers() { ITypeDefinition encoding = compilation.FindType(typeof(UTF32Encoding)).GetDefinition(); - Assert.AreEqual(Accessibility.Public, encoding.Accessibility); - Assert.IsTrue(encoding.IsSealed); - Assert.IsFalse(encoding.IsAbstract); + Assert.That(encoding.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(encoding.IsSealed); + Assert.That(!encoding.IsAbstract); IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); - Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); - Assert.IsFalse(getDecoder.IsStatic); - Assert.IsFalse(getDecoder.IsAbstract); - Assert.IsFalse(getDecoder.IsSealed); - Assert.IsFalse(getDecoder.IsVirtual); - Assert.IsTrue(getDecoder.IsOverride); + Assert.That(getDecoder.Accessibility, Is.EqualTo(Accessibility.Public)); + Assert.That(!getDecoder.IsStatic); + Assert.That(!getDecoder.IsAbstract); + Assert.That(!getDecoder.IsSealed); + Assert.That(!getDecoder.IsVirtual); + Assert.That(getDecoder.IsOverride); } [Test] @@ -1957,22 +1954,22 @@ public void FindRedirectedType() var typeRef = ReflectionHelper.ParseReflectionName("System.Func`2, System.Core"); ITypeDefinition c = typeRef.Resolve(new SimpleTypeResolveContext(compilationWithSystemCore)).GetDefinition(); - Assert.IsNotNull(c, "System.Func<,> not found"); - Assert.AreEqual("mscorlib", c.ParentModule.AssemblyName); + Assert.That(c, Is.Not.Null, "System.Func<,> not found"); + Assert.That(c.ParentModule.AssemblyName, Is.EqualTo("mscorlib")); } public void DelegateIsClass() { var @delegate = compilation.FindType(KnownTypeCode.Delegate).GetDefinition(); - Assert.AreEqual(TypeKind.Class, @delegate); - Assert.IsFalse(@delegate.IsSealed); + Assert.That(@delegate, Is.EqualTo(TypeKind.Class)); + Assert.That(!@delegate.IsSealed); } public void MulticastDelegateIsClass() { var multicastDelegate = compilation.FindType(KnownTypeCode.MulticastDelegate).GetDefinition(); - Assert.AreEqual(TypeKind.Class, multicastDelegate); - Assert.IsFalse(multicastDelegate.IsSealed); + Assert.That(multicastDelegate, Is.EqualTo(TypeKind.Class)); + Assert.That(!multicastDelegate.IsSealed); } [Test] @@ -1988,13 +1985,13 @@ public void HasSpecialName() var @class = nonCustomAttributes.GetNestedTypes(t => t.Name == "SpecialNameClass").Single().GetDefinition(); var @struct = nonCustomAttributes.GetNestedTypes(t => t.Name == "SpecialNameStruct").Single().GetDefinition(); - Assert.IsTrue(method.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsTrue(property.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsTrue(@event.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsTrue(field.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(method.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(property.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(@event.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(field.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsTrue(@class.HasAttribute(KnownAttribute.SpecialName)); - Assert.IsTrue(@struct.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(@class.HasAttribute(KnownAttribute.SpecialName)); + Assert.That(@struct.HasAttribute(KnownAttribute.SpecialName)); } } } diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs index 1e2cceb6c5..620424ca85 100644 --- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs @@ -47,7 +47,7 @@ public void AllFilesHaveTests() || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) { var testName = file.Name.Split('.')[0]; - Assert.Contains(testName, testNames); + Assert.That(testNames, Has.Member(testName)); } } } diff --git a/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs b/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs index 1263bb4fa7..a7c5b3dc3c 100644 --- a/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs @@ -30,13 +30,13 @@ public void SetRange() { var bitset = new BitSet(302); bitset.Set(2, 300); - Assert.IsFalse(bitset[0]); - Assert.IsFalse(bitset[1]); + Assert.That(!bitset[0]); + Assert.That(!bitset[1]); for (int i = 2; i < 300; ++i) { - Assert.IsTrue(bitset[i]); + Assert.That(bitset[i]); } - Assert.IsFalse(bitset[301]); + Assert.That(!bitset[301]); } [Test] @@ -45,12 +45,12 @@ public void ClearRange() var bitset = new BitSet(300); bitset.Set(0, 300); bitset.Clear(1, 299); - Assert.IsTrue(bitset[0]); + Assert.That(bitset[0]); for (int i = 1; i < 299; ++i) { - Assert.IsFalse(bitset[i]); + Assert.That(!bitset[i]); } - Assert.IsTrue(bitset[299]); + Assert.That(bitset[299]); } [Test] @@ -58,14 +58,14 @@ public void AllInRange() { var bitset = new BitSet(300); bitset.Set(1, 299); - Assert.IsTrue(bitset.All(1, 299)); - Assert.IsTrue(bitset.All(10, 290)); - Assert.IsTrue(bitset.All(100, 200)); - Assert.IsFalse(bitset.All(0, 200)); - Assert.IsFalse(bitset.All(0, 1)); - Assert.IsFalse(bitset.All(1, 300)); + Assert.That(bitset.All(1, 299)); + Assert.That(bitset.All(10, 290)); + Assert.That(bitset.All(100, 200)); + Assert.That(!bitset.All(0, 200)); + Assert.That(!bitset.All(0, 1)); + Assert.That(!bitset.All(1, 300)); bitset[200] = false; - Assert.IsFalse(bitset.All(1, 299)); + Assert.That(!bitset.All(1, 299)); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs b/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs index e188f94780..19f8ea5e49 100644 --- a/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs @@ -29,157 +29,157 @@ public class FileUtilityTests [Test] public void NormalizePath() { - Assert.AreEqual(@"c:\temp\test.txt", FileUtility.NormalizePath(@"c:\temp\project\..\test.txt")); - Assert.AreEqual(@"c:\temp\test.txt", FileUtility.NormalizePath(@"c:\temp\project\.\..\test.txt")); - Assert.AreEqual(@"c:\temp\test.txt", FileUtility.NormalizePath(@"c:\temp\\test.txt")); // normalize double backslash - Assert.AreEqual(@"c:\temp", FileUtility.NormalizePath(@"c:\temp\.")); - Assert.AreEqual(@"c:\temp", FileUtility.NormalizePath(@"c:\temp\subdir\..")); + Assert.That(FileUtility.NormalizePath(@"c:\temp\project\..\test.txt"), Is.EqualTo(@"c:\temp\test.txt")); + Assert.That(FileUtility.NormalizePath(@"c:\temp\project\.\..\test.txt"), Is.EqualTo(@"c:\temp\test.txt")); + Assert.That(FileUtility.NormalizePath(@"c:\temp\\test.txt"), Is.EqualTo(@"c:\temp\test.txt")); // normalize double backslash + Assert.That(FileUtility.NormalizePath(@"c:\temp\."), Is.EqualTo(@"c:\temp")); + Assert.That(FileUtility.NormalizePath(@"c:\temp\subdir\.."), Is.EqualTo(@"c:\temp")); } [Test] public void NormalizePath_DriveRoot() { - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:\")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:/")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:/.")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:/..")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:/./")); - Assert.AreEqual(@"C:\", FileUtility.NormalizePath(@"C:/..\")); + Assert.That(FileUtility.NormalizePath(@"C:\"), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:/"), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:"), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:/."), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:/.."), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:/./"), Is.EqualTo(@"C:\")); + Assert.That(FileUtility.NormalizePath(@"C:/..\"), Is.EqualTo(@"C:\")); } [Test] public void NormalizePath_UNC() { - Assert.AreEqual(@"\\server\share", FileUtility.NormalizePath(@"\\server\share")); - Assert.AreEqual(@"\\server\share", FileUtility.NormalizePath(@"\\server\share\")); - Assert.AreEqual(@"\\server\share", FileUtility.NormalizePath(@"//server/share/")); - Assert.AreEqual(@"\\server\share\otherdir", FileUtility.NormalizePath(@"//server/share/dir/..\otherdir")); + Assert.That(FileUtility.NormalizePath(@"\\server\share"), Is.EqualTo(@"\\server\share")); + Assert.That(FileUtility.NormalizePath(@"\\server\share\"), Is.EqualTo(@"\\server\share")); + Assert.That(FileUtility.NormalizePath(@"//server/share/"), Is.EqualTo(@"\\server\share")); + Assert.That(FileUtility.NormalizePath(@"//server/share/dir/..\otherdir"), Is.EqualTo(@"\\server\share\otherdir")); } [Test] public void NormalizePath_Web() { - Assert.AreEqual(@"http://danielgrunwald.de/path/", FileUtility.NormalizePath(@"http://danielgrunwald.de/path/")); - Assert.AreEqual(@"browser://http://danielgrunwald.de/path/", FileUtility.NormalizePath(@"browser://http://danielgrunwald.de/wrongpath/../path/")); + Assert.That(FileUtility.NormalizePath(@"http://danielgrunwald.de/path/"), Is.EqualTo(@"http://danielgrunwald.de/path/")); + Assert.That(FileUtility.NormalizePath(@"browser://http://danielgrunwald.de/wrongpath/../path/"), Is.EqualTo(@"browser://http://danielgrunwald.de/path/")); } [Test] public void NormalizePath_Relative() { - Assert.AreEqual(@"../b", FileUtility.NormalizePath(@"..\a\..\b")); - Assert.AreEqual(@".", FileUtility.NormalizePath(@".")); - Assert.AreEqual(@".", FileUtility.NormalizePath(@"a\..")); + Assert.That(FileUtility.NormalizePath(@"..\a\..\b"), Is.EqualTo(@"../b")); + Assert.That(FileUtility.NormalizePath(@"."), Is.EqualTo(@".")); + Assert.That(FileUtility.NormalizePath(@"a\.."), Is.EqualTo(@".")); } [Test] public void NormalizePath_UnixStyle() { - Assert.AreEqual("/", FileUtility.NormalizePath("/")); - Assert.AreEqual("/a/b", FileUtility.NormalizePath("/a/b")); - Assert.AreEqual("/a/b", FileUtility.NormalizePath("/c/../a/./b")); - Assert.AreEqual("/a/b", FileUtility.NormalizePath("/c/../../a/./b")); + Assert.That(FileUtility.NormalizePath("/"), Is.EqualTo("/")); + Assert.That(FileUtility.NormalizePath("/a/b"), Is.EqualTo("/a/b")); + Assert.That(FileUtility.NormalizePath("/c/../a/./b"), Is.EqualTo("/a/b")); + Assert.That(FileUtility.NormalizePath("/c/../../a/./b"), Is.EqualTo("/a/b")); } #endregion [Test] public void TestIsBaseDirectory() { - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a", @"C:\A\b\hello")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a", @"C:\a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a\", @"C:\a\")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a\", @"C:\a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a", @"C:\a\")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\A", @"C:\a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a", @"C:\A")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\a\x\fWufhweoe", @"C:\a\x\fwuFHweoe\a\b\hello")); - - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\b\..\A", @"C:\a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\HELLO\..\B\..\a", @"C:\b\..\a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\.\B\..\.\.\a", @"C:\.\.\.\.\.\.\.\a")); - - Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\b", @"C:\a\b\hello")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\a\b\hello", @"C:\b")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\a\x\fwufhweoe", @"C:\a\x\fwuFHweoex\a\b\hello")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\", @"C:\")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\", @"C:\a\b\hello")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\", @"D:\a\b\hello")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a", @"C:\A\b\hello")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a", @"C:\a")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a\", @"C:\a\")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a\", @"C:\a")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a", @"C:\a\")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\A", @"C:\a")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a", @"C:\A")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\a\x\fWufhweoe", @"C:\a\x\fwuFHweoe\a\b\hello")); + + Assert.That(FileUtility.IsBaseDirectory(@"C:\b\..\A", @"C:\a")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\HELLO\..\B\..\a", @"C:\b\..\a")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\.\B\..\.\.\a", @"C:\.\.\.\.\.\.\.\a")); + + Assert.That(!FileUtility.IsBaseDirectory(@"C:\b", @"C:\a\b\hello")); + Assert.That(!FileUtility.IsBaseDirectory(@"C:\a\b\hello", @"C:\b")); + Assert.That(!FileUtility.IsBaseDirectory(@"C:\a\x\fwufhweoe", @"C:\a\x\fwuFHweoex\a\b\hello")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\", @"C:\")); + Assert.That(FileUtility.IsBaseDirectory(@"C:\", @"C:\a\b\hello")); + Assert.That(!FileUtility.IsBaseDirectory(@"C:\", @"D:\a\b\hello")); } [Test] public void TestIsBaseDirectoryRelative() { - Assert.IsTrue(FileUtility.IsBaseDirectory(@".", @"a\b")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@".", @"a")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@".", @"c:\")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@".", @"/")); + Assert.That(FileUtility.IsBaseDirectory(@".", @"a\b")); + Assert.That(FileUtility.IsBaseDirectory(@".", @"a")); + Assert.That(!FileUtility.IsBaseDirectory(@".", @"c:\")); + Assert.That(!FileUtility.IsBaseDirectory(@".", @"/")); } [Test] public void TestIsBaseDirectoryUnixStyle() { - Assert.IsTrue(FileUtility.IsBaseDirectory(@"/", @"/")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"/", @"/a")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"/", @"/a/subdir")); + Assert.That(FileUtility.IsBaseDirectory(@"/", @"/")); + Assert.That(FileUtility.IsBaseDirectory(@"/", @"/a")); + Assert.That(FileUtility.IsBaseDirectory(@"/", @"/a/subdir")); } [Test] public void TestIsBaseDirectoryUNC() { - Assert.IsTrue(FileUtility.IsBaseDirectory(@"\\server\share", @"\\server\share\dir\subdir")); - Assert.IsTrue(FileUtility.IsBaseDirectory(@"\\server\share", @"\\server\share\dir\subdir")); - Assert.IsFalse(FileUtility.IsBaseDirectory(@"\\server2\share", @"\\server\share\dir\subdir")); + Assert.That(FileUtility.IsBaseDirectory(@"\\server\share", @"\\server\share\dir\subdir")); + Assert.That(FileUtility.IsBaseDirectory(@"\\server\share", @"\\server\share\dir\subdir")); + Assert.That(!FileUtility.IsBaseDirectory(@"\\server2\share", @"\\server\share\dir\subdir")); } [Test] public void TestGetRelativePath() { - Assert.AreEqual(@"blub", FileUtility.GetRelativePath(@"C:\hello\.\..\a", @"C:\.\a\blub")); - Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\hello", @"C:\.\blub\.\..\.\a\.\blub")); - Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\hello\", @"C:\.\blub\.\..\.\a\.\blub")); - Assert.AreEqual(@".", FileUtility.GetRelativePath(@"C:\hello", @"C:\.\hello")); - Assert.AreEqual(@".", FileUtility.GetRelativePath(@"C:\", @"C:\")); - Assert.AreEqual(@"blub", FileUtility.GetRelativePath(@"C:\", @"C:\blub")); - Assert.AreEqual(@"D:\", FileUtility.GetRelativePath(@"C:\", @"D:\")); - Assert.AreEqual(@"D:\def", FileUtility.GetRelativePath(@"C:\abc", @"D:\def")); + Assert.That(FileUtility.GetRelativePath(@"C:\hello\.\..\a", @"C:\.\a\blub"), Is.EqualTo(@"blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\.\.\.\.\hello", @"C:\.\blub\.\..\.\a\.\blub"), Is.EqualTo(@"..\a\blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\.\.\.\.\hello\", @"C:\.\blub\.\..\.\a\.\blub"), Is.EqualTo(@"..\a\blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\hello", @"C:\.\hello"), Is.EqualTo(@".")); + Assert.That(FileUtility.GetRelativePath(@"C:\", @"C:\"), Is.EqualTo(@".")); + Assert.That(FileUtility.GetRelativePath(@"C:\", @"C:\blub"), Is.EqualTo(@"blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\", @"D:\"), Is.EqualTo(@"D:\")); + Assert.That(FileUtility.GetRelativePath(@"C:\abc", @"D:\def"), Is.EqualTo(@"D:\def")); // casing troubles - Assert.AreEqual(@"blub", FileUtility.GetRelativePath(@"C:\hello\.\..\A", @"C:\.\a\blub")); - Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\HELlo", @"C:\.\blub\.\..\.\a\.\blub")); - Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\heLLo\A\..", @"C:\.\blub\.\..\.\a\.\blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\hello\.\..\A", @"C:\.\a\blub"), Is.EqualTo(@"blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\.\.\.\.\HELlo", @"C:\.\blub\.\..\.\a\.\blub"), Is.EqualTo(@"..\a\blub")); + Assert.That(FileUtility.GetRelativePath(@"C:\.\.\.\.\heLLo\A\..", @"C:\.\blub\.\..\.\a\.\blub"), Is.EqualTo(@"..\a\blub")); } [Test] public void RelativeGetRelativePath() { // Relative path - Assert.AreEqual(@"a", FileUtility.GetRelativePath(@".", @"a")); - Assert.AreEqual(@"..", FileUtility.GetRelativePath(@"a", @".")); - Assert.AreEqual(@"..\b", FileUtility.GetRelativePath(@"a", @"b")); - Assert.AreEqual(@"..\..", FileUtility.GetRelativePath(@"a", @"..")); + Assert.That(FileUtility.GetRelativePath(@".", @"a"), Is.EqualTo(@"a")); + Assert.That(FileUtility.GetRelativePath(@"a", @"."), Is.EqualTo(@"..")); + Assert.That(FileUtility.GetRelativePath(@"a", @"b"), Is.EqualTo(@"..\b")); + Assert.That(FileUtility.GetRelativePath(@"a", @".."), Is.EqualTo(@"..\..")); // Getting a path from an absolute path to a relative path isn't really possible; // so we just keep the existing relative path (don't introduce incorrect '..\'). - Assert.AreEqual(@"def", FileUtility.GetRelativePath(@"C:\abc", @"def")); + Assert.That(FileUtility.GetRelativePath(@"C:\abc", @"def"), Is.EqualTo(@"def")); } [Test] public void GetRelativePath_Unix() { - Assert.AreEqual(@"a", FileUtility.GetRelativePath("/", "/a")); - Assert.AreEqual(@"a\b", FileUtility.GetRelativePath("/", "/a/b")); - Assert.AreEqual(@"b", FileUtility.GetRelativePath("/a", "/a/b")); + Assert.That(FileUtility.GetRelativePath("/", "/a"), Is.EqualTo(@"a")); + Assert.That(FileUtility.GetRelativePath("/", "/a/b"), Is.EqualTo(@"a\b")); + Assert.That(FileUtility.GetRelativePath("/a", "/a/b"), Is.EqualTo(@"b")); } [Test] public void TestIsEqualFile() { - Assert.IsTrue(FileUtility.IsEqualFileName(@"C:\.\Hello World.Exe", @"C:\HELLO WOrld.exe")); - Assert.IsTrue(FileUtility.IsEqualFileName(@"C:\bla\..\a\my.file.is.this", @"C:\gg\..\.\.\.\.\a\..\a\MY.FILE.IS.THIS")); + Assert.That(FileUtility.IsEqualFileName(@"C:\.\Hello World.Exe", @"C:\HELLO WOrld.exe")); + Assert.That(FileUtility.IsEqualFileName(@"C:\bla\..\a\my.file.is.this", @"C:\gg\..\.\.\.\.\a\..\a\MY.FILE.IS.THIS")); - Assert.IsFalse(FileUtility.IsEqualFileName(@"C:\.\Hello World.Exe", @"C:\HELLO_WOrld.exe")); - Assert.IsFalse(FileUtility.IsEqualFileName(@"C:\a\my.file.is.this", @"C:\gg\..\.\.\.\.\a\..\b\MY.FILE.IS.THIS")); + Assert.That(!FileUtility.IsEqualFileName(@"C:\.\Hello World.Exe", @"C:\HELLO_WOrld.exe")); + Assert.That(!FileUtility.IsEqualFileName(@"C:\a\my.file.is.this", @"C:\gg\..\.\.\.\.\a\..\b\MY.FILE.IS.THIS")); } } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs b/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs index 6fcf322af4..ff7dbcf1b5 100644 --- a/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs @@ -27,54 +27,54 @@ public class IntervalTests [Test] public void DefaultIsEmpty() { - Assert.IsTrue(default(Interval).IsEmpty); - Assert.IsFalse(default(Interval).Contains(-1)); - Assert.IsFalse(default(Interval).Contains(0)); - Assert.IsFalse(default(Interval).Contains(1)); + Assert.That(default(Interval).IsEmpty); + Assert.That(!default(Interval).Contains(-1)); + Assert.That(!default(Interval).Contains(0)); + Assert.That(!default(Interval).Contains(1)); } [Test] public void EmptyAt1() { Interval i = new Interval(1, 1); - Assert.IsTrue(default(Interval).IsEmpty); - Assert.IsFalse(default(Interval).Contains(-1)); - Assert.IsFalse(default(Interval).Contains(0)); - Assert.IsFalse(default(Interval).Contains(1)); - Assert.IsFalse(default(Interval).Contains(2)); + Assert.That(default(Interval).IsEmpty); + Assert.That(!default(Interval).Contains(-1)); + Assert.That(!default(Interval).Contains(0)); + Assert.That(!default(Interval).Contains(1)); + Assert.That(!default(Interval).Contains(2)); } [Test] public void OneToThree() { Interval i = new Interval(1, 3); - Assert.IsFalse(i.IsEmpty); - Assert.IsFalse(i.Contains(0)); - Assert.IsTrue(i.Contains(1)); - Assert.IsTrue(i.Contains(2)); - Assert.IsFalse(i.Contains(3)); + Assert.That(!i.IsEmpty); + Assert.That(!i.Contains(0)); + Assert.That(i.Contains(1)); + Assert.That(i.Contains(2)); + Assert.That(!i.Contains(3)); } [Test] public void FullInterval() { Interval full = new Interval(int.MinValue, int.MinValue); - Assert.IsFalse(full.IsEmpty); - Assert.IsTrue(full.Contains(int.MinValue)); - Assert.IsTrue(full.Contains(0)); - Assert.IsTrue(full.Contains(int.MaxValue)); + Assert.That(!full.IsEmpty); + Assert.That(full.Contains(int.MinValue)); + Assert.That(full.Contains(0)); + Assert.That(full.Contains(int.MaxValue)); } [Test] public void NonNegativeIntegers() { Interval i = new Interval(0, int.MinValue); - Assert.IsFalse(i.IsEmpty); - Assert.IsTrue(i.Contains(0)); - Assert.IsTrue(i.Contains(1000)); - Assert.IsTrue(i.Contains(int.MaxValue)); - Assert.IsFalse(i.Contains(-1)); - Assert.IsFalse(i.Contains(-1000)); - Assert.IsFalse(i.Contains(int.MinValue)); + Assert.That(!i.IsEmpty); + Assert.That(i.Contains(0)); + Assert.That(i.Contains(1000)); + Assert.That(i.Contains(int.MaxValue)); + Assert.That(!i.Contains(-1)); + Assert.That(!i.Contains(-1000)); + Assert.That(!i.Contains(int.MinValue)); } [Test] @@ -87,12 +87,12 @@ public void Intersection() Interval nonneg = new Interval(0, int.MinValue); Interval nonpos = new Interval(int.MinValue, 1); Interval maxval = new Interval(int.MaxValue, int.MinValue); - Assert.AreEqual(nonneg, full.Intersect(nonneg)); - Assert.AreEqual(nonneg, nonneg.Intersect(full)); - Assert.AreEqual(zero, nonneg.Intersect(zero)); - Assert.AreEqual(zero, nonneg.Intersect(nonpos)); - Assert.AreEqual(maxval, nonneg.Intersect(maxval)); - Assert.AreEqual(empty, nonpos.Intersect(maxval)); + Assert.That(full.Intersect(nonneg), Is.EqualTo(nonneg)); + Assert.That(nonneg.Intersect(full), Is.EqualTo(nonneg)); + Assert.That(nonneg.Intersect(zero), Is.EqualTo(zero)); + Assert.That(nonneg.Intersect(nonpos), Is.EqualTo(zero)); + Assert.That(nonneg.Intersect(maxval), Is.EqualTo(maxval)); + Assert.That(nonpos.Intersect(maxval), Is.EqualTo(empty)); } } } diff --git a/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs b/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs index 1718a394bb..e74c8a6980 100644 --- a/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs @@ -32,94 +32,92 @@ public class LongSetTests public void UpperBound() { var longSet = new LongSet(new[] { new LongInterval(1, 5), new LongInterval(6, 7) }.ToImmutableArray()); - Assert.AreEqual(0, longSet.upper_bound(0)); + Assert.That(longSet.upper_bound(0), Is.EqualTo(0)); for (int i = 1; i <= 5; i++) - Assert.AreEqual(1, longSet.upper_bound(i)); + Assert.That(longSet.upper_bound(i), Is.EqualTo(1)); for (int i = 6; i <= 10; i++) - Assert.AreEqual(2, longSet.upper_bound(i)); + Assert.That(longSet.upper_bound(i), Is.EqualTo(2)); } [Test] public void UniverseContainsAll() { - Assert.IsTrue(LongSet.Universe.Contains(long.MinValue)); - Assert.IsTrue(LongSet.Universe.Contains(1)); - Assert.IsTrue(LongSet.Universe.Contains(long.MaxValue)); - Assert.IsFalse(LongSet.Universe.IsEmpty); + Assert.That(LongSet.Universe.Contains(long.MinValue)); + Assert.That(LongSet.Universe.Contains(1)); + Assert.That(LongSet.Universe.Contains(long.MaxValue)); + Assert.That(!LongSet.Universe.IsEmpty); } [Test] public void IntersectUniverse() { - Assert.AreEqual(LongSet.Universe, LongSet.Universe.IntersectWith(LongSet.Universe)); - Assert.AreEqual(LongSet.Empty, LongSet.Universe.IntersectWith(LongSet.Empty)); - Assert.AreEqual(new LongSet(long.MaxValue), LongSet.Universe.IntersectWith(new LongSet(long.MaxValue))); + Assert.That(LongSet.Universe.IntersectWith(LongSet.Universe), Is.EqualTo(LongSet.Universe)); + Assert.That(LongSet.Universe.IntersectWith(LongSet.Empty), Is.EqualTo(LongSet.Empty)); + Assert.That(LongSet.Universe.IntersectWith(new LongSet(long.MaxValue)), Is.EqualTo(new LongSet(long.MaxValue))); var longSet = new LongSet(new[] { new LongInterval(1, 5), new LongInterval(6, 7) }.ToImmutableArray()); - Assert.AreEqual(longSet, longSet.IntersectWith(LongSet.Universe)); + Assert.That(longSet.IntersectWith(LongSet.Universe), Is.EqualTo(longSet)); } [Test] public void UnionUniverse() { - Assert.AreEqual(LongSet.Universe, LongSet.Universe.UnionWith(LongSet.Universe)); - Assert.AreEqual(LongSet.Universe, LongSet.Universe.UnionWith(LongSet.Empty)); - Assert.AreEqual(LongSet.Universe, LongSet.Universe.UnionWith(new LongSet(long.MaxValue))); + Assert.That(LongSet.Universe.UnionWith(LongSet.Universe), Is.EqualTo(LongSet.Universe)); + Assert.That(LongSet.Universe.UnionWith(LongSet.Empty), Is.EqualTo(LongSet.Universe)); + Assert.That(LongSet.Universe.UnionWith(new LongSet(long.MaxValue)), Is.EqualTo(LongSet.Universe)); var longSet = new LongSet(new[] { new LongInterval(1, 5), new LongInterval(6, 7) }.ToImmutableArray()); - Assert.AreEqual(LongSet.Universe, longSet.UnionWith(LongSet.Universe)); + Assert.That(longSet.UnionWith(LongSet.Universe), Is.EqualTo(LongSet.Universe)); } [Test] public void ExceptWithUniverse() { - Assert.AreEqual(LongSet.Universe, LongSet.Universe.ExceptWith(LongSet.Empty)); - Assert.AreEqual(LongSet.Empty, LongSet.Universe.ExceptWith(LongSet.Universe)); - Assert.AreEqual(LongSet.Empty, LongSet.Empty.ExceptWith(LongSet.Universe)); - Assert.AreEqual(LongSet.Empty, LongSet.Empty.ExceptWith(LongSet.Empty)); + Assert.That(LongSet.Universe.ExceptWith(LongSet.Empty), Is.EqualTo(LongSet.Universe)); + Assert.That(LongSet.Universe.ExceptWith(LongSet.Universe), Is.EqualTo(LongSet.Empty)); + Assert.That(LongSet.Empty.ExceptWith(LongSet.Universe), Is.EqualTo(LongSet.Empty)); + Assert.That(LongSet.Empty.ExceptWith(LongSet.Empty), Is.EqualTo(LongSet.Empty)); } [Test] public void UnionWith() { - Assert.AreEqual(new LongSet(new LongInterval(0, 2)), - new LongSet(0).UnionWith(new LongSet(1))); + Assert.That(new LongSet(0).UnionWith(new LongSet(1)), Is.EqualTo(new LongSet(new LongInterval(0, 2)))); - Assert.AreEqual(LongSet.Universe, new LongSet(0).Invert().UnionWith(new LongSet(0))); + Assert.That(new LongSet(0).Invert().UnionWith(new LongSet(0)), Is.EqualTo(LongSet.Universe)); } [Test] public void AddTo() { - Assert.AreEqual(new LongSet(1), new LongSet(0).AddOffset(1)); - Assert.AreEqual(new LongSet(long.MinValue), new LongSet(long.MaxValue).AddOffset(1)); + Assert.That(new LongSet(0).AddOffset(1), Is.EqualTo(new LongSet(1))); + Assert.That(new LongSet(long.MaxValue).AddOffset(1), Is.EqualTo(new LongSet(long.MinValue))); TestAddTo(new LongSet(new LongInterval(-10, 10)), 5); TestAddTo(new LongSet(new LongInterval(-10, 10)), long.MaxValue); - Assert.AreEqual(new LongSet(10).Invert(), new LongSet(0).Invert().AddOffset(10)); - Assert.AreEqual(new LongSet(20).Invert(), new LongSet(30).Invert().AddOffset(-10)); + Assert.That(new LongSet(0).Invert().AddOffset(10), Is.EqualTo(new LongSet(10).Invert())); + Assert.That(new LongSet(30).Invert().AddOffset(-10), Is.EqualTo(new LongSet(20).Invert())); } void TestAddTo(LongSet input, long constant) { - Assert.AreEqual( - input.Values.Select(e => unchecked(e + constant)).OrderBy(e => e).ToList(), - input.AddOffset(constant).Values.ToList()); + Assert.That( + input.AddOffset(constant).Values.ToList(), Is.EqualTo(input.Values.Select(e => unchecked(e + constant)).OrderBy(e => e).ToList())); } [Test] public void Values() { - Assert.IsFalse(LongSet.Empty.Values.Any()); - Assert.IsTrue(LongSet.Universe.Values.Any()); - Assert.AreEqual(new[] { 1, 2, 3 }, new LongSet(LongInterval.Inclusive(1, 3)).Values.ToArray()); + Assert.That(!LongSet.Empty.Values.Any()); + Assert.That(LongSet.Universe.Values.Any()); + Assert.That(new LongSet(LongInterval.Inclusive(1, 3)).Values.ToArray(), Is.EqualTo(new[] { 1, 2, 3 })); } [Test] public void ValueCount() { - Assert.AreEqual(0, LongSet.Empty.Count()); - Assert.AreEqual(ulong.MaxValue, new LongSet(3).Invert().Count()); - Assert.AreEqual(ulong.MaxValue, LongSet.Universe.Count()); - Assert.AreEqual(long.MaxValue + 2ul, new LongSet(LongInterval.Inclusive(-1, long.MaxValue)).Count()); + Assert.That(LongSet.Empty.Count(), Is.EqualTo(0)); + Assert.That(new LongSet(3).Invert().Count(), Is.EqualTo(ulong.MaxValue)); + Assert.That(LongSet.Universe.Count(), Is.EqualTo(ulong.MaxValue)); + Assert.That(new LongSet(LongInterval.Inclusive(-1, long.MaxValue)).Count(), Is.EqualTo(long.MaxValue + 2ul)); } } } diff --git a/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs b/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs index cad0afa930..59f8aadce0 100644 --- a/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs @@ -100,9 +100,9 @@ public void Read(string name, object value) using var testFile = ProduceResourcesTestFile(name, value); using var reader = new ResourcesFile(testFile); var items = reader.ToArray(); - Assert.AreEqual(1, items.Length); - Assert.AreEqual(name, items[0].Key); - Assert.AreEqual(value, items[0].Value); + Assert.That(items.Length, Is.EqualTo(1)); + Assert.That(items[0].Key, Is.EqualTo(name)); + Assert.That(items[0].Value, Is.EqualTo(value)); } [TestCase("Null", null, null, "System.Resources.ResXNullRef" + WinFormsAssemblyName)] @@ -124,14 +124,14 @@ public void Read(string name, object value) public void Write(string name, object value, string serializedValue, string typeName) { var element = ProduceResXTest(name, value); - Assert.AreEqual(name, element.Attribute("name")?.Value); + Assert.That(element.Attribute("name")?.Value, Is.EqualTo(name)); if (typeName != null) { - Assert.AreEqual(typeName, element.Attribute("type")?.Value); + Assert.That(element.Attribute("type")?.Value, Is.EqualTo(typeName)); } var v = element.Element("value"); - Assert.IsNotNull(v); - Assert.IsTrue(v.IsEmpty ? serializedValue == null : v.Value == serializedValue); + Assert.That(v, Is.Not.Null); + Assert.That(v.IsEmpty ? serializedValue == null : v.Value == serializedValue); } [Test] @@ -149,10 +149,10 @@ public void BitmapIsResourceSerializedObject() .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources"); using var reader = new ResourcesFile(stream); var items = reader.ToArray(); - Assert.AreEqual(3, items.Length); + Assert.That(items.Length, Is.EqualTo(3)); var item = items.FirstOrDefault(i => i.Key == "Bitmap"); - Assert.IsNotNull(item.Key); - Assert.IsInstanceOf(item.Value); + Assert.That(item.Key, Is.Not.Null); + Assert.That(item.Value, Is.InstanceOf()); } [Test] @@ -162,15 +162,15 @@ public void ByteArrayIsSupported() .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources"); using var reader = new ResourcesFile(stream); var items = reader.ToArray(); - Assert.AreEqual(3, items.Length); + Assert.That(items.Length, Is.EqualTo(3)); var item = items.FirstOrDefault(i => i.Key == "Byte[]"); - Assert.IsNotNull(item.Key); - Assert.IsInstanceOf(item.Value); + Assert.That(item.Key, Is.Not.Null); + Assert.That(item.Value, Is.InstanceOf()); byte[] array = (byte[])item.Value; - Assert.AreEqual(3, array.Length); - Assert.AreEqual(42, array[0]); - Assert.AreEqual(43, array[1]); - Assert.AreEqual(44, array[2]); + Assert.That(array.Length, Is.EqualTo(3)); + Assert.That(array[0], Is.EqualTo(42)); + Assert.That(array[1], Is.EqualTo(43)); + Assert.That(array[2], Is.EqualTo(44)); } [Test] @@ -180,10 +180,10 @@ public void MemoryStreamIsSupported() .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources"); using var reader = new ResourcesFile(stream); var items = reader.ToArray(); - Assert.AreEqual(3, items.Length); + Assert.That(items.Length, Is.EqualTo(3)); var item = items.FirstOrDefault(i => i.Key == "MemoryStream"); - Assert.IsNotNull(item.Key); - Assert.IsInstanceOf(item.Value); + Assert.That(item.Key, Is.Not.Null); + Assert.That(item.Value, Is.InstanceOf()); } } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index 2dcd061392..c21dc07758 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -45,8 +45,8 @@ public void AllFilesHaveTests() if (file.Extension.Equals(".vb", StringComparison.OrdinalIgnoreCase)) { var testName = file.Name.Split('.')[0]; - Assert.Contains(testName, testNames); - Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); + Assert.That(testNames, Has.Member(testName)); + Assert.That(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); } } } diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index cedf888944..9d44a14a35 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -251,7 +251,7 @@ public CSharpDecompiler(string fileName, IAssemblyResolver assemblyResolver, Dec /// /// Creates a new instance from the given using the given and . /// - public CSharpDecompiler(PEFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + public CSharpDecompiler(MetadataFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings) : this(new DecompilerTypeSystem(module, assemblyResolver, settings), settings) { } @@ -264,7 +264,7 @@ public CSharpDecompiler(DecompilerTypeSystem typeSystem, DecompilerSettings sett this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem)); this.settings = settings; this.module = typeSystem.MainModule; - this.metadata = module.PEFile.Metadata; + this.metadata = module.MetadataFile.Metadata; if (module.TypeSystemOptions.HasFlag(TypeSystemOptions.Uncached)) throw new ArgumentException("Cannot use an uncached type system in the decompiler."); } @@ -276,7 +276,7 @@ public CSharpDecompiler(DecompilerTypeSystem typeSystem, DecompilerSettings sett /// The module containing the member. /// The metadata token/handle of the member. Can be a TypeDef, MethodDef or FieldDef. /// THe settings used to determine whether code should be hidden. E.g. if async methods are not transformed, async state machines are included in the decompiled code. - public static bool MemberIsHidden(Metadata.PEFile module, EntityHandle member, DecompilerSettings settings) + public static bool MemberIsHidden(MetadataFile module, EntityHandle member, DecompilerSettings settings) { if (module == null || member.IsNil) return false; @@ -539,7 +539,7 @@ IDocumentationProvider CreateDefaultDocumentationProvider() { try { - return XmlDocLoader.LoadDocumentation(module.PEFile); + return XmlDocLoader.LoadDocumentation(module.MetadataFile); } catch (System.Xml.XmlException) { @@ -633,7 +633,7 @@ void DoDecompileTypes(IEnumerable types, DecompileRun deco var typeDef = module.GetDefinition(typeDefHandle); if (typeDef.Name == "" && typeDef.Members.Count == 0) continue; - if (MemberIsHidden(module.PEFile, typeDefHandle, settings)) + if (MemberIsHidden(module.MetadataFile, typeDefHandle, settings)) continue; if (string.IsNullOrEmpty(typeDef.Namespace)) { @@ -702,7 +702,7 @@ public ILTransformContext CreateILTransformContext(ILFunction function) /// /// Determines the "code-mappings" for a given TypeDef or MethodDef. See for more information. /// - public static CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public static CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { var declaringType = (TypeDefinitionHandle)member.GetDeclaringType(module.Metadata); @@ -744,7 +744,7 @@ public static CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle mem return info; } - private static void ReadCodeMappingInfo(PEFile module, CodeMappingInfo info, MethodDefinitionHandle parent, MethodDefinitionHandle part, Queue connectedMethods, HashSet processedNestedTypes) + private static void ReadCodeMappingInfo(MetadataFile module, CodeMappingInfo info, MethodDefinitionHandle parent, MethodDefinitionHandle part, Queue connectedMethods, HashSet processedNestedTypes) { var md = module.Metadata.GetMethodDefinition(part); @@ -756,7 +756,7 @@ private static void ReadCodeMappingInfo(PEFile module, CodeMappingInfo info, Met var declaringType = md.GetDeclaringType(); - var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); + var blob = module.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); while (blob.RemainingBytes > 0) { var code = blob.DecodeOpCode(); @@ -1357,7 +1357,7 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun // Decompile members that are not compiler-generated. foreach (var entity in allOrderedEntities) { - if (entity.MetadataToken.IsNil || MemberIsHidden(module.PEFile, entity.MetadataToken, settings)) + if (entity.MetadataToken.IsNil || MemberIsHidden(module.MetadataFile, entity.MetadataToken, settings)) { continue; } @@ -1403,7 +1403,7 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun if (typeDecl.ClassType == ClassType.Enum) { Debug.Assert(typeDef.Kind == TypeKind.Enum); - EnumValueDisplayMode displayMode = DetectBestEnumValueDisplayMode(typeDef, module.PEFile); + EnumValueDisplayMode displayMode = DetectBestEnumValueDisplayMode(typeDef, module.MetadataFile); switch (displayMode) { case EnumValueDisplayMode.FirstOnly: @@ -1532,7 +1532,7 @@ void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler, Partia } } - EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module) + EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, MetadataFile module) { if (typeDef.HasAttribute(KnownAttribute.Flags)) return EnumValueDisplayMode.AllHex; @@ -1608,7 +1608,7 @@ EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeRe } FixParameterNames(methodDecl); var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) + if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.MetadataFile, (MethodDefinitionHandle)method.MetadataToken)) { // if local functions are not active and we're dealing with a local function, // reduce the visibility of the method to private, @@ -1701,7 +1701,7 @@ void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun de MethodBodyBlock methodBody; try { - methodBody = module.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + methodBody = module.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); } catch (BadImageFormatException ex) { @@ -1980,7 +1980,7 @@ EntityDeclaration DoDecompile(IField field, DecompileRun decompileRun, ITypeReso string message; try { - var initVal = fieldDefinition.GetInitialValue(module.PEFile.Reader, TypeSystem); + var initVal = fieldDefinition.GetInitialValue(module.MetadataFile, TypeSystem); message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(initVal.ReadBytes(initVal.RemainingBytes)).Replace('-', ' ')); } catch (BadImageFormatException ex) diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs index 26c1a8a587..28f55f6be5 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// An interface for a service that creates and writes a project file structure /// for a specific module being decompiled. /// - interface IProjectFileWriter + public interface IProjectFileWriter { /// /// Writes the content of a new project file for the specified being decompiled. @@ -36,6 +36,6 @@ interface IProjectFileWriter /// The information about the project being created. /// A collection of source files to be included into the project. /// The module being decompiled. - void Write(TextWriter target, IProjectInfoProvider project, IEnumerable files, PEFile module); + void Write(TextWriter target, IProjectInfoProvider project, IEnumerable files, MetadataFile module); } } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs index 306afd4562..dc3d65f3f7 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// /// An interface that provides common information for a project being decompiled to. /// - interface IProjectInfoProvider + public interface IProjectInfoProvider { /// /// Gets the assembly resolver active for the project. diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs index eb383ba750..a536d72c74 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs @@ -45,10 +45,10 @@ public void Write( TextWriter target, IProjectInfoProvider project, IEnumerable files, - PEFile module) + MetadataFile module) { const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; - string platformName = TargetServices.GetPlatformName(module); + string platformName = module is PEFile peFile ? TargetServices.GetPlatformName(peFile) : "AnyCPU"; var targetFramework = TargetServices.DetectTargetFramework(module); if (targetFramework.Identifier == ".NETFramework" && targetFramework.VersionNumber == 200) targetFramework = TargetServices.DetectTargetFrameworkNET20(module, project.AssemblyResolver, targetFramework); @@ -80,26 +80,22 @@ public void Write( w.WriteValue(platformName); w.WriteEndElement(); // - if (module.Reader.PEHeaders.IsDll) - { - w.WriteElementString("OutputType", "Library"); - } - else + string outputType; + + switch ((module as PEFile)?.Reader.PEHeaders.PEHeader.Subsystem) { - switch (module.Reader.PEHeaders.PEHeader.Subsystem) - { - case Subsystem.WindowsGui: - w.WriteElementString("OutputType", "WinExe"); - break; - case Subsystem.WindowsCui: - w.WriteElementString("OutputType", "Exe"); - break; - default: - w.WriteElementString("OutputType", "Library"); - break; - } + case Subsystem.WindowsGui: + outputType = "WinExe"; + break; + case Subsystem.WindowsCui: + outputType = "Exe"; + break; + default: + outputType = "Library"; + break; } + w.WriteElementString("OutputType", outputType); w.WriteElementString("LangVersion", project.LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); w.WriteElementString("AssemblyName", module.Name); @@ -123,7 +119,8 @@ public void Write( w.WriteStartElement("PropertyGroup"); // platform-specific w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); w.WriteElementString("PlatformTarget", platformName); - if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) + if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" + && ((module as PEFile)?.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) { w.WriteElementString("Prefer32Bit", "false"); } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs index b5273f1d56..ee0029dc94 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs @@ -67,7 +67,7 @@ public void Write( TextWriter target, IProjectInfoProvider project, IEnumerable files, - PEFile module) + MetadataFile module) { using (XmlTextWriter xmlWriter = new XmlTextWriter(target)) { @@ -76,7 +76,7 @@ public void Write( } } - static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable files, PEFile module) + static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable files, MetadataFile module) { xml.WriteStartElement("Project"); @@ -105,18 +105,30 @@ static void PlaceIntoTag(string tagName, XmlTextWriter xml, Action content) } } - static void WriteAssemblyInfo(XmlTextWriter xml, PEFile module, IProjectInfoProvider project, ProjectType projectType) + static void WriteAssemblyInfo(XmlTextWriter xml, MetadataFile module, IProjectInfoProvider project, ProjectType projectType) { xml.WriteElementString("AssemblyName", module.Name); // Since we create AssemblyInfo.cs manually, we need to disable the auto-generation xml.WriteElementString("GenerateAssemblyInfo", FalseString); - WriteOutputType(xml, module.Reader.PEHeaders.IsDll, module.Reader.PEHeaders.PEHeader.Subsystem, projectType); + string platformName; + CorFlags flags; + if (module is PEFile { Reader.PEHeaders: var headers } peFile) + { + WriteOutputType(xml, headers.IsDll, headers.PEHeader.Subsystem, projectType); + platformName = TargetServices.GetPlatformName(peFile); + flags = headers.CorHeader.Flags; + } + else + { + WriteOutputType(xml, isDll: true, Subsystem.Unknown, projectType); + platformName = AnyCpuString; + flags = 0; + } WriteDesktopExtensions(xml, projectType); - string platformName = TargetServices.GetPlatformName(module); var targetFramework = TargetServices.DetectTargetFramework(module); if (targetFramework.Identifier == ".NETFramework" && targetFramework.VersionNumber == 200) targetFramework = TargetServices.DetectTargetFrameworkNET20(module, project.AssemblyResolver, targetFramework); @@ -134,7 +146,7 @@ static void WriteAssemblyInfo(XmlTextWriter xml, PEFile module, IProjectInfoProv xml.WriteElementString("PlatformTarget", platformName); } - if (platformName == AnyCpuString && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) + if (platformName == AnyCpuString && (flags & CorFlags.Prefers32Bit) != 0) { xml.WriteElementString("Prefer32Bit", TrueString); } @@ -238,7 +250,7 @@ static void WriteResources(XmlTextWriter xml, IEnumerable files } } - static void WriteReferences(XmlTextWriter xml, PEFile module, IProjectInfoProvider project, ProjectType projectType) + static void WriteReferences(XmlTextWriter xml, MetadataFile module, IProjectInfoProvider project, ProjectType projectType) { bool isNetCoreApp = TargetServices.DetectTargetFramework(module).Identifier == ".NETCoreApp"; var targetPacks = new HashSet(); @@ -292,7 +304,7 @@ static string GetSdkString(ProjectType projectType) } } - static ProjectType GetProjectType(PEFile module) + static ProjectType GetProjectType(MetadataFile module) { foreach (var referenceName in module.AssemblyReferences.Select(r => r.Name)) { diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs index eb00bc6c9f..adbf96fc45 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs @@ -39,7 +39,7 @@ static class TargetServices /// The module to get the target framework description for. Cannot be null. /// A new instance of the class that describes the specified . /// - public static TargetFramework DetectTargetFramework(PEFile module) + public static TargetFramework DetectTargetFramework(MetadataFile module) { if (module is null) { @@ -216,9 +216,9 @@ public static string GetPlatformName(PEFile module) }; /// - /// Gets exact if is + /// Gets exact if is /// - public static TargetFramework DetectTargetFrameworkNET20(PEFile module, IAssemblyResolver assemblyResolver, TargetFramework targetFramework) + public static TargetFramework DetectTargetFrameworkNET20(MetadataFile module, IAssemblyResolver assemblyResolver, TargetFramework targetFramework) { var resolvedAssemblies = new HashSet(); int version = 200; @@ -226,7 +226,7 @@ public static TargetFramework DetectTargetFrameworkNET20(PEFile module, IAssembl return new TargetFramework(targetFramework.Identifier, version, targetFramework.Profile); } - static void GetFrameworkVersionNET20(PEFile module, IAssemblyResolver assemblyResolver, HashSet resolvedAssemblies, ref int version) + static void GetFrameworkVersionNET20(MetadataFile module, IAssemblyResolver assemblyResolver, HashSet resolvedAssemblies, ref int version) { foreach (var r in module.Metadata.AssemblyReferences) { @@ -245,7 +245,7 @@ static void GetFrameworkVersionNET20(PEFile module, IAssemblyResolver assemblyRe break; } - PEFile resolvedReference; + MetadataFile resolvedReference; try { resolvedReference = assemblyResolver.Resolve(reference); diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 4dd22ee8fd..ed757600b7 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -37,8 +37,6 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using Microsoft.Win32; - using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -101,16 +99,17 @@ public LanguageVersion LanguageVersion { #endregion public WholeProjectDecompiler(IAssemblyResolver assemblyResolver) - : this(new DecompilerSettings(), assemblyResolver, assemblyReferenceClassifier: null, debugInfoProvider: null) + : this(new DecompilerSettings(), assemblyResolver, projectWriter: null, assemblyReferenceClassifier: null, debugInfoProvider: null) { } public WholeProjectDecompiler( DecompilerSettings settings, IAssemblyResolver assemblyResolver, + IProjectFileWriter projectWriter, AssemblyReferenceClassifier assemblyReferenceClassifier, IDebugInfoProvider debugInfoProvider) - : this(settings, Guid.NewGuid(), assemblyResolver, assemblyReferenceClassifier, debugInfoProvider) + : this(settings, Guid.NewGuid(), assemblyResolver, projectWriter, assemblyReferenceClassifier, debugInfoProvider) { } @@ -118,6 +117,7 @@ protected WholeProjectDecompiler( DecompilerSettings settings, Guid projectGuid, IAssemblyResolver assemblyResolver, + IProjectFileWriter projectWriter, AssemblyReferenceClassifier assemblyReferenceClassifier, IDebugInfoProvider debugInfoProvider) { @@ -126,23 +126,23 @@ protected WholeProjectDecompiler( AssemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver)); AssemblyReferenceClassifier = assemblyReferenceClassifier ?? new AssemblyReferenceClassifier(); DebugInfoProvider = debugInfoProvider; - projectWriter = Settings.UseSdkStyleProjectFormat ? ProjectFileWriterSdkStyle.Create() : ProjectFileWriterDefault.Create(); + this.projectWriter = projectWriter ?? (Settings.UseSdkStyleProjectFormat ? ProjectFileWriterSdkStyle.Create() : ProjectFileWriterDefault.Create()); } // per-run members HashSet directories = new HashSet(Platform.FileNameComparer); readonly IProjectFileWriter projectWriter; - public void DecompileProject(PEFile moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) + public void DecompileProject(MetadataFile file, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) { - string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(moduleDefinition.Name) + ".csproj"); + string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(file.Name) + ".csproj"); using (var writer = new StreamWriter(projectFileName)) { - DecompileProject(moduleDefinition, targetDirectory, writer, cancellationToken); + DecompileProject(file, targetDirectory, writer, cancellationToken); } } - public ProjectId DecompileProject(PEFile moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) + public ProjectId DecompileProject(MetadataFile file, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) { if (string.IsNullOrEmpty(targetDirectory)) { @@ -150,23 +150,27 @@ protected WholeProjectDecompiler( } TargetDirectory = targetDirectory; directories.Clear(); - var resources = WriteResourceFilesInProject(moduleDefinition).ToList(); - var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty()).ToList(), cancellationToken).ToList(); + var resources = WriteResourceFilesInProject(file).ToList(); + var files = WriteCodeFilesInProject(file, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty()).ToList(), cancellationToken).ToList(); files.AddRange(resources); - files.AddRange(WriteMiscellaneousFilesInProject(moduleDefinition)); + var module = file as PEFile; + if (module != null) + { + files.AddRange(WriteMiscellaneousFilesInProject(module)); + } if (StrongNameKeyFile != null) { File.Copy(StrongNameKeyFile, Path.Combine(targetDirectory, Path.GetFileName(StrongNameKeyFile)), overwrite: true); } - projectWriter.Write(projectFileWriter, this, files, moduleDefinition); + projectWriter.Write(projectFileWriter, this, files, file); - string platformName = TargetServices.GetPlatformName(moduleDefinition); + string platformName = module != null ? TargetServices.GetPlatformName(module) : "AnyCPU"; return new ProjectId(platformName, ProjectGuid, ProjectTypeGuids.CSharpWindows); } #region WriteCodeFilesInProject - protected virtual bool IncludeTypeWhenDecompilingProject(PEFile module, TypeDefinitionHandle type) + protected virtual bool IncludeTypeWhenDecompilingProject(MetadataFile module, TypeDefinitionHandle type) { var metadata = module.Metadata; var typeDef = metadata.GetTypeDefinition(type); @@ -208,7 +212,7 @@ IEnumerable WriteAssemblyInfo(DecompilerTypeSystem ts, Cancella return new[] { new ProjectItemInfo("Compile", assemblyInfo) }; } - IEnumerable WriteCodeFilesInProject(Metadata.PEFile module, IList partialTypes, CancellationToken cancellationToken) + IEnumerable WriteCodeFilesInProject(MetadataFile module, IList partialTypes, CancellationToken cancellationToken) { var metadata = module.Metadata; var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)) @@ -244,7 +248,18 @@ string GetFileFileNameForHandle(TypeDefinitionHandle h) { string dir = Settings.UseNestedDirectoriesForNamespaces ? CleanUpPath(ns) : CleanUpDirectoryName(ns); if (directories.Add(dir)) - Directory.CreateDirectory(Path.Combine(TargetDirectory, dir)); + { + var path = Path.Combine(TargetDirectory, dir); + try + { + Directory.CreateDirectory(path); + } + catch (IOException) + { + File.Delete(path); + Directory.CreateDirectory(path); + } + } return Path.Combine(dir, file); } } @@ -306,7 +321,7 @@ void ProcessFiles(List> files) #endregion #region WriteResourceFilesInProject - protected virtual IEnumerable WriteResourceFilesInProject(Metadata.PEFile module) + protected virtual IEnumerable WriteResourceFilesInProject(MetadataFile module) { foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded)) { @@ -758,7 +773,7 @@ static bool IsReservedFileSystemName(string name) } } - public static bool CanUseSdkStyleProjectFormat(PEFile module) + public static bool CanUseSdkStyleProjectFormat(MetadataFile module) { return TargetServices.DetectTargetFramework(module).Moniker != null; } diff --git a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs index 6ddc23b437..8abe102f2c 100644 --- a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs @@ -1100,7 +1100,7 @@ Block DecompileBody(IMethod method) var genericContext = new GenericContext( classTypeParameters: recordTypeDef.TypeParameters, methodTypeParameters: null); - var body = typeSystem.MainModule.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = typeSystem.MainModule.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); var ilReader = new ILReader(typeSystem.MainModule); var il = ilReader.ReadIL(methodDefHandle, body, genericContext, ILFunctionKind.TopLevelFunction, cancellationToken); var settings = new DecompilerSettings(LanguageVersion.CSharp1); diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index bdb77fab44..d304ad3fe6 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -58,10 +58,10 @@ public static void CollectNamespaces(IEntity entity, MetadataModule module, Hash void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo mappingInfo = null) { - if (entity == null || entity.MetadataToken.IsNil) + if (entity == null || entity.MetadataToken.IsNil || module.MetadataFile is not MetadataFile corFile) return; if (mappingInfo == null) - mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); + mappingInfo = CSharpDecompiler.GetCodeMappingInfo(corFile, entity.MetadataToken); switch (entity) { case ITypeDefinition td: @@ -104,7 +104,6 @@ void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo ma CollectNamespacesForTypeReference(field.ReturnType); break; case IMethod method: - var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); foreach (var part in parts) { @@ -125,7 +124,7 @@ void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo ma MethodBodyBlock body; try { - body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); + body = module.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); } catch (BadImageFormatException) { diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs index bb32e2ac6f..6d00db35a2 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs @@ -311,7 +311,7 @@ void HandleStaticFieldInitializers(IEnumerable members) IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; if (!ctorMethod.MetadataToken.IsNil) { - var metadata = context.TypeSystem.MainModule.PEFile.Metadata; + var metadata = context.TypeSystem.MainModule.MetadataFile.Metadata; SRM.MethodDefinition ctorMethodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)ctorMethod.MetadataToken); SRM.TypeDefinition declaringType = metadata.GetTypeDefinition(ctorMethodDef.GetDeclaringType()); bool declaringTypeIsBeforeFieldInit = declaringType.HasFlag(TypeAttributes.BeforeFieldInit); diff --git a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs index 84de80d2ac..daca4e6e31 100644 --- a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs +++ b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs @@ -19,15 +19,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -231,11 +228,11 @@ void HandleMethod(AstNode node, ILFunction function) this.functions.Add(function); var method = function.MoveNextMethod ?? function.Method; MethodDefinitionHandle handle = (MethodDefinitionHandle)method.MetadataToken; - var file = typeSystem.MainModule.PEFile; + var file = typeSystem.MainModule.MetadataFile; MethodDefinition md = file.Metadata.GetMethodDefinition(handle); if (md.HasBody()) { - HandleMethodBody(function, file.Reader.GetMethodBody(md.RelativeVirtualAddress)); + HandleMethodBody(function, file.GetMethodBody(md.RelativeVirtualAddress)); } } diff --git a/ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs b/ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs index 5c148df258..810919e567 100644 --- a/ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs +++ b/ICSharpCode.Decompiler/DebugInfo/IDebugInfoProvider.cs @@ -17,12 +17,19 @@ public Variable(int index, string name) public string Name { get; } } + public struct PdbExtraTypeInfo + { + public string[] TupleElementNames; + public bool[] DynamicFlags; + } + public interface IDebugInfoProvider { string Description { get; } IList GetSequencePoints(MethodDefinitionHandle method); IList GetVariables(MethodDefinitionHandle method); bool TryGetName(MethodDefinitionHandle method, int index, out string name); + bool TryGetExtraTypeInfo(MethodDefinitionHandle method, int index, out PdbExtraTypeInfo extraTypeInfo); string SourceFileName { get; } } } diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index 0e0026ea87..3779ace159 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -26,10 +26,8 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; -using System.Runtime; using System.Security.Cryptography; using System.Text; -using System.Threading; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; @@ -49,7 +47,7 @@ public class PortablePdbWriter public static bool HasCodeViewDebugDirectoryEntry(PEFile file) { - return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); + return file != null && file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); } private static bool IncludeTypeWhenGeneratingPdb(PEFile module, TypeDefinitionHandle type, DecompilerSettings settings) diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs index ef3ba7d170..b32563526d 100644 --- a/ICSharpCode.Decompiler/DecompilerException.cs +++ b/ICSharpCode.Decompiler/DecompilerException.cs @@ -42,18 +42,18 @@ public class DecompilerException : Exception, ISerializable public IEntity DecompiledEntity { get; } public IModule Module { get; } - public PEFile File { get; } + public MetadataFile File { get; } public DecompilerException(MetadataModule module, IEntity decompiledEntity, Exception innerException, string message = null) : base(message ?? GetDefaultMessage(decompiledEntity), innerException) { - this.File = module.PEFile; + this.File = module.MetadataFile; this.Module = module; this.DecompiledEntity = decompiledEntity; } - public DecompilerException(PEFile file, string message, Exception innerException) + public DecompilerException(MetadataFile file, string message, Exception innerException) : base(message, innerException) { this.File = file; diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index e0da5f5ceb..1032093b39 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -1959,6 +1959,21 @@ public bool ApplyWindowsRuntimeProjections { } } + bool autoLoadAssemblyReferences = true; + + [Category("DecompilerSettings.Other")] + [Description("DecompilerSettings.AutoLoadAssemblyReferences")] + public bool AutoLoadAssemblyReferences { + get { return autoLoadAssemblyReferences; } + set { + if (autoLoadAssemblyReferences != value) + { + autoLoadAssemblyReferences = value; + OnPropertyChanged(); + } + } + } + #endregion bool forStatement = true; diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 89adb046b9..a1d4cc7436 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Text; @@ -26,8 +25,6 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; -using SRM = System.Reflection.Metadata; - namespace ICSharpCode.Decompiler.Disassembler { public enum ILNameSyntax @@ -72,7 +69,7 @@ public static void WriteOffsetReference(ITextOutput writer, int? offset) writer.WriteLocalReference(OffsetToString(offset.Value), offset); } - public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, MetadataGenericContext context, ITextOutput writer) + public static void WriteTo(this ExceptionRegion exceptionHandler, MetadataFile module, MetadataGenericContext context, ITextOutput writer) { writer.Write(".try "); WriteOffsetReference(writer, exceptionHandler.TryOffset); diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs index 5e09284500..9cfb95fae1 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs @@ -27,11 +27,11 @@ namespace ICSharpCode.Decompiler.Disassembler { public class DisassemblerSignatureTypeProvider : ISignatureTypeProvider, MetadataGenericContext> { - readonly PEFile module; + readonly MetadataFile module; readonly MetadataReader metadata; readonly ITextOutput output; - public DisassemblerSignatureTypeProvider(PEFile module, ITextOutput output) + public DisassemblerSignatureTypeProvider(MetadataFile module, ITextOutput output) { this.module = module ?? throw new ArgumentNullException(nameof(module)); this.output = output ?? throw new ArgumentNullException(nameof(output)); diff --git a/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs b/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs index 5d94500d1d..e275dc22ce 100644 --- a/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs +++ b/ICSharpCode.Decompiler/Disassembler/IEntityProcessor.cs @@ -27,18 +27,18 @@ namespace ICSharpCode.Decompiler.Disassembler { public interface IEntityProcessor { - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); - IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items); + IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items); } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 77c79137ac..f73b317637 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -58,7 +58,7 @@ public enum ILStructureType /// public class ILStructure { - public readonly PEFile Module; + public readonly MetadataFile Module; public readonly MethodDefinitionHandle MethodHandle; public readonly MetadataGenericContext GenericContext; public readonly ILStructureType Type; @@ -88,7 +88,7 @@ public class ILStructure /// public readonly List Children = new List(); - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, MethodBodyBlock body) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, MethodBodyBlock body) : this(module, handle, genericContext, ILStructureType.Root, 0, body.GetILReader().Length) { // Build the tree of exception structures: @@ -142,7 +142,7 @@ public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGeneric SortChildren(); } - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default) { Debug.Assert(startOffset < endOffset); this.Module = module; @@ -154,7 +154,7 @@ public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGeneric this.ExceptionHandler = handler; } - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint) { Debug.Assert(startOffset < endOffset); this.Module = module; diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index d0ba6a4992..c611792113 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -72,7 +72,7 @@ public class MethodBodyDisassembler int nextSequencePointIndex; // cache info - PEFile module; + MetadataFile module; MetadataReader metadata; MetadataGenericContext genericContext; DisassemblerSignatureTypeProvider signatureDecoder; @@ -83,7 +83,7 @@ public MethodBodyDisassembler(ITextOutput output, CancellationToken cancellation this.cancellationToken = cancellationToken; } - public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle) + public virtual void Disassemble(MetadataFile module, MethodDefinitionHandle handle) { this.module = module ?? throw new ArgumentNullException(nameof(module)); metadata = module.Metadata; @@ -105,8 +105,8 @@ public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle) BlobReader bodyBlockReader; try { - body = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); - bodyBlockReader = module.Reader.GetSectionData(methodDefinition.RelativeVirtualAddress).GetReader(); + body = module.GetMethodBody(methodDefinition.RelativeVirtualAddress); + bodyBlockReader = module.GetSectionData(methodDefinition.RelativeVirtualAddress).GetReader(); } catch (BadImageFormatException ex) { @@ -119,7 +119,7 @@ public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle) output.WriteLine("// Code size: {0} (0x{0:x})", blob.Length); output.WriteLine(".maxstack {0}", body.MaxStack); - var entrypointHandle = MetadataTokens.MethodDefinitionHandle(module.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); + var entrypointHandle = MetadataTokens.MethodDefinitionHandle(module.CorHeader?.EntryPointTokenOrRelativeVirtualAddress ?? 0); if (handle == entrypointHandle) output.WriteLine(".entrypoint"); @@ -141,7 +141,7 @@ public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle) while (blob.RemainingBytes > 0) { cancellationToken.ThrowIfCancellationRequested(); - WriteInstruction(output, metadata, handle, ref blob, methodDefinition.RelativeVirtualAddress); + WriteInstruction(output, module, handle, ref blob, methodDefinition.RelativeVirtualAddress); } WriteExceptionHandlers(module, handle, body); } @@ -195,7 +195,7 @@ void DisassembleLocalsBlock(MethodDefinitionHandle method, MethodBodyBlock body) output.WriteLine(")"); } - internal void WriteExceptionHandlers(PEFile module, MethodDefinitionHandle handle, MethodBodyBlock body) + internal void WriteExceptionHandlers(MetadataFile module, MethodDefinitionHandle handle, MethodBodyBlock body) { this.module = module; metadata = module.Metadata; @@ -291,7 +291,7 @@ void WriteStructureBody(ILStructure s, BitSet branchTargets, ref BlobReader body } var currentOpCode = ILParser.DecodeOpCode(ref body); body.Offset = offset; // reset IL stream - WriteInstruction(output, metadata, s.MethodHandle, ref body, methodRva); + WriteInstruction(output, module, s.MethodHandle, ref body, methodRva); prevInstructionWasBranch = currentOpCode.IsBranch() || currentOpCode.IsReturn() || currentOpCode == ILOpCode.Throw @@ -324,8 +324,9 @@ void WriteStructureFooter(ILStructure s) } } - protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) + protected virtual void WriteInstruction(ITextOutput output, MetadataFile metadataFile, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) { + var metadata = metadataFile.Metadata; int offset = blob.Offset; if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index b268ff3014..11c8bdb9a0 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -143,7 +143,7 @@ public ReflectionDisassembler(ITextOutput output, MethodBodyDisassembler methodB { MethodImplAttributes.AggressiveInlining, "aggressiveinlining" }, }; - public void DisassembleMethod(PEFile module, MethodDefinitionHandle handle) + public void DisassembleMethod(MetadataFile module, MethodDefinitionHandle handle) { var genericContext = new MetadataGenericContext(handle, module); // write method header @@ -153,7 +153,7 @@ public void DisassembleMethod(PEFile module, MethodDefinitionHandle handle) DisassembleMethodBlock(module, handle, genericContext); } - public void DisassembleMethodHeader(PEFile module, MethodDefinitionHandle handle) + public void DisassembleMethodHeader(MetadataFile module, MethodDefinitionHandle handle) { var genericContext = new MetadataGenericContext(handle, module); // write method header @@ -162,7 +162,7 @@ public void DisassembleMethodHeader(PEFile module, MethodDefinitionHandle handle DisassembleMethodHeaderInternal(module, handle, genericContext); } - void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) + void DisassembleMethodHeaderInternal(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) { var metadata = module.Metadata; @@ -310,7 +310,7 @@ void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handl output.Unindent(); } - internal static void WriteMetadataToken(ITextOutput output, PEFile module, Handle? handle, + internal static void WriteMetadataToken(ITextOutput output, MetadataFile module, Handle? handle, int metadataToken, bool spaceAfter, bool spaceBefore, bool showMetadataTokens, bool base10) { // handle can be null in case of errors, if that's the case, we always want to print a comment, @@ -344,7 +344,7 @@ internal static void WriteMetadataToken(ITextOutput output, PEFile module, Handl } } - void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, + void DisassembleMethodBlock(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) { var metadata = module.Metadata; @@ -362,7 +362,7 @@ void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, foreach (var p in methodDefinition.GetGenericParameters()) { - WriteGenericParameterAttributes(module, genericContext, p); + WriteGenericParametersAndAttributes(module, genericContext, p); } foreach (var p in methodDefinition.GetParameters()) { @@ -380,7 +380,7 @@ void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, } #region Write Security Declarations - void WriteSecurityDeclarations(PEFile module, DeclarativeSecurityAttributeHandleCollection secDeclProvider) + void WriteSecurityDeclarations(MetadataFile module, DeclarativeSecurityAttributeHandleCollection secDeclProvider) { if (secDeclProvider.Count == 0) return; @@ -479,9 +479,9 @@ class SecurityDeclarationDecoder : ICustomAttributeTypeProvider<(PrimitiveTypeCo { readonly ITextOutput output; readonly IAssemblyResolver resolver; - readonly PEFile module; + readonly MetadataFile module; - public SecurityDeclarationDecoder(ITextOutput output, IAssemblyResolver resolver, PEFile module) + public SecurityDeclarationDecoder(ITextOutput output, IAssemblyResolver resolver, MetadataFile module) { this.output = output; this.resolver = resolver; @@ -535,11 +535,11 @@ public bool IsSystemType((PrimitiveTypeCode, string) type) return "type" == type.Item2; } - (PEFile, TypeDefinitionHandle) ResolveType(string typeName, PEFile module) + (MetadataFile, TypeDefinitionHandle) ResolveType(string typeName, MetadataFile module) { string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None); string[] typeNameParts = nameParts[0].Split('.'); - PEFile containingModule = null; + MetadataFile containingModule = null; TypeDefinitionHandle typeDefHandle = default; // if we deal with an assembly-qualified name, resolve the assembly if (nameParts.Length == 2) @@ -564,7 +564,7 @@ public bool IsSystemType((PrimitiveTypeCode, string) type) return (containingModule, typeDefHandle); - TypeDefinitionHandle FindType(PEFile currentModule, string[] name) + TypeDefinitionHandle FindType(MetadataFile currentModule, string[] name) { var metadata = currentModule.Metadata; var currentNamespace = metadata.GetNamespaceDefinitionRoot(); @@ -618,9 +618,9 @@ PrimitiveTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module) return typeCode; } - PEFile mscorlib; + MetadataFile mscorlib; - bool TryResolveMscorlib(out PEFile mscorlib) + bool TryResolveMscorlib(out MetadataFile mscorlib) { mscorlib = null; if (this.mscorlib != null) @@ -637,7 +637,7 @@ bool TryResolveMscorlib(out PEFile mscorlib) } } - void TryDecodeSecurityDeclaration(TextOutputWithRollback output, BlobReader blob, PEFile module) + void TryDecodeSecurityDeclaration(TextOutputWithRollback output, BlobReader blob, MetadataFile module) { output.WriteLine(" = {"); output.Indent(); @@ -1134,7 +1134,7 @@ void WriteParameters(MetadataReader metadata, IEnumerable param output.WriteLine(); } - void WriteGenericParameterAttributes(PEFile module, MetadataGenericContext context, GenericParameterHandle handle) + void WriteGenericParametersAndAttributes(MetadataFile module, MetadataGenericContext context, GenericParameterHandle handle) { var metadata = module.Metadata; var p = metadata.GetGenericParameter(handle); @@ -1161,7 +1161,7 @@ void WriteGenericParameterAttributes(PEFile module, MetadataGenericContext conte } } - void WriteParameterAttributes(PEFile module, ParameterHandle handle) + void WriteParameterAttributes(MetadataFile module, ParameterHandle handle) { var metadata = module.Metadata; var p = metadata.GetParameter(handle); @@ -1247,7 +1247,7 @@ void WriteConstant(MetadataReader metadata, Constant constant) { FieldAttributes.NotSerialized, "notserialized" }, }; - public void DisassembleField(PEFile module, FieldDefinitionHandle handle) + public void DisassembleField(MetadataFile module, FieldDefinitionHandle handle) { var metadata = module.Metadata; var fieldDefinition = metadata.GetFieldDefinition(handle); @@ -1264,7 +1264,7 @@ public void DisassembleField(PEFile module, FieldDefinitionHandle handle) { // Field data as specified in II.16.3.1 of ECMA-335 6th edition int rva = fieldDefinition.GetRelativeVirtualAddress(); - int sectionIndex = module.Reader.PEHeaders.GetContainingSectionIndex(rva); + int sectionIndex = module.GetContainingSectionIndex(rva); if (sectionIndex < 0) { output.WriteLine($"// RVA {rva:X8} invalid (not in any section)"); @@ -1274,7 +1274,7 @@ public void DisassembleField(PEFile module, FieldDefinitionHandle handle) BlobReader initVal; try { - initVal = fieldDefinition.GetInitialValue(module.Reader, null); + initVal = fieldDefinition.GetInitialValue(module, null); } catch (BadImageFormatException ex) { @@ -1283,7 +1283,7 @@ public void DisassembleField(PEFile module, FieldDefinitionHandle handle) } if (initVal.Length > 0) { - var sectionHeader = module.Reader.PEHeaders.SectionHeaders[sectionIndex]; + var sectionHeader = module.SectionHeaders[sectionIndex]; output.Write(".data "); if (sectionHeader.Name == ".text") { @@ -1293,7 +1293,7 @@ public void DisassembleField(PEFile module, FieldDefinitionHandle handle) { output.Write("tls "); } - else if (sectionHeader.Name != ".data") + else if (sectionHeader.Name is not (null or ".data")) { output.Write($"/* {sectionHeader.Name} */ "); } @@ -1305,14 +1305,14 @@ public void DisassembleField(PEFile module, FieldDefinitionHandle handle) } } - public void DisassembleFieldHeader(PEFile module, FieldDefinitionHandle handle) + public void DisassembleFieldHeader(MetadataFile module, FieldDefinitionHandle handle) { var metadata = module.Metadata; var fieldDefinition = metadata.GetFieldDefinition(handle); DisassembleFieldHeaderInternal(module, handle, metadata, fieldDefinition); } - private char DisassembleFieldHeaderInternal(PEFile module, FieldDefinitionHandle handle, MetadataReader metadata, FieldDefinition fieldDefinition) + private char DisassembleFieldHeaderInternal(MetadataFile module, FieldDefinitionHandle handle, MetadataReader metadata, FieldDefinition fieldDefinition) { output.WriteReference(module, handle, ".field", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1342,7 +1342,7 @@ private char DisassembleFieldHeaderInternal(PEFile module, FieldDefinitionHandle if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) { int rva = fieldDefinition.GetRelativeVirtualAddress(); - sectionPrefix = GetRVASectionPrefix(module.Reader.PEHeaders, rva); + sectionPrefix = GetRVASectionPrefix(module, rva); output.Write(" at {1}_{0:X8}", rva, sectionPrefix); } @@ -1356,12 +1356,14 @@ private char DisassembleFieldHeaderInternal(PEFile module, FieldDefinitionHandle return sectionPrefix; } - char GetRVASectionPrefix(System.Reflection.PortableExecutable.PEHeaders headers, int rva) + char GetRVASectionPrefix(MetadataFile module, int rva) { - int sectionIndex = headers.GetContainingSectionIndex(rva); + if (module is not PEFile peFile) + throw new NotSupportedException("Cannot get RVA section prefix from module"); + int sectionIndex = peFile.Reader.PEHeaders.GetContainingSectionIndex(rva); if (sectionIndex < 0) return 'D'; - var sectionHeader = headers.SectionHeaders[sectionIndex]; + var sectionHeader = peFile.Reader.PEHeaders.SectionHeaders[sectionIndex]; switch (sectionHeader.Name) { case ".tls": @@ -1381,7 +1383,7 @@ char GetRVASectionPrefix(System.Reflection.PortableExecutable.PEHeaders headers, { PropertyAttributes.HasDefault, "hasdefault" }, }; - public void DisassembleProperty(PEFile module, PropertyDefinitionHandle property) + public void DisassembleProperty(MetadataFile module, PropertyDefinitionHandle property) { var metadata = module.Metadata; var propertyDefinition = metadata.GetPropertyDefinition(property); @@ -1398,14 +1400,14 @@ public void DisassembleProperty(PEFile module, PropertyDefinitionHandle property CloseBlock(); } - public void DisassemblePropertyHeader(PEFile module, PropertyDefinitionHandle property) + public void DisassemblePropertyHeader(MetadataFile module, PropertyDefinitionHandle property) { var metadata = module.Metadata; var propertyDefinition = metadata.GetPropertyDefinition(property); DisassemblePropertyHeaderInternal(module, property, metadata, propertyDefinition); } - private PropertyAccessors DisassemblePropertyHeaderInternal(PEFile module, PropertyDefinitionHandle handle, MetadataReader metadata, PropertyDefinition propertyDefinition) + private PropertyAccessors DisassemblePropertyHeaderInternal(MetadataFile module, PropertyDefinitionHandle handle, MetadataReader metadata, PropertyDefinition propertyDefinition) { output.WriteReference(module, handle, ".property", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1436,7 +1438,7 @@ private PropertyAccessors DisassemblePropertyHeaderInternal(PEFile module, Prope return accessors; } - void WriteNestedMethod(string keyword, PEFile module, MethodDefinitionHandle method) + void WriteNestedMethod(string keyword, MetadataFile module, MethodDefinitionHandle method) { if (method.IsNil) return; @@ -1454,7 +1456,7 @@ void WriteNestedMethod(string keyword, PEFile module, MethodDefinitionHandle met { EventAttributes.RTSpecialName, "rtspecialname" }, }; - public void DisassembleEvent(PEFile module, EventDefinitionHandle handle) + public void DisassembleEvent(MetadataFile module, EventDefinitionHandle handle) { var eventDefinition = module.Metadata.GetEventDefinition(handle); var accessors = eventDefinition.GetAccessors(); @@ -1471,14 +1473,14 @@ public void DisassembleEvent(PEFile module, EventDefinitionHandle handle) CloseBlock(); } - public void DisassembleEventHeader(PEFile module, EventDefinitionHandle handle) + public void DisassembleEventHeader(MetadataFile module, EventDefinitionHandle handle) { var eventDefinition = module.Metadata.GetEventDefinition(handle); var accessors = eventDefinition.GetAccessors(); DisassembleEventHeaderInternal(module, handle, eventDefinition, accessors); } - private void DisassembleEventHeaderInternal(PEFile module, EventDefinitionHandle handle, EventDefinition eventDefinition, EventAccessors accessors) + private void DisassembleEventHeaderInternal(MetadataFile module, EventDefinitionHandle handle, EventDefinition eventDefinition, EventAccessors accessors) { TypeDefinitionHandle declaringType; if (!accessors.Adder.IsNil) @@ -1555,7 +1557,7 @@ private void DisassembleEventHeaderInternal(PEFile module, EventDefinitionHandle { TypeAttributes.HasSecurity, null }, }; - public void DisassembleType(PEFile module, TypeDefinitionHandle type) + public void DisassembleType(MetadataFile module, TypeDefinitionHandle type) { var typeDefinition = module.Metadata.GetTypeDefinition(type); MetadataGenericContext genericContext = new MetadataGenericContext(type, module); @@ -1591,7 +1593,7 @@ public void DisassembleType(PEFile module, TypeDefinitionHandle type) WriteSecurityDeclarations(module, typeDefinition.GetDeclarativeSecurityAttributes()); foreach (var tp in typeDefinition.GetGenericParameters()) { - WriteGenericParameterAttributes(module, genericContext, tp); + WriteGenericParametersAndAttributes(module, genericContext, tp); } var layout = typeDefinition.GetLayout(); if (!layout.IsDefault) @@ -1609,7 +1611,9 @@ public void DisassembleType(PEFile module, TypeDefinitionHandle type) output.Write(".interfaceimpl type "); iface.Interface.WriteTo(module, output, genericContext, ILNameSyntax.TypeName); output.WriteLine(); + output.Indent(); WriteAttributes(module, customAttributes); + output.Unindent(); output.WriteLine(); } } @@ -1674,14 +1678,14 @@ public void DisassembleType(PEFile module, TypeDefinitionHandle type) isInType = oldIsInType; } - public void DisassembleTypeHeader(PEFile module, TypeDefinitionHandle type) + public void DisassembleTypeHeader(MetadataFile module, TypeDefinitionHandle type) { var typeDefinition = module.Metadata.GetTypeDefinition(type); MetadataGenericContext genericContext = new MetadataGenericContext(type, module); DisassembleTypeHeaderInternal(module, type, typeDefinition, genericContext); } - private void DisassembleTypeHeaderInternal(PEFile module, TypeDefinitionHandle handle, TypeDefinition typeDefinition, MetadataGenericContext genericContext) + private void DisassembleTypeHeaderInternal(MetadataFile module, TypeDefinitionHandle handle, TypeDefinition typeDefinition, MetadataGenericContext genericContext) { output.WriteReference(module, handle, ".class", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1710,7 +1714,7 @@ private void DisassembleTypeHeaderInternal(PEFile module, TypeDefinitionHandle h } } - void WriteTypeParameters(ITextOutput output, PEFile module, MetadataGenericContext context, GenericParameterHandleCollection p) + void WriteTypeParameters(ITextOutput output, MetadataFile module, MetadataGenericContext context, GenericParameterHandleCollection p) { if (p.Count > 0) { @@ -1763,37 +1767,37 @@ void WriteTypeParameters(ITextOutput output, PEFile module, MetadataGenericConte #region Processing - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } @@ -1802,12 +1806,14 @@ private IReadOnlyCollection Process(PEFile module, IReadO #region Helper methods - void WriteAttributes(PEFile module, CustomAttributeHandleCollection attributes) + void WriteAttributes(MetadataFile module, CustomAttributeHandleCollection attributes) { var metadata = module.Metadata; foreach (CustomAttributeHandle a in Process(module, attributes)) { output.Write(".custom "); + WriteMetadataToken(output, module, a, MetadataTokens.GetToken(a), + spaceAfter: true, spaceBefore: false, ShowMetadataTokens, ShowMetadataTokensInBase10); var attr = metadata.GetCustomAttribute(a); attr.Constructor.WriteTo(module, output, default); if (!attr.Value.IsNil) @@ -1927,7 +1933,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() } #endregion - public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable types) + public void DisassembleNamespace(string nameSpace, MetadataFile module, IEnumerable types) { if (!string.IsNullOrEmpty(nameSpace)) { @@ -1949,7 +1955,7 @@ public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - public IReadOnlyCollection Process(PEFile module, + public IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return items.OrderBy(item => GetSortKey(item, module)).ToArray(); } - private static string GetSortKey(TypeDefinitionHandle handle, PEFile module) => + private static string GetSortKey(TypeDefinitionHandle handle, MetadataFile module) => handle.GetFullTypeName(module.Metadata).ToILNameString(); - private static string GetSortKey(MethodDefinitionHandle handle, PEFile module) + private static string GetSortKey(MethodDefinitionHandle handle, MetadataFile module) { PlainTextOutput output = new PlainTextOutput(); MethodDefinition definition = module.Metadata.GetMethodDefinition(handle); @@ -97,22 +97,22 @@ private static string GetSortKey(MethodDefinitionHandle handle, PEFile module) return output.ToString(); } - private static string GetSortKey(InterfaceImplementationHandle handle, PEFile module) => + private static string GetSortKey(InterfaceImplementationHandle handle, MetadataFile module) => module.Metadata.GetInterfaceImplementation(handle) .Interface .GetFullTypeName(module.Metadata) .ToILNameString(); - private static string GetSortKey(FieldDefinitionHandle handle, PEFile module) => + private static string GetSortKey(FieldDefinitionHandle handle, MetadataFile module) => module.Metadata.GetString(module.Metadata.GetFieldDefinition(handle).Name); - private static string GetSortKey(PropertyDefinitionHandle handle, PEFile module) => + private static string GetSortKey(PropertyDefinitionHandle handle, MetadataFile module) => module.Metadata.GetString(module.Metadata.GetPropertyDefinition(handle).Name); - private static string GetSortKey(EventDefinitionHandle handle, PEFile module) => + private static string GetSortKey(EventDefinitionHandle handle, MetadataFile module) => module.Metadata.GetString(module.Metadata.GetEventDefinition(handle).Name); - private static string GetSortKey(CustomAttributeHandle handle, PEFile module) => + private static string GetSortKey(CustomAttributeHandle handle, MetadataFile module) => module.Metadata.GetCustomAttribute(handle) .Constructor .GetDeclaringType(module.Metadata) diff --git a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs index ce8cc84f53..754fe1f9a7 100644 --- a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs +++ b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs @@ -79,7 +79,7 @@ public IType Resolve(ITypeResolveContext context) /// /// Either TypeDefinitionHandle, if the type is defined in the module or ExportedTypeHandle, /// if the module contains a type forwarder. Returns a nil handle, if the type was not found. - public EntityHandle ResolveInPEFile(PEFile module) + public EntityHandle ResolveInPEFile(MetadataFile module) { string[] parts = typeName.Split('.'); for (int i = parts.Length - 1; i >= 0; i--) diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs index 690eca6895..ba2b1d95b9 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation public static class XmlDocLoader { static readonly Lazy mscorlibDocumentation = new Lazy(LoadMscorlibDocumentation); - static readonly ConditionalWeakTable cache = new ConditionalWeakTable(); + static readonly ConditionalWeakTable cache = new(); static XmlDocumentationProvider LoadMscorlibDocumentation() { @@ -48,7 +48,7 @@ public static XmlDocumentationProvider MscorlibDocumentation { get { return mscorlibDocumentation.Value; } } - public static XmlDocumentationProvider LoadDocumentation(PEFile module) + public static XmlDocumentationProvider LoadDocumentation(MetadataFile module) { if (module == null) throw new ArgumentNullException(nameof(module)); diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index a742391f72..7fe6df907a 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -69,12 +69,14 @@ - + + false + - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -84,7 +86,7 @@ - + @@ -95,6 +97,9 @@ + + + @@ -142,6 +147,7 @@ + @@ -359,6 +365,9 @@ + + + diff --git a/ICSharpCode.Decompiler/IL/ApplyPdbLocalTypeInfoTypeVisitor.cs b/ICSharpCode.Decompiler/IL/ApplyPdbLocalTypeInfoTypeVisitor.cs new file mode 100644 index 0000000000..1d8796c1e7 --- /dev/null +++ b/ICSharpCode.Decompiler/IL/ApplyPdbLocalTypeInfoTypeVisitor.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Immutable; + +using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; + +namespace ICSharpCode.Decompiler.IL +{ + /// + /// Heavily based on + /// + sealed class ApplyPdbLocalTypeInfoTypeVisitor : TypeVisitor + { + private readonly bool[] dynamicData; + private readonly string[] tupleElementNames; + private int dynamicTypeIndex = 0; + private int tupleTypeIndex = 0; + + private ApplyPdbLocalTypeInfoTypeVisitor(bool[] dynamicData, string[] tupleElementNames) + { + this.dynamicData = dynamicData; + this.tupleElementNames = tupleElementNames; + } + + public static IType Apply(IType type, PdbExtraTypeInfo pdbExtraTypeInfo) + { + if (pdbExtraTypeInfo.DynamicFlags is null && pdbExtraTypeInfo.TupleElementNames is null) + return type; + return type.AcceptVisitor(new ApplyPdbLocalTypeInfoTypeVisitor(pdbExtraTypeInfo.DynamicFlags, pdbExtraTypeInfo.TupleElementNames)); + } + + public override IType VisitModOpt(ModifiedType type) + { + dynamicTypeIndex++; + return base.VisitModOpt(type); + } + + public override IType VisitModReq(ModifiedType type) + { + dynamicTypeIndex++; + return base.VisitModReq(type); + } + + public override IType VisitPointerType(PointerType type) + { + dynamicTypeIndex++; + return base.VisitPointerType(type); + } + + public override IType VisitArrayType(ArrayType type) + { + dynamicTypeIndex++; + return base.VisitArrayType(type); + } + + public override IType VisitByReferenceType(ByReferenceType type) + { + dynamicTypeIndex++; + return base.VisitByReferenceType(type); + } + + public override IType VisitTupleType(TupleType type) + { + if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) + { + int tupleCardinality = type.Cardinality; + string[] extractedValues = new string[tupleCardinality]; + Array.Copy(tupleElementNames, tupleTypeIndex, extractedValues, 0, + Math.Min(tupleCardinality, tupleElementNames.Length - tupleTypeIndex)); + var elementNames = ImmutableArray.CreateRange(extractedValues); + tupleTypeIndex += tupleCardinality; + + int level = 0; + var elementTypes = new IType[type.ElementTypes.Length]; + for (int i = 0; i < type.ElementTypes.Length; i++) + { + dynamicTypeIndex++; + IType elementType = type.ElementTypes[i]; + if (i != 0 && (i - level) % TupleType.RestPosition == 0 && elementType is TupleType tuple) + { + tupleTypeIndex += tuple.Cardinality; + level++; + } + elementTypes[i] = elementType.AcceptVisitor(this); + } + + return new TupleType( + type.Compilation, + elementTypes.ToImmutableArray(), + elementNames, + type.GetDefinition()?.ParentModule + ); + } + return base.VisitTupleType(type); + } + + public override IType VisitParameterizedType(ParameterizedType type) + { + if (TupleType.IsTupleCompatible(type, out var tupleCardinality)) + tupleTypeIndex += tupleCardinality; + // Visit generic type and type arguments. + // Like base implementation, except that it increments dynamicTypeIndex. + var genericType = type.GenericType.AcceptVisitor(this); + bool changed = type.GenericType != genericType; + var arguments = new IType[type.TypeArguments.Count]; + for (int i = 0; i < type.TypeArguments.Count; i++) + { + dynamicTypeIndex++; + arguments[i] = type.TypeArguments[i].AcceptVisitor(this); + changed = changed || arguments[i] != type.TypeArguments[i]; + } + if (!changed) + return type; + return new ParameterizedType(genericType, arguments); + } + + public override IType VisitFunctionPointerType(FunctionPointerType type) + { + dynamicTypeIndex++; + if (type.ReturnIsRefReadOnly) + { + dynamicTypeIndex++; + } + var returnType = type.ReturnType.AcceptVisitor(this); + bool changed = type.ReturnType != returnType; + var parameters = new IType[type.ParameterTypes.Length]; + for (int i = 0; i < parameters.Length; i++) + { + dynamicTypeIndex += type.ParameterReferenceKinds[i] switch { + ReferenceKind.None => 1, + ReferenceKind.Ref => 1, + ReferenceKind.Out => 2, // in/out also count the modreq + ReferenceKind.In => 2, + _ => throw new NotSupportedException() + }; + parameters[i] = type.ParameterTypes[i].AcceptVisitor(this); + changed = changed || parameters[i] != type.ParameterTypes[i]; + } + if (!changed) + return type; + return type.WithSignature(returnType, parameters.ToImmutableArray()); + } + + public override IType VisitTypeDefinition(ITypeDefinition type) + { + IType newType = type; + var ktc = type.KnownTypeCode; + if (ktc == KnownTypeCode.Object && dynamicData is not null) + { + if (dynamicTypeIndex >= dynamicData.Length) + newType = SpecialType.Dynamic; + else if (dynamicData[dynamicTypeIndex]) + newType = SpecialType.Dynamic; + } + return newType; + } + } +} diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 377f9a24dd..259367b2d4 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -26,8 +26,8 @@ using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -53,11 +53,11 @@ internal static bool IsCompilerGeneratedStateMachine(TypeDefinitionHandle type, return false; } - internal static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, MethodDefinitionHandle method) + internal static bool IsCompilerGeneratedMainMethod(MetadataFile module, MethodDefinitionHandle method) { var metadata = module.Metadata; var definition = metadata.GetMethodDefinition(method); - var entrypoint = System.Reflection.Metadata.Ecma335.MetadataTokens.MethodDefinitionHandle(module.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); + var entrypoint = System.Reflection.Metadata.Ecma335.MetadataTokens.MethodDefinitionHandle(module.CorHeader?.EntryPointTokenOrRelativeVirtualAddress ?? 0); return method == entrypoint && metadata.GetString(definition.Name).Equals("
", StringComparison.Ordinal); } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index ba698e97e2..3475d4d610 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.InteropServices.ComTypes; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -612,18 +613,16 @@ bool CreatePinnedRegion(Block block, StLoc stLoc) innerBlock = (Block)innerBlock.Clone(); clonedBlocks[i] = innerBlock; } - Branch br = innerBlock.Instructions.LastOrDefault() as Branch; - if (br != null && br.TargetBlock.IncomingEdgeCount == 1 - && br.TargetContainer == sourceContainer && reachedEdgesPerBlock[br.TargetBlock.ChildIndex] == 0) + if (innerBlock.MatchIfAtEndOfBlock(out _, out var trueInst, out var falseInst)) { - // branch that leaves body. - // The target block should have an instruction that resets the pin; delete that instruction: - StLoc unpin = br.TargetBlock.Instructions.First() as StLoc; - if (unpin != null && unpin.Variable == stLoc.Variable && IsNullOrZero(unpin.Value)) - { - br.TargetBlock.Instructions.RemoveAt(0); - } + HandleBranchLeavingPinnedRegion(trueInst, reachedEdgesPerBlock, sourceContainer, stLoc.Variable); + HandleBranchLeavingPinnedRegion(falseInst, reachedEdgesPerBlock, sourceContainer, stLoc.Variable); + } + else + { + HandleBranchLeavingPinnedRegion(innerBlock.Instructions.LastOrDefault(), reachedEdgesPerBlock, sourceContainer, stLoc.Variable); } + // move block into body if (sourceContainer.Blocks[i] == entryBlock) { @@ -698,6 +697,21 @@ bool CreatePinnedRegion(Block block, StLoc stLoc) return true; } + static void HandleBranchLeavingPinnedRegion(ILInstruction potentialBranch, int[] reachedEdgesPerBlock, BlockContainer sourceContainer, ILVariable pinnedRegionVar) + { + if (potentialBranch is Branch branch && branch.TargetBlock.IncomingEdgeCount == 1 + && branch.TargetContainer == sourceContainer && reachedEdgesPerBlock[branch.TargetBlock.ChildIndex] == 0) + { + // branch that leaves body. + // The target block should have an instruction that resets the pin; delete that instruction: + StLoc unpin = branch.TargetBlock.Instructions.First() as StLoc; + if (unpin != null && unpin.Variable == pinnedRegionVar && IsNullOrZero(unpin.Value)) + { + branch.TargetBlock.Instructions.RemoveAt(0); + } + } + } + static bool IsNullOrZero(ILInstruction inst) { while (inst is Conv conv) @@ -750,6 +764,13 @@ void ProcessPinnedRegion(PinnedRegion pinnedRegion) // fixing a string HandleStringToPointer(pinnedRegion); } + else if (pinnedRegion.Init is Conv { Kind: ConversionKind.StopGCTracking, Argument: var convArg }) + { + // If pinnedRegion.Variable was already a pointer type, the input IL has a StopGCTracking conversion. + // We can simply remove this conversion, as it is not needed. + context.Step("Remove StopGCTracking conversion", pinnedRegion); + pinnedRegion.Init = convArg; + } // Detect nested pinned regions: BlockContainer body = (BlockContainer)pinnedRegion.Body; foreach (var block in body.Blocks) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index 3fb1734daa..dc6bd309c9 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -16,12 +16,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -361,7 +359,7 @@ private bool UseCSharpSwitch(out KeyValuePair defaultSec private bool MatchRoslynSwitchOnString() { var insns = analysis.RootBlock.Instructions; - return insns.Count >= 3 && SwitchOnStringTransform.MatchComputeStringHashCall(insns[insns.Count - 3], analysis.SwitchVariable, out var switchLdLoc); + return insns.Count >= 3 && SwitchOnStringTransform.MatchComputeStringOrReadOnlySpanHashCall(insns[insns.Count - 3], analysis.SwitchVariable, out _); } /// diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index 8c60690a68..dbea7d4cfe 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -496,7 +496,7 @@ internal static ILFunction CreateILAst(MethodDefinitionHandle method, ILTransfor classTypeParameters: (genericContext.ClassTypeParameters ?? EmptyList.Instance) .Concat(genericContext.MethodTypeParameters ?? EmptyList.Instance).ToArray(), methodTypeParameters: null); - var body = context.TypeSystem.MainModule.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = context.TypeSystem.MainModule.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); var il = context.CreateILReader() .ReadIL(method, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken); il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true), @@ -1438,7 +1438,7 @@ bool IsCallToMonoFinallyMethod(Call call, out IMethod finallyMethod) ITypeDefinition declaringTypeDefinition = call.Method.DeclaringTypeDefinition; if (declaringTypeDefinition.MetadataToken != this.enumeratorType) return false; - if (declaringTypeDefinition.ParentModule.PEFile.Metadata != metadata) + if (declaringTypeDefinition.ParentModule.MetadataFile.Metadata != metadata) return false; finallyMethod = call.Method; return !call.Method.MetadataToken.IsNil; diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 5aa7edb742..21f8e52903 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2014 Daniel Grunwald +// Copyright (c) 2014 Daniel Grunwald // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software @@ -304,6 +304,13 @@ ILVariable CreateILVariable(int index, IType type) { kind = VariableKind.Local; } + + if (UseDebugSymbols && DebugInfo is not null && + DebugInfo.TryGetExtraTypeInfo((MethodDefinitionHandle)method.MetadataToken, index, out var pdbExtraTypeInfo)) + { + type = ApplyPdbLocalTypeInfoTypeVisitor.Apply(type, pdbExtraTypeInfo); + } + ILVariable ilVar = new ILVariable(kind, type, index); if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) { @@ -683,7 +690,7 @@ public void WriteTypedIL(MethodDefinitionHandle method, MethodBodyBlock body, output.WriteLine(); } new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } - .WriteExceptionHandlers(module.PEFile, method, body); + .WriteExceptionHandlers(module.MetadataFile, method, body); } /// diff --git a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs index be5ebcd2d7..6c48fa8bd0 100644 --- a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs +++ b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs @@ -69,7 +69,7 @@ public static void WriteTo(this Interval interval, ITextOutput output, ILAstWrit output.Write($"[{interval.Start:x4}..{interval.InclusiveEnd:x4}] "); } - public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) + public static void WriteTo(this EntityHandle entity, MetadataFile module, ITextOutput output, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) { if (entity.IsNil) { @@ -138,7 +138,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput case HandleKind.FieldDefinition: { var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); - signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext(fd.GetDeclaringType(), module)); + signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext(fd.GetDeclaringType(), metadata)); signature(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); ((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, default, ILNameSyntax.TypeName); @@ -149,7 +149,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput case HandleKind.MethodDefinition: { var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); - methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, module)); + methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, metadata)); methodSignature.Header.WriteTo(output); methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); @@ -198,7 +198,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput if (j > 0) output.Write(", "); var constraint = metadata.GetGenericParameterConstraint(constraints[j]); - constraint.Type.WriteTo(module, output, new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName); + constraint.Type.WriteTo(module, output, new Metadata.MetadataGenericContext((MethodDefinitionHandle)entity, metadata), ILNameSyntax.TypeName); } output.Write(") "); } @@ -227,7 +227,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput methodSignature.Header.WriteTo(output); methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); - WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); + WriteParent(output, module, mr.Parent, genericContext, syntax); output.Write("::"); output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); WriteParameterList(output, methodSignature); @@ -236,7 +236,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); - WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); + WriteParent(output, module, mr.Parent, genericContext, syntax); output.Write("::"); output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); break; @@ -279,7 +279,7 @@ public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput methodSignature.Header.WriteTo(output); methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); - WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax); + WriteParent(output, module, memberReference.Parent, genericContext, syntax); output.Write("::"); output.Write(DisassemblerHelpers.Escape(memberName)); WriteTypeParameterList(output, syntax, substitution); @@ -352,24 +352,24 @@ internal static void WriteTo(this in SignatureHeader header, ITextOutput output) } } - static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax) + static void WriteParent(ITextOutput output, MetadataFile metadataFile, EntityHandle parentHandle, Metadata.MetadataGenericContext genericContext, ILNameSyntax syntax) { switch (parentHandle.Kind) { case HandleKind.MethodDefinition: - var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle); - ((EntityHandle)methodDef.GetDeclaringType()).WriteTo(module, output, genericContext, syntax); + var methodDef = metadataFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle); + ((EntityHandle)methodDef.GetDeclaringType()).WriteTo(metadataFile, output, genericContext, syntax); break; case HandleKind.ModuleReference: output.Write('['); - var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle); - output.Write(metadata.GetString(moduleRef.Name)); + var moduleRef = metadataFile.Metadata.GetModuleReference((ModuleReferenceHandle)parentHandle); + output.Write(metadataFile.Metadata.GetString(moduleRef.Name)); output.Write(']'); break; case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: - parentHandle.WriteTo(module, output, genericContext, syntax); + parentHandle.WriteTo(metadataFile, output, genericContext, syntax); break; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index 2832e9e25a..d84091d9d2 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -240,9 +240,13 @@ void AssignName() } else { - // use the name from the debug symbols - // (but ensure we don't use the same name for two variables) - v.Name = GetAlternativeName(v.Name); + // use the name from the debug symbols and update index appended to duplicates + string nameWithoutNumber = SplitName(v.Name, out int newIndex); + if (!reservedVariableNames.TryGetValue(nameWithoutNumber, out int currentIndex)) + { + currentIndex = 1; + } + reservedVariableNames[nameWithoutNumber] = Math.Max(newIndex, currentIndex); } } } @@ -274,7 +278,21 @@ void AssignName() var newName = localFunction.Name; if (newName == null) { - newName = GetAlternativeName("f"); + string nameWithoutNumber = "f"; + if (!reservedVariableNames.TryGetValue(nameWithoutNumber, out int currentIndex)) + { + currentIndex = 1; + } + int count = Math.Max(1, currentIndex) + 1; + reservedVariableNames[nameWithoutNumber] = count; + if (count > 1) + { + newName = nameWithoutNumber + count.ToString(); + } + else + { + newName = nameWithoutNumber; + } } localFunction.Name = newName; localFunction.ReducedMethod.Name = newName; @@ -342,42 +360,6 @@ internal static bool IsValidName(string varName) return true; } - public string GetAlternativeName(string oldVariableName) - { - if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) - { - for (char c = 'i'; c <= maxLoopVariableName; c++) - { - if (!reservedVariableNames.ContainsKey(c.ToString())) - { - reservedVariableNames.Add(c.ToString(), 1); - return c.ToString(); - } - } - } - - string nameWithoutDigits = SplitName(oldVariableName, out int number); - - if (!reservedVariableNames.ContainsKey(nameWithoutDigits)) - { - reservedVariableNames.Add(nameWithoutDigits, number - 1); - } - int count = ++reservedVariableNames[nameWithoutDigits]; - string nameWithDigits = nameWithoutDigits + count.ToString(); - if (oldVariableName == nameWithDigits) - { - return oldVariableName; - } - if (count != 1) - { - return nameWithDigits; - } - else - { - return nameWithoutDigits; - } - } - HashSet CollectLoopCounters(ILFunction function) { var loopCounters = new HashSet(); diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index 3a78c1ffce..bf87343576 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -189,7 +189,7 @@ ILFunction TransformDelegateConstruction( if (genericContext == null) return null; var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDefinition.RelativeVirtualAddress); var function = ilReader.ReadIL((MethodDefinitionHandle)targetMethod.MetadataToken, body, genericContext.Value, ILFunctionKind.Delegate, context.CancellationToken); function.DelegateType = delegateType; // Embed the lambda into the parent function's ILAst, so that "Show steps" can show diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 7f494cad6b..5385bbaae6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -274,6 +274,18 @@ void VisitLogicNot(Comp inst, ILInstruction arg) protected internal override void VisitCall(Call inst) { + if (NullableLiftingTransform.MatchGetValueOrDefault(inst, out var nullableValue, out var fallback) + && SemanticHelper.IsPure(fallback.Flags)) + { + context.Step("call Nullable{T}.GetValueOrDefault(a, b) -> a ?? b", inst); + var ldObj = new LdObj(nullableValue, inst.Method.DeclaringType); + var replacement = new NullCoalescingInstruction(NullCoalescingKind.NullableWithValueFallback, ldObj, fallback) { + UnderlyingResultType = fallback.ResultType + }; + inst.ReplaceWith(replacement.WithILRange(inst)); + replacement.AcceptVisitor(this); + return; + } base.VisitCall(inst); TransformAssignment.HandleCompoundAssign(inst, context); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index 35c5fd7fb4..e42551471d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -47,7 +47,7 @@ public class ILTransformContext public DecompilerSettings Settings { get; } public CancellationToken CancellationToken { get; set; } public Stepper Stepper { get; set; } - public Metadata.PEFile PEFile => TypeSystem.MainModule.PEFile; + public Metadata.MetadataFile PEFile => TypeSystem.MainModule.MetadataFile; internal DecompileRun? DecompileRun { get; set; } internal ResolvedUsingScope? UsingScope => DecompileRun?.UsingScope.Resolve(TypeSystem); @@ -88,12 +88,14 @@ internal ILReader CreateILReader() /// Unlike context.Stepper.Step(), calls to this method are only compiled in debug builds. /// [Conditional("STEP")] + [DebuggerStepThrough] internal void Step(string description, ILInstruction? near) { Stepper.Step(description, near); } [Conditional("STEP")] + [DebuggerStepThrough] internal void StepStartGroup(string description, ILInstruction? near = null) { Stepper.StartGroup(description, near); diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index ebc9a149a0..bc0e209c4c 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -80,7 +80,7 @@ public void Run(ILFunction function, ILTransformContext context) // Disable the transform if we are decompiling a display-class or local function method: // This happens if a local function or display class is selected in the ILSpy tree view. if (IsLocalFunctionMethod(function.Method, context) || IsLocalFunctionDisplayClass( - function.Method.ParentModule.PEFile, + function.Method.ParentModule.MetadataFile, (TypeDefinitionHandle)function.Method.DeclaringTypeDefinition.MetadataToken, context) ) @@ -462,7 +462,7 @@ ILFunction ReadLocalFunctionDefinition(ILFunction rootFunction, IMethod targetMe else { var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDefinition.RelativeVirtualAddress); function = ilReader.ReadIL((MethodDefinitionHandle)targetMethod.MetadataToken, body, genericContext.GetValueOrDefault(), ILFunctionKind.LocalFunction, @@ -755,10 +755,10 @@ public static bool IsLocalFunctionMethod(IMethod method, ILTransformContext cont { if (method.MetadataToken.IsNil) return false; - return IsLocalFunctionMethod(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken, context); + return IsLocalFunctionMethod(method.ParentModule.MetadataFile, (MethodDefinitionHandle)method.MetadataToken, context); } - public static bool IsLocalFunctionMethod(PEFile module, MethodDefinitionHandle methodHandle, ILTransformContext context = null) + public static bool IsLocalFunctionMethod(MetadataFile module, MethodDefinitionHandle methodHandle, ILTransformContext context = null) { if (context != null && context.PEFile != module) return false; @@ -776,7 +776,7 @@ public static bool IsLocalFunctionMethod(PEFile module, MethodDefinitionHandle m return true; } - public static bool LocalFunctionNeedsAccessibilityChange(PEFile module, MethodDefinitionHandle methodHandle) + public static bool LocalFunctionNeedsAccessibilityChange(MetadataFile module, MethodDefinitionHandle methodHandle) { if (!IsLocalFunctionMethod(module, methodHandle)) return false; @@ -797,7 +797,7 @@ public static bool LocalFunctionNeedsAccessibilityChange(PEFile module, MethodDe return false; } - public static bool IsLocalFunctionDisplayClass(PEFile module, TypeDefinitionHandle typeHandle, ILTransformContext context = null) + public static bool IsLocalFunctionDisplayClass(MetadataFile module, TypeDefinitionHandle typeHandle, ILTransformContext context = null) { if (context != null && context.PEFile != module) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 44f73e3e47..4e297b00d9 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -16,7 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -1047,6 +1046,24 @@ internal static bool MatchGetValueOrDefault(ILInstruction inst, out ILInstructio return true; } + /// + /// Matches 'call nullableValue.GetValueOrDefault(fallback)' + /// + internal static bool MatchGetValueOrDefault(ILInstruction inst, out ILInstruction nullableValue, out ILInstruction fallback) + { + nullableValue = null; + fallback = null; + if (!(inst is Call call)) + return false; + if (call.Method.Name != "GetValueOrDefault" || call.Arguments.Count != 2) + return false; + if (call.Method.DeclaringTypeDefinition?.KnownTypeCode != KnownTypeCode.NullableOfT) + return false; + nullableValue = call.Arguments[0]; + fallback = call.Arguments[1]; + return true; + } + /// /// Matches 'call Nullable{T}.GetValueOrDefault(ldloca v)' /// diff --git a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs index 2d82abd296..164b806e23 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs @@ -54,7 +54,7 @@ void Run(CallInstruction inst, ILTransformContext context) var genericContext = new GenericContext(inst.Method); // partially copied from CSharpDecompiler var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDef.RelativeVirtualAddress); var proxyFunction = ilReader.ReadIL(handle, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken); var transformContext = new ILTransformContext(context, proxyFunction); proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext); diff --git a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs b/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs index f3f85386ac..0882427f20 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs @@ -95,11 +95,13 @@ public Stepper() /// /// May throw in debug mode. /// + [DebuggerStepThrough] public void Step(string description, ILInstruction? near = null) { StepInternal(description, near); } + [DebuggerStepThrough] private Node StepInternal(string description, ILInstruction? near) { if (step == StepLimit) @@ -123,6 +125,7 @@ private Node StepInternal(string description, ILInstruction? near) return stepNode; } + [DebuggerStepThrough] public void StartGroup(string description, ILInstruction? near = null) { groups.Push(StepInternal(description, near)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index d59041381a..e254d243b6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -294,6 +294,16 @@ bool AddSwitchSection(string value, ILInstruction inst) keepAssignmentBefore = true; switchValue = new LdLoc(switchValueVar); } + if (!switchValueVar.Type.IsKnownType(KnownTypeCode.String)) + { + if (!context.Settings.SwitchOnReadOnlySpanChar) + return false; + if (!switchValueVar.Type.IsKnownType(KnownTypeCode.ReadOnlySpanOfT) + && !switchValueVar.Type.IsKnownType(KnownTypeCode.SpanOfT)) + { + return false; + } + } // if instruction must be followed by a branch to the next case if (!nextCaseJump.MatchBranch(out Block currentCaseBlock)) return false; @@ -335,7 +345,7 @@ bool AddSwitchSection(string value, ILInstruction inst) int offset = firstBlock == null ? 1 : 0; var sections = new List(values.Skip(offset).SelectWithIndex((index, s) => new SwitchSection { Labels = new LongSet(index), Body = s.Item2 is Block b ? new Branch(b) : s.Item2.Clone() })); sections.Add(new SwitchSection { Labels = new LongSet(new LongInterval(0, sections.Count)).Invert(), Body = currentCaseBlock != null ? (ILInstruction)new Branch(currentCaseBlock) : new Leave((BlockContainer)nextCaseBlock) }); - var stringToInt = new StringToInt(switchValue, values.Skip(offset).Select(item => item.Item1).ToArray(), context.TypeSystem.FindType(KnownTypeCode.String)); + var stringToInt = new StringToInt(switchValue, values.Skip(offset).Select(item => item.Item1).ToArray(), switchValueVar.Type); var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); if (removeExtraLoad) @@ -1008,7 +1018,7 @@ bool MatchRoslynSwitchOnString(InstructionCollection instructions if (!(switchBlockInstructionsOffset + 1 < switchBlockInstructions.Count && switchBlockInstructions[switchBlockInstructionsOffset + 1] is SwitchInstruction switchInst && switchInst.Value.MatchLdLoc(out var switchValueVar) - && MatchComputeStringHashCall(switchBlockInstructions[switchBlockInstructionsOffset], + && MatchComputeStringOrReadOnlySpanHashCall(switchBlockInstructions[switchBlockInstructionsOffset], switchValueVar, out LdLoc switchValueLoad))) { return false; @@ -1643,19 +1653,28 @@ bool MatchStringLengthCall(ILInstruction inst, ILVariable switchValueVar) } /// - /// Matches 'stloc(targetVar, call ComputeStringHash(ldloc switchValue))' + /// Matches + /// 'stloc(targetVar, call ComputeStringHash(ldloc switchValue))' + /// - or - + /// 'stloc(targetVar, call ComputeSpanHash(ldloc switchValue))' + /// - or - + /// 'stloc(targetVar, call ComputeReadOnlySpanHash(ldloc switchValue))' /// - internal static bool MatchComputeStringHashCall(ILInstruction inst, ILVariable targetVar, out LdLoc switchValue) + internal static bool MatchComputeStringOrReadOnlySpanHashCall(ILInstruction inst, ILVariable targetVar, out LdLoc switchValue) { switchValue = null; if (!inst.MatchStLoc(targetVar, out var value)) return false; - if (!(value is Call c && c.Arguments.Count == 1 && c.Method.Name == "ComputeStringHash" && c.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass())) - return false; - if (!(c.Arguments[0] is LdLoc)) - return false; - switchValue = (LdLoc)c.Arguments[0]; - return true; + if (value is Call c && c.Arguments.Count == 1 + && c.Method.Name is "ComputeStringHash" or "ComputeSpanHash" or "ComputeReadOnlySpanHash" + && c.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) + { + if (c.Arguments[0] is not LdLoc ldloc) + return false; + switchValue = ldloc; + return true; + } + return false; } /// diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs index 1944872a84..cc0027b0a9 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs @@ -124,7 +124,7 @@ internal static bool TransformSpanTArrayInitialization(NewObj inst, StatementTra if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (context.Settings.Utf8StringLiterals && elementType.IsKnownType(KnownTypeCode.Byte) && DecodeUTF8String(initialValue, size, out string text)) @@ -311,7 +311,7 @@ bool HandleCpblkInitializer(Block block, int pos, ILVariable v, long length, out { return false; } - blob = fd.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + blob = fd.GetInitialValue(context.PEFile, context.TypeSystem); return true; } @@ -720,7 +720,7 @@ bool HandleRuntimeHelpersInitializeArray(Block body, int pos, ILVariable array, if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (DecodeArrayInitializer(arrayType, initialValue, arrayLength, valuesList)) { values = valuesList.ToArray(); @@ -753,7 +753,7 @@ bool DoTransformInlineRuntimeHelpersInitializeArray(Block body, int pos) if (!field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) return false; var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (!DecodeArrayInitializer(elementType, initialValue, arrayLength, valuesList)) return false; context.Step("InlineRuntimeHelpersInitializeArray: single-dim", inst); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index a62e16eb29..078faa3816 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -413,11 +413,11 @@ private bool ValidateDisplayClassDefinition(ITypeDefinition definition) { if (definition == null) return false; - if (definition.ParentModule.PEFile != context.PEFile) + if (definition.ParentModule.MetadataFile != context.PEFile) return false; // We do not want to accidentially transform state-machines and thus destroy them. var token = (TypeDefinitionHandle)definition.MetadataToken; - var metadata = definition.ParentModule.PEFile.Metadata; + var metadata = definition.ParentModule.MetadataFile.Metadata; if (YieldReturnDecompiler.IsCompilerGeneratorEnumerator(token, metadata)) return false; if (AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(token, metadata)) @@ -440,13 +440,13 @@ internal static bool ValidateConstructor(ILTransformContext context, IMethod met return false; var handle = (MethodDefinitionHandle)method.MetadataToken; var module = (MetadataModule)method.ParentModule; - var file = module.PEFile; + var file = module.MetadataFile; if (handle.IsNil || file != context.PEFile) return false; var def = file.Metadata.GetMethodDefinition(handle); if (def.RelativeVirtualAddress == 0) return false; - var body = file.Reader.GetMethodBody(def.RelativeVirtualAddress); + var body = file.GetMethodBody(def.RelativeVirtualAddress); // some compilers produce ctors with unused local variables // see https://github.com/icsharpcode/ILSpy/issues/2174 //if (!body.LocalSignature.IsNil) diff --git a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs index d1b642a308..557e80e88f 100644 --- a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs +++ b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs @@ -19,6 +19,7 @@ #nullable enable using System; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -60,10 +61,10 @@ public ResolutionException(string mainModule, string moduleName, string? resolve public interface IAssemblyResolver { #if !VSADDIN - PEFile? Resolve(IAssemblyReference reference); - PEFile? ResolveModule(PEFile mainModule, string moduleName); - Task ResolveAsync(IAssemblyReference reference); - Task ResolveModuleAsync(PEFile mainModule, string moduleName); + MetadataFile? Resolve(IAssemblyReference reference); + MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName); + Task ResolveAsync(IAssemblyReference reference); + Task ResolveModuleAsync(MetadataFile mainModule, string moduleName); #endif } @@ -275,6 +276,42 @@ public string FullName { return bytes; } + ImmutableArray typeReferences; + public ImmutableArray TypeReferences { + get { + var value = typeReferences; + if (value.IsDefault) + { + value = Metadata.TypeReferences + .Select(r => new TypeReferenceMetadata(Metadata, r)) + .Where(r => r.ResolutionScope == Handle) + .OrderBy(r => r.Namespace) + .ThenBy(r => r.Name) + .ToImmutableArray(); + typeReferences = value; + } + return value; + } + } + + ImmutableArray exportedTypes; + public ImmutableArray ExportedTypes { + get { + var value = exportedTypes; + if (value.IsDefault) + { + value = Metadata.ExportedTypes + .Select(r => new ExportedTypeMetadata(Metadata, r)) + .Where(r => r.Implementation == Handle) + .OrderBy(r => r.Namespace) + .ThenBy(r => r.Name) + .ToImmutableArray(); + exportedTypes = value; + } + return value; + } + } + public AssemblyReference(MetadataReader metadata, AssemblyReferenceHandle handle) { if (metadata == null) @@ -286,7 +323,7 @@ public AssemblyReference(MetadataReader metadata, AssemblyReferenceHandle handle entry = metadata.GetAssemblyReference(handle); } - public AssemblyReference(PEFile module, AssemblyReferenceHandle handle) + public AssemblyReference(MetadataFile module, AssemblyReferenceHandle handle) { if (module == null) throw new ArgumentNullException(nameof(module)); diff --git a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs index 241996e0bd..75a5187fba 100644 --- a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs +++ b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs @@ -32,7 +32,7 @@ public class CodeMappingInfo /// /// The module containing the code. /// - public PEFile Module { get; } + public MetadataFile Module { get; } /// /// The (parent) TypeDef containing the code. @@ -45,7 +45,7 @@ public class CodeMappingInfo /// /// Creates a instance using the given and . /// - public CodeMappingInfo(PEFile module, TypeDefinitionHandle type) + public CodeMappingInfo(MetadataFile module, TypeDefinitionHandle type) { this.Module = module; this.TypeDefinition = type; diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index 9e31cf9c90..692515ca9f 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -18,7 +18,6 @@ using System; using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; using System.Text.RegularExpressions; using ICSharpCode.Decompiler.TypeSystem; @@ -40,7 +39,7 @@ public static class DotNetCorePathFinderExtensions @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + @"|(packs[/\\](?[^/\\]+)\\(?[^/\\]+)\\ref([/\\].*)?[/\\])"; - public static string DetectTargetFrameworkId(this PEFile assembly) + public static string DetectTargetFrameworkId(this MetadataFile assembly) { return DetectTargetFrameworkId(assembly.Metadata, assembly.FileName); } @@ -178,17 +177,16 @@ public static string DetectTargetFrameworkId(this MetadataReader metadata, strin return string.Empty; } - public static bool IsReferenceAssembly(this PEFile assembly) + public static bool IsReferenceAssembly(this MetadataFile assembly) { - return IsReferenceAssembly(assembly.Reader, assembly.FileName); + return IsReferenceAssembly(assembly.Metadata, assembly.FileName); } - public static bool IsReferenceAssembly(this PEReader assembly, string assemblyPath) + public static bool IsReferenceAssembly(this MetadataReader metadata, string assemblyPath) { - if (assembly == null) - throw new ArgumentNullException(nameof(assembly)); + if (metadata == null) + throw new ArgumentNullException(nameof(metadata)); - var metadata = assembly.GetMetadataReader(); if (metadata.GetCustomAttributes(Handle.AssemblyDefinition).HasKnownAttribute(metadata, KnownAttribute.ReferenceAssembly)) return true; @@ -197,7 +195,7 @@ public static bool IsReferenceAssembly(this PEReader assembly, string assemblyPa return refPathMatch.Success; } - public static string DetectRuntimePack(this PEFile assembly) + public static string DetectRuntimePack(this MetadataFile assembly) { if (assembly is null) { diff --git a/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs b/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs index a2c1414b66..d914f8685f 100644 --- a/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs +++ b/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs @@ -35,12 +35,12 @@ protected EnumUnderlyingTypeResolveException( } [Serializable] - public class PEFileNotSupportedException : Exception + public class MetadataFileNotSupportedException : Exception { - public PEFileNotSupportedException() { } - public PEFileNotSupportedException(string message) : base(message) { } - public PEFileNotSupportedException(string message, Exception inner) : base(message, inner) { } - protected PEFileNotSupportedException( + public MetadataFileNotSupportedException() { } + public MetadataFileNotSupportedException(string message) : base(message) { } + public MetadataFileNotSupportedException(string message, Exception inner) : base(message, inner) { } + protected MetadataFileNotSupportedException( SerializationInfo info, StreamingContext context) : base(info, context) { } } diff --git a/ICSharpCode.Decompiler/Metadata/ExportedTypeMetadata.cs b/ICSharpCode.Decompiler/Metadata/ExportedTypeMetadata.cs new file mode 100644 index 0000000000..3bada57eed --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/ExportedTypeMetadata.cs @@ -0,0 +1,103 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; + +namespace ICSharpCode.Decompiler.Metadata +{ +#if !VSADDIN + /// + /// Convenience wrapper for and . + /// + public sealed class ExportedTypeMetadata + { + readonly ExportedType entry; + + public MetadataReader Metadata { get; } + public ExportedTypeHandle Handle { get; } + + string? name; + public string Name { + get { + try + { + return name ??= Metadata.GetString(entry.Name); + } + catch (BadImageFormatException) + { + return name = $"ET:{Handle}"; + } + } + } + + string? @namespace; + public string Namespace { + get { + try + { + return @namespace ??= Metadata.GetString(entry.Namespace); + } + catch (BadImageFormatException) + { + return @namespace = $"namespace(ET:{Handle})"; + } + } + } + + public EntityHandle Implementation => entry.Implementation; + public TypeAttributes Attributes => entry.Attributes; + public bool IsForwarder => entry.IsForwarder; + public NamespaceDefinition NamespaceDefinition => Metadata.GetNamespaceDefinition(entry.NamespaceDefinition); + + ImmutableArray exportedTypes; + public ImmutableArray ExportedTypes { + get { + var value = exportedTypes; + if (value.IsDefault) + { + value = Metadata.ExportedTypes + .Select(r => new ExportedTypeMetadata(Metadata, r)) + .Where(r => r.Implementation == Handle) + .OrderBy(r => r.Namespace) + .ThenBy(r => r.Name) + .ToImmutableArray(); + exportedTypes = value; + } + return value; + } + } + + public ExportedTypeMetadata(MetadataReader metadata, ExportedTypeHandle handle) + { + Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); + if (handle.IsNil) + throw new ArgumentNullException(nameof(handle)); + Handle = handle; + entry = metadata.GetExportedType(handle); + } + + public override string ToString() => $"{Namespace}::{Name}"; + } +#endif +} diff --git a/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs index 012525b1ed..cb0c595f0a 100644 --- a/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs +++ b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Metadata { public class FindTypeDecoder : ISignatureTypeProvider { - readonly PEFile declaringModule; + readonly MetadataFile declaringModule; readonly MetadataModule? currentModule; readonly TypeDefinitionHandle handle; readonly string? typeName; @@ -40,7 +40,7 @@ public class FindTypeDecoder : ISignatureTypeProvider /// Constructs a FindTypeDecoder that finds uses of a specific type-definition handle. /// This assumes that the module we are search in is the same as the module containing the type-definiton. /// - internal FindTypeDecoder(TypeDefinitionHandle handle, PEFile declaringModule) + internal FindTypeDecoder(TypeDefinitionHandle handle, MetadataFile declaringModule) { this.handle = handle; this.declaringModule = declaringModule; @@ -54,7 +54,7 @@ internal FindTypeDecoder(TypeDefinitionHandle handle, PEFile declaringModule) public FindTypeDecoder(MetadataModule currentModule, ITypeDefinition type) { this.currentModule = currentModule; - this.declaringModule = type.ParentModule?.PEFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); + this.declaringModule = type.ParentModule?.MetadataFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); this.handle = (TypeDefinitionHandle)type.MetadataToken; this.primitiveType = type.KnownTypeCode == KnownTypeCode.None ? 0 : type.KnownTypeCode.ToPrimitiveTypeCode(); this.typeName = type.MetadataName; @@ -128,7 +128,7 @@ public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle hand if (td == null) return false; - return td.MetadataToken == this.handle && td.ParentModule?.PEFile == declaringModule; + return td.MetadataToken == this.handle && td.ParentModule?.MetadataFile == declaringModule; } public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) diff --git a/ICSharpCode.Decompiler/Metadata/MemberReferenceMetadata.cs b/ICSharpCode.Decompiler/Metadata/MemberReferenceMetadata.cs new file mode 100644 index 0000000000..001f58776f --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/MemberReferenceMetadata.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Reflection.Metadata; + +namespace ICSharpCode.Decompiler.Metadata +{ +#if !VSADDIN + /// + /// Convenience wrapper for and . + /// + public sealed class MemberReferenceMetadata + { + readonly MemberReference entry; + + public MetadataReader Metadata { get; } + public MemberReferenceHandle Handle { get; } + + string? name; + + public string Name { + get { + try + { + return name ??= Metadata.GetString(entry.Name); + } + catch (BadImageFormatException) + { + return name = $"MR:{Handle}"; + } + } + } + + public EntityHandle Parent => entry.Parent; + + public MemberReferenceKind MemberReferenceKind => entry.GetKind(); + + public MemberReferenceMetadata(MetadataReader metadata, MemberReferenceHandle handle) + { + Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); + if (handle.IsNil) + throw new ArgumentNullException(nameof(handle)); + Handle = handle; + entry = metadata.GetMemberReference(handle); + } + + public override string ToString() + => Name; + } +#endif +} diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index 5ce6beafa4..90f44096a8 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -1,15 +1,31 @@ -using System; +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Buffers.Binary; using System.Collections.Generic; -using System.Collections.Immutable; +using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -21,33 +37,11 @@ namespace ICSharpCode.Decompiler.Metadata { public static class MetadataExtensions { - static HashAlgorithm GetHashAlgorithm(this MetadataReader reader) - { - switch (reader.GetAssemblyDefinition().HashAlgorithm) - { - case AssemblyHashAlgorithm.None: - // only for multi-module assemblies? - return SHA1.Create(); - case AssemblyHashAlgorithm.MD5: - return MD5.Create(); - case AssemblyHashAlgorithm.Sha1: - return SHA1.Create(); - case AssemblyHashAlgorithm.Sha256: - return SHA256.Create(); - case AssemblyHashAlgorithm.Sha384: - return SHA384.Create(); - case AssemblyHashAlgorithm.Sha512: - return SHA512.Create(); - default: - return SHA1.Create(); // default? - } - } - static string CalculatePublicKeyToken(BlobHandle blob, MetadataReader reader) { // Calculate public key token: - // 1. hash the public key using the appropriate algorithm. - byte[] publicKeyTokenBytes = reader.GetHashAlgorithm().ComputeHash(reader.GetBlobBytes(blob)); + // 1. hash the public key (always use SHA1). + byte[] publicKeyTokenBytes = SHA1.Create().ComputeHash(reader.GetBlobBytes(blob)); // 2. take the last 8 bytes // 3. according to Cecil we need to reverse them, other sources did not mention this. return publicKeyTokenBytes.TakeLast(8).Reverse().ToHexString(8); @@ -451,5 +445,23 @@ public static BlobReader AsBlobReader(this MetadataReader metadataReader) return new(metadataReader.MetadataPointer, metadataReader.MetadataLength); } } + + public static uint ReadULEB128(this BinaryReader reader) + { + uint val = 0; + int shift = 0; + while (true) + { + byte b = reader.ReadByte(); + val |= (b & 0b0111_1111u) << shift; + if ((b & 0b1000_0000) == 0) + break; + shift += 7; + if (shift >= 35) + throw new OverflowException(); + } + return val; + } + } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataFile.cs b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs new file mode 100644 index 0000000000..c92c0e061c --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs @@ -0,0 +1,332 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + +namespace ICSharpCode.Decompiler.Metadata +{ + /// + /// MetadataFile is the main class the decompiler uses to represent a metadata assembly/module. + /// Every file on disk can be loaded into a standalone MetadataFile instance. + /// + /// A MetadataFile can be combined with its referenced assemblies/modules to form a type system, + /// in that case the class is used instead. + /// + /// + /// In addition to wrapping a System.Reflection.Metadata.MetadataReader, this class + /// contains a few decompiler-specific caches to allow efficiently constructing a type + /// system from multiple MetadataFiles. This allows the caches to be shared across multiple + /// decompiled type systems. + /// + [DebuggerDisplay("{Kind}: {FileName}")] + public class MetadataFile + { + public enum MetadataFileKind + { + PortableExecutable, + ProgramDebugDatabase, + WebCIL, + Metadata + } + + public string FileName { get; } + public MetadataFileKind Kind { get; } + public MetadataReader Metadata { get; } + + public virtual int MetadataOffset { get; } + public virtual bool IsEmbedded { get; } + + public bool IsAssembly => Metadata.IsAssembly; + + string? name; + + public string Name { + get { + var value = LazyInit.VolatileRead(ref name); + if (value == null) + { + var metadata = Metadata; + value = metadata.IsAssembly + ? metadata.GetString(metadata.GetAssemblyDefinition().Name) + : metadata.GetString(metadata.GetModuleDefinition().Name); + value = LazyInit.GetOrSet(ref name, value); + } + return value; + } + } + + string? fullName; + + public string FullName { + get { + var value = LazyInit.VolatileRead(ref fullName); + if (value == null) + { + var metadata = Metadata; + value = metadata.IsAssembly ? metadata.GetFullAssemblyName() : Name; + value = LazyInit.GetOrSet(ref fullName, value); + } + return value; + } + } + + public TargetRuntime GetRuntime() + { + string version = Metadata.MetadataVersion; + if (version == null || version.Length <= 1) + return TargetRuntime.Unknown; + switch (version[1]) + { + case '1': + if (version.Length <= 3) + return TargetRuntime.Unknown; + if (version[3] == 1) + return TargetRuntime.Net_1_0; + else + return TargetRuntime.Net_1_1; + case '2': + return TargetRuntime.Net_2_0; + case '4': + return TargetRuntime.Net_4_0; + default: + return TargetRuntime.Unknown; + } + } + + ImmutableArray assemblyReferences; + public ImmutableArray AssemblyReferences { + get { + var value = assemblyReferences; + if (value.IsDefault) + { + value = Metadata.AssemblyReferences.Select(r => new AssemblyReference(this.Metadata, r)).ToImmutableArray(); + assemblyReferences = value; + } + return value; + } + } + + ImmutableArray moduleReferences; + public ImmutableArray ModuleReferences { + get { + var value = moduleReferences; + if (value.IsDefault) + { + value = Metadata.GetModuleReferences() + .Select(m => new ModuleReferenceMetadata(this.Metadata, m)) + .ToImmutableArray(); + + moduleReferences = value; + } + return value; + } + } + + public ImmutableArray Resources => GetResources().ToImmutableArray(); + + IEnumerable GetResources() + { + var metadata = Metadata; + foreach (var h in metadata.ManifestResources) + { + yield return new MetadataResource(this, h); + } + } + + Dictionary? typeLookup; + + /// + /// Finds the top-level-type with the specified name. + /// + public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName) + { + var lookup = LazyInit.VolatileRead(ref typeLookup); + if (lookup == null) + { + lookup = new Dictionary(); + foreach (var handle in Metadata.TypeDefinitions) + { + var td = Metadata.GetTypeDefinition(handle); + if (!td.GetDeclaringType().IsNil) + { + continue; // nested type + } + var nsHandle = td.Namespace; + string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle); + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount); + lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle; + } + lookup = LazyInit.GetOrSet(ref typeLookup, lookup); + } + if (lookup.TryGetValue(typeName, out var resultHandle)) + return resultHandle; + else + return default; + } + + Dictionary? typeForwarderLookup; + + /// + /// Finds the type forwarder with the specified name. + /// + public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName) + { + var lookup = LazyInit.VolatileRead(ref typeForwarderLookup); + if (lookup == null) + { + lookup = new Dictionary(); + foreach (var handle in Metadata.ExportedTypes) + { + var td = Metadata.GetExportedType(handle); + lookup[td.GetFullTypeName(Metadata)] = handle; + } + lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup); + } + if (lookup.TryGetValue(typeName, out var resultHandle)) + return resultHandle; + else + return default; + } + + MethodSemanticsLookup? methodSemanticsLookup; + + internal MethodSemanticsLookup MethodSemanticsLookup { + get { + var r = LazyInit.VolatileRead(ref methodSemanticsLookup); + if (r != null) + return r; + else + return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata)); + } + } + + public MetadataFile(MetadataFileKind kind, string fileName, MetadataReaderProvider metadata, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default, int metadataOffset = 0, bool isEmbedded = false) + { + this.Kind = kind; + this.FileName = fileName; + this.Metadata = metadata.GetMetadataReader(metadataOptions); + this.MetadataOffset = metadataOffset; + this.IsEmbedded = isEmbedded; + } + + private protected MetadataFile(MetadataFileKind kind, string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + { + this.Kind = kind; + this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); + _ = reader ?? throw new ArgumentNullException(nameof(reader)); + if (!reader.HasMetadata) + throw new MetadataFileNotSupportedException("PE file does not contain any managed metadata."); + this.Metadata = reader.GetMetadataReader(metadataOptions); + } + + public virtual MethodBodyBlock GetMethodBody(int rva) + { + throw new BadImageFormatException("This metadata file does not contain method bodies."); + } + + public virtual SectionData GetSectionData(int rva) + { + throw new BadImageFormatException("This metadata file does not support sections."); + } + + public virtual int GetContainingSectionIndex(int rva) + { + throw new BadImageFormatException("This metadata file does not support sections."); + } + + public virtual ImmutableArray SectionHeaders => throw new BadImageFormatException("This metadata file does not support sections."); + + /// + /// Gets the CLI header or null if the image does not have one. + /// + public virtual CorHeader? CorHeader => null; + + public IModuleReference WithOptions(TypeSystemOptions options) + { + return new MetadataFileWithOptions(this, options); + } + + private class MetadataFileWithOptions : IModuleReference + { + readonly MetadataFile peFile; + readonly TypeSystemOptions options; + + public MetadataFileWithOptions(MetadataFile peFile, TypeSystemOptions options) + { + this.peFile = peFile; + this.options = options; + } + + IModule IModuleReference.Resolve(ITypeResolveContext context) + { + return new MetadataModule(context.Compilation, peFile, options); + } + } + } + + /// + /// Abstraction over PEMemoryBlock + /// + public readonly unsafe struct SectionData + { + public byte* Pointer { get; } + public int Length { get; } + + public SectionData(PEMemoryBlock block) + { + Pointer = block.Pointer; + Length = block.Length; + } + + public SectionData(byte* startPointer, int length) + { + Pointer = startPointer; + Length = length; + } + + public BlobReader GetReader() + { + return new BlobReader(Pointer, Length); + } + + internal BlobReader GetReader(int offset, int size) + { + return new BlobReader(Pointer + offset, size); + } + } + + public struct SectionHeader + { + public string Name; + public uint VirtualSize; + public uint VirtualAddress; + public uint RawDataSize; + public uint RawDataPtr; + } +} diff --git a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs index b647579721..0b96627b2e 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs @@ -29,7 +29,7 @@ public readonly struct MetadataGenericContext readonly TypeDefinitionHandle declaringType; readonly MethodDefinitionHandle method; - public MetadataGenericContext(MethodDefinitionHandle method, PEFile module) + public MetadataGenericContext(MethodDefinitionHandle method, MetadataFile module) { this.metadata = module.Metadata; this.method = method; @@ -43,7 +43,7 @@ public MetadataGenericContext(MethodDefinitionHandle method, MetadataReader meta this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType(); } - public MetadataGenericContext(TypeDefinitionHandle declaringType, PEFile module) + public MetadataGenericContext(TypeDefinitionHandle declaringType, MetadataFile module) { this.metadata = module.Metadata; this.method = default; diff --git a/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs b/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs new file mode 100644 index 0000000000..eee2078f88 --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/ModuleReferenceMetadata.cs @@ -0,0 +1,132 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; + +namespace ICSharpCode.Decompiler.Metadata +{ +#if !VSADDIN + public class ModuleReferenceMetadata /* : IModuleReference*/ + { + readonly ModuleReference entry; + + public MetadataReader Metadata { get; } + public ModuleReferenceHandle Handle { get; } + + string? name; + public string Name { + get { + if (name == null) + { + try + { + name = Metadata.GetString(entry.Name); + } + catch (BadImageFormatException) + { + name = $"AR:{Handle}"; + } + } + return name; + } + } + + ImmutableArray attributes; + public ImmutableArray Attributes { + get { + var value = attributes; + if (value.IsDefault) + { + value = entry.GetCustomAttributes().Select(Metadata.GetCustomAttribute).ToImmutableArray(); + attributes = value; + } + return value; + } + } + + ImmutableArray typeReferences; + public ImmutableArray TypeReferences { + get { + var value = typeReferences; + if (value.IsDefault) + { + value = Metadata.TypeReferences + .Select(r => new TypeReferenceMetadata(Metadata, r)) + .Where(r => r.ResolutionScope == Handle) + .OrderBy(r => r.Namespace) + .ThenBy(r => r.Name) + .ToImmutableArray(); + typeReferences = value; + } + return value; + } + } + + ImmutableArray exportedTypes; + public ImmutableArray ExportedTypes { + get { + var value = exportedTypes; + if (value.IsDefault) + { + value = Metadata.ExportedTypes + .Select(r => new ExportedTypeMetadata(Metadata, r)) + .Where(r => r.Implementation == Handle) + .OrderBy(r => r.Namespace) + .ThenBy(r => r.Name) + .ToImmutableArray(); + exportedTypes = value; + } + return value; + } + } + + public ModuleReferenceMetadata(MetadataReader metadata, ModuleReferenceHandle handle) + { + if (metadata == null) + throw new ArgumentNullException(nameof(metadata)); + if (handle.IsNil) + throw new ArgumentNullException(nameof(handle)); + Metadata = metadata; + Handle = handle; + entry = metadata.GetModuleReference(handle); + } + + public ModuleReferenceMetadata(PEFile module, ModuleReferenceHandle handle) + { + if (module == null) + throw new ArgumentNullException(nameof(module)); + if (handle.IsNil) + throw new ArgumentNullException(nameof(handle)); + Metadata = module.Metadata; + Handle = handle; + entry = Metadata.GetModuleReference(handle); + } + + public override string ToString() + { + return Name; + } + } +#endif +} diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs index 45b72824e9..9277ed71f1 100644 --- a/ICSharpCode.Decompiler/Metadata/PEFile.cs +++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs @@ -19,7 +19,6 @@ #nullable enable using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.IO; @@ -28,29 +27,13 @@ using System.Reflection.PortableExecutable; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.Metadata { - /// - /// PEFile is the main class the decompiler uses to represent a metadata assembly/module. - /// Every file on disk can be loaded into a standalone PEFile instance. - /// - /// A PEFile can be combined with its referenced assemblies/modules to form a type system, - /// in that case the class is used instead. - /// - /// - /// In addition to wrapping a System.Reflection.Metadata.PEReader, this class - /// contains a few decompiler-specific caches to allow efficiently constructing a type - /// system from multiple PEFiles. This allows the caches to be shared across multiple - /// decompiled type systems. - /// [DebuggerDisplay("{FileName}")] - public class PEFile : IDisposable, TypeSystem.IModuleReference + public class PEFile : MetadataFile, IDisposable, IModuleReference { - public string FileName { get; } public PEReader Reader { get; } - public MetadataReader Metadata { get; } public PEFile(string fileName, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) : this(fileName, new PEReader(new FileStream(fileName, FileMode.Open, FileAccess.Read), streamOptions), metadataOptions) @@ -63,193 +46,59 @@ public PEFile(string fileName, Stream stream, PEStreamOptions streamOptions = PE } public PEFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + : base(MetadataFileKind.PortableExecutable, fileName, reader, metadataOptions) { - this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); - this.Reader = reader ?? throw new ArgumentNullException(nameof(reader)); - if (!reader.HasMetadata) - throw new PEFileNotSupportedException("PE file does not contain any managed metadata."); - this.Metadata = reader.GetMetadataReader(metadataOptions); + this.Reader = reader; } - public bool IsAssembly => Metadata.IsAssembly; - - string? name; - - public string Name { - get { - var value = LazyInit.VolatileRead(ref name); - if (value == null) - { - var metadata = Metadata; - value = metadata.IsAssembly - ? metadata.GetString(metadata.GetAssemblyDefinition().Name) - : metadata.GetString(metadata.GetModuleDefinition().Name); - value = LazyInit.GetOrSet(ref name, value); - } - return value; - } - } - - string? fullName; - - public string FullName { - get { - var value = LazyInit.VolatileRead(ref fullName); - if (value == null) - { - var metadata = Metadata; - value = metadata.IsAssembly ? metadata.GetFullAssemblyName() : Name; - value = LazyInit.GetOrSet(ref fullName, value); - } - return value; - } - } - - public TargetRuntime GetRuntime() - { - string version = Metadata.MetadataVersion; - if (version == null || version.Length <= 1) - return TargetRuntime.Unknown; - switch (version[1]) - { - case '1': - if (version.Length <= 3) - return TargetRuntime.Unknown; - if (version[3] == 1) - return TargetRuntime.Net_1_0; - else - return TargetRuntime.Net_1_1; - case '2': - return TargetRuntime.Net_2_0; - case '4': - return TargetRuntime.Net_4_0; - default: - return TargetRuntime.Unknown; - } - } - - ImmutableArray assemblyReferences; - - public ImmutableArray AssemblyReferences { - get { - var value = assemblyReferences; - if (value.IsDefault) - { - value = Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray(); - assemblyReferences = value; - } - return value; - } - } - - public ImmutableArray Resources => GetResources().ToImmutableArray(); - - IEnumerable GetResources() - { - var metadata = Metadata; - foreach (var h in metadata.ManifestResources) - { - yield return new MetadataResource(this, h); - } - } + public override bool IsEmbedded => false; + public override int MetadataOffset => Reader.PEHeaders.MetadataStartOffset; public void Dispose() { Reader.Dispose(); } - Dictionary? typeLookup; - - /// - /// Finds the top-level-type with the specified name. - /// - public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName) + IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) { - var lookup = LazyInit.VolatileRead(ref typeLookup); - if (lookup == null) - { - lookup = new Dictionary(); - foreach (var handle in Metadata.TypeDefinitions) - { - var td = Metadata.GetTypeDefinition(handle); - if (!td.GetDeclaringType().IsNil) - { - continue; // nested type - } - var nsHandle = td.Namespace; - string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle); - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount); - lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle; - } - lookup = LazyInit.GetOrSet(ref typeLookup, lookup); - } - if (lookup.TryGetValue(typeName, out var resultHandle)) - return resultHandle; - else - return default; + return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); } - Dictionary? typeForwarderLookup; - - /// - /// Finds the type forwarder with the specified name. - /// - public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName) + public override MethodBodyBlock GetMethodBody(int rva) { - var lookup = LazyInit.VolatileRead(ref typeForwarderLookup); - if (lookup == null) - { - lookup = new Dictionary(); - foreach (var handle in Metadata.ExportedTypes) - { - var td = Metadata.GetExportedType(handle); - lookup[td.GetFullTypeName(Metadata)] = handle; - } - lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup); - } - if (lookup.TryGetValue(typeName, out var resultHandle)) - return resultHandle; - else - return default; - } - - MethodSemanticsLookup? methodSemanticsLookup; - - internal MethodSemanticsLookup MethodSemanticsLookup { - get { - var r = LazyInit.VolatileRead(ref methodSemanticsLookup); - if (r != null) - return r; - else - return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata)); - } + return Reader.GetMethodBody(rva); } - public TypeSystem.IModuleReference WithOptions(TypeSystemOptions options) + public override SectionData GetSectionData(int rva) { - return new PEFileWithOptions(this, options); + return new SectionData(Reader.GetSectionData(rva)); } - IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) + public override int GetContainingSectionIndex(int rva) { - return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); + return Reader.PEHeaders.GetContainingSectionIndex(rva); } - private class PEFileWithOptions : TypeSystem.IModuleReference - { - readonly PEFile peFile; - readonly TypeSystemOptions options; - - public PEFileWithOptions(PEFile peFile, TypeSystemOptions options) - { - this.peFile = peFile; - this.options = options; - } - - IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) - { - return new MetadataModule(context.Compilation, peFile, options); + ImmutableArray sectionHeaders; + public override ImmutableArray SectionHeaders { + get { + var value = sectionHeaders; + if (value.IsDefault) + { + value = Reader.PEHeaders.SectionHeaders + .Select(h => new SectionHeader { + Name = h.Name, + RawDataPtr = unchecked((uint)h.PointerToRawData), + RawDataSize = unchecked((uint)h.SizeOfRawData), + VirtualAddress = unchecked((uint)h.VirtualAddress), + VirtualSize = unchecked((uint)h.VirtualSize) + }).ToImmutableArray(); + sectionHeaders = value; + } + return value; } } + + public override CorHeader? CorHeader => Reader.PEHeaders.CorHeader; } } diff --git a/ICSharpCode.Decompiler/Metadata/Resource.cs b/ICSharpCode.Decompiler/Metadata/Resource.cs index ca3ece687f..e1f22eb6ad 100644 --- a/ICSharpCode.Decompiler/Metadata/Resource.cs +++ b/ICSharpCode.Decompiler/Metadata/Resource.cs @@ -23,7 +23,6 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; namespace ICSharpCode.Decompiler.Metadata { @@ -67,11 +66,11 @@ public override Stream TryOpenStream() sealed class MetadataResource : Resource { - public PEFile Module { get; } + public MetadataFile Module { get; } public ManifestResourceHandle Handle { get; } public bool IsNil => Handle.IsNil; - public MetadataResource(PEFile module, ManifestResourceHandle handle) + public MetadataResource(MetadataFile module, ManifestResourceHandle handle) { this.Module = module ?? throw new ArgumentNullException(nameof(module)); this.Handle = handle; @@ -117,15 +116,13 @@ unsafe bool TryReadResource(out byte* ptr, out long length) // embedded resources cannot be read from this binary. if (ResourceType != ResourceType.Embedded) return false; - // get cor header - var headers = Module.Reader.PEHeaders; - if (headers.CorHeader == null) + if (Module.CorHeader == null) return false; - var resources = headers.CorHeader.ResourcesDirectory; + var resources = Module.CorHeader.ResourcesDirectory; // validate resources directory, GetSectionData throws on negative RVAs if (resources.RelativeVirtualAddress <= 0) return false; - var sectionData = Module.Reader.GetSectionData(resources.RelativeVirtualAddress); + var sectionData = Module.GetSectionData(resources.RelativeVirtualAddress); // validate section length: we need at least 4 bytes to extract // the actual length of the resource blob. if (sectionData.Length < 4) @@ -144,7 +141,7 @@ unsafe bool TryReadResource(out byte* ptr, out long length) { if (!TryReadResource(out var ptr, out var length)) return null; - return new ResourceMemoryStream(Module.Reader, ptr + sizeof(int), length); + return new ResourceMemoryStream(Module, ptr + sizeof(int), length); } public unsafe override long? TryGetLength() @@ -158,10 +155,10 @@ unsafe bool TryReadResource(out byte* ptr, out long length) sealed unsafe class ResourceMemoryStream : UnmanagedMemoryStream { #pragma warning disable IDE0052 // Remove unread private members - readonly PEReader peReader; + readonly MetadataFile peReader; #pragma warning restore IDE0052 // Remove unread private members - public ResourceMemoryStream(PEReader peReader, byte* data, long length) + public ResourceMemoryStream(MetadataFile peReader, byte* data, long length) : base(data, length, length, FileAccess.Read) { // Keep the PEReader alive while the stream in in use. diff --git a/ICSharpCode.Decompiler/Metadata/TypeReferenceMetadata.cs b/ICSharpCode.Decompiler/Metadata/TypeReferenceMetadata.cs new file mode 100644 index 0000000000..fb2c826048 --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/TypeReferenceMetadata.cs @@ -0,0 +1,112 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection.Metadata; + +namespace ICSharpCode.Decompiler.Metadata +{ +#if !VSADDIN + public sealed class TypeReferenceMetadata + { + readonly TypeReference entry; + + public MetadataReader Metadata { get; } + public TypeReferenceHandle Handle { get; } + + string? name; + public string Name { + get { + try + { + return name ??= Metadata.GetString(entry.Name); + } + catch (BadImageFormatException) + { + return name = $"TR:{Handle}"; + } + } + } + + string? @namespace; + public string Namespace { + get { + try + { + return @namespace ??= Metadata.GetString(entry.Namespace); + } + catch (BadImageFormatException) + { + return @namespace = $"namespace(TR:{Handle})"; + } + } + } + + public EntityHandle ResolutionScope => entry.ResolutionScope; + + ImmutableArray memberReferences; + public ImmutableArray MemberReferences { + get { + var value = memberReferences; + if (value.IsDefault) + { + value = Metadata.MemberReferences + .Select(r => new MemberReferenceMetadata(Metadata, r)) + .Where(r => r.Parent == Handle) + .OrderBy(r => r.Name) + .ToImmutableArray(); + memberReferences = value; + } + return value; + } + } + + ImmutableArray typeReferences; + public ImmutableArray TypeReferences { + get { + var value = typeReferences; + if (value.IsDefault) + { + value = Metadata.TypeReferences + .Select(r => new TypeReferenceMetadata(Metadata, r)) + .Where(r => r.ResolutionScope == Handle) + .OrderBy(r => r.Name) + .ToImmutableArray(); + typeReferences = value; + } + return value; + } + } + + public TypeReferenceMetadata(MetadataReader metadata, TypeReferenceHandle handle) + { + Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); + if (handle.IsNil) + throw new ArgumentNullException(nameof(handle)); + Handle = handle; + entry = metadata.GetTypeReference(handle); + } + + public override string ToString() => $"{Namespace}::{Name}"; + } +#endif +} diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 92fff14b0a..ff27d30d6a 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -209,13 +209,13 @@ internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string } #if !VSADDIN - public PEFile? Resolve(IAssemblyReference name) + public MetadataFile? Resolve(IAssemblyReference name) { var file = FindAssemblyFile(name); return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex)); } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { string? baseDirectory = Path.GetDirectoryName(mainModule.FileName); if (baseDirectory == null) @@ -224,7 +224,7 @@ internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string return CreatePEFileFromFileName(moduleFileName, ex => new ResolutionException(mainModule.FileName, moduleName, moduleFileName, ex)); } - private PEFile? CreatePEFileFromFileName(string? fileName, Func makeException) + private MetadataFile? CreatePEFileFromFileName(string? fileName, Func makeException) { if (fileName == null) { @@ -251,12 +251,12 @@ internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string return null; } - public Task ResolveAsync(IAssemblyReference name) + public Task ResolveAsync(IAssemblyReference name) { return Task.Run(() => Resolve(name)); } - public Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { return Task.Run(() => ResolveModule(mainModule, moduleName)); } diff --git a/ICSharpCode.Decompiler/Metadata/WebCilFile.cs b/ICSharpCode.Decompiler/Metadata/WebCilFile.cs new file mode 100644 index 0000000000..291316085c --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/WebCilFile.cs @@ -0,0 +1,284 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.IO.MemoryMappedFiles; +using System.Reflection.Metadata; +using System.Text; + +using ICSharpCode.Decompiler.TypeSystem; + +#nullable enable + +namespace ICSharpCode.Decompiler.Metadata +{ + public class WebCilFile : MetadataFile, IDisposable, IModuleReference + { + readonly MemoryMappedViewAccessor view; + readonly long webcilOffset; + + private WebCilFile(string fileName, long webcilOffset, long metadataOffset, MemoryMappedViewAccessor view, ImmutableArray sectionHeaders, ImmutableArray wasmSections, MetadataReaderProvider provider, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + : base(MetadataFileKind.WebCIL, fileName, provider, metadataOptions, 0) + { + this.webcilOffset = webcilOffset; + this.MetadataOffset = (int)metadataOffset; + this.view = view; + this.SectionHeaders = sectionHeaders; + this.WasmSections = wasmSections; + } + + public static WebCilFile? FromStream(string fileName, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + { + using var memoryMappedFile = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); + var view = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); + try + { + // read magic "\0asm" + if (view.ReadUInt32(0) != WASM_MAGIC) + return null; + + // read version + if (view.ReadUInt32(4) != 1) + return null; + + using var stream = view.AsStream(); + using var reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true); + + stream.Position += 8; + + long metadataOffset = -1; + List sections = new List(); + + while (stream.Position < stream.Length) + { + WasmSectionId id = (WasmSectionId)reader.ReadByte(); + uint size = reader.ReadULEB128(); + sections.Add(new WasmSection(id, stream.Position, size, view)); + + if (id == WasmSectionId.Custom && size == 0) + { + break; + } + stream.Seek(size, SeekOrigin.Current); + } + + foreach (var section in sections) + { + if (section.Id != WasmSectionId.Data || metadataOffset > -1) + continue; + + stream.Seek(section.Offset, SeekOrigin.Begin); + + uint numSegments = reader.ReadULEB128(); + if (numSegments != 2) + continue; + + // skip the first segment + if (reader.ReadByte() != 1) + continue; + + long segmentLength = reader.ReadULEB128(); + long segmentStart = reader.BaseStream.Position; + + reader.BaseStream.Seek(segmentLength, SeekOrigin.Current); + + if (reader.ReadByte() != 1) + continue; + + segmentLength = reader.ReadULEB128(); + if (TryReadWebCilSegment(reader, out var header, out metadataOffset, out var webcilOffset, out var sectionHeaders)) + { + stream.Seek(metadataOffset, SeekOrigin.Begin); + var metadata = MetadataReaderProvider.FromMetadataStream(stream, MetadataStreamOptions.LeaveOpen | MetadataStreamOptions.PrefetchMetadata); + + var result = new WebCilFile(fileName, webcilOffset, metadataOffset, view, ImmutableArray.Create(sectionHeaders), sections.ToImmutableArray(), metadata, metadataOptions); + + view = null; // don't dispose the view, we're still using it in the sections + return result; + } + } + + return null; + } + finally + { + view?.Dispose(); + } + } + + static unsafe bool TryReadWebCilSegment(BinaryReader reader, out WebcilHeader webcilHeader, out long metadataOffset, out long webcilOffset, [NotNullWhen(true)] out SectionHeader[]? sectionHeaders) + { + webcilHeader = default; + metadataOffset = -1; + sectionHeaders = null; + + webcilOffset = reader.BaseStream.Position; + + if (reader.ReadUInt32() != WEBCIL_MAGIC) + return false; + + webcilHeader.VersionMajor = reader.ReadUInt16(); + webcilHeader.VersionMinor = reader.ReadUInt16(); + webcilHeader.CoffSections = reader.ReadUInt16(); + _ = reader.ReadUInt16(); // reserved0 + webcilHeader.PECliHeaderRVA = reader.ReadUInt32(); + webcilHeader.PECliHeaderSize = reader.ReadUInt32(); + webcilHeader.PEDebugRVA = reader.ReadUInt32(); + webcilHeader.PEDebugSize = reader.ReadUInt32(); + + sectionHeaders = new SectionHeader[webcilHeader.CoffSections]; + for (int i = 0; i < webcilHeader.CoffSections; i++) + { + sectionHeaders[i].VirtualSize = reader.ReadUInt32(); + sectionHeaders[i].VirtualAddress = reader.ReadUInt32(); + sectionHeaders[i].RawDataSize = reader.ReadUInt32(); + sectionHeaders[i].RawDataPtr = reader.ReadUInt32(); + } + + long corHeaderStart = TranslateRVA(sectionHeaders, webcilOffset, webcilHeader.PECliHeaderRVA); + if (reader.BaseStream.Seek(corHeaderStart, SeekOrigin.Begin) != corHeaderStart) + return false; + int byteCount = reader.ReadInt32(); + int majorVersion = reader.ReadUInt16(); + int minorVersion = reader.ReadUInt16(); + metadataOffset = TranslateRVA(sectionHeaders, webcilOffset, (uint)reader.ReadInt32()); + return reader.BaseStream.Seek(metadataOffset, SeekOrigin.Begin) == metadataOffset; + } + + public override int MetadataOffset { get; } + + private static int GetContainingSectionIndex(IEnumerable sections, int rva) + { + int i = 0; + foreach (var section in sections) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + return i; + } + i++; + } + return -1; + } + + private static long TranslateRVA(IEnumerable sections, long webcilOffset, uint rva) + { + foreach (var section in sections) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + return section.RawDataPtr + (rva - section.VirtualAddress) + webcilOffset; + } + } + throw new BadImageFormatException("RVA not found in any section"); + } + + public override MethodBodyBlock GetMethodBody(int rva) + { + var reader = GetSectionData(rva).GetReader(); + return MethodBodyBlock.Create(reader); + } + + public override int GetContainingSectionIndex(int rva) + { + return GetContainingSectionIndex(SectionHeaders, rva); + } + + public override unsafe SectionData GetSectionData(int rva) + { + foreach (var section in SectionHeaders) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + byte* ptr = (byte*)0; + view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); + return new SectionData(ptr + section.RawDataPtr + webcilOffset + (rva - section.VirtualAddress), (int)section.RawDataSize); + } + } + throw new BadImageFormatException("RVA not found in any section"); + } + + public override ImmutableArray SectionHeaders { get; } + + public ImmutableArray WasmSections { get; } + + IModule? IModuleReference.Resolve(ITypeResolveContext context) + { + return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); + } + + public void Dispose() + { + view.Dispose(); + } + + public struct WebcilHeader + { + public ushort VersionMajor; + public ushort VersionMinor; + public ushort CoffSections; + public uint PECliHeaderRVA; + public uint PECliHeaderSize; + public uint PEDebugRVA; + public uint PEDebugSize; + } + + const uint WASM_MAGIC = 0x6d736100u; // "\0asm" + const uint WEBCIL_MAGIC = 0x4c496257u; // "WbIL" + + [DebuggerDisplay("WasmSection {Id}: {Offset} {Size}")] + public class WasmSection + { + public WasmSectionId Id; + public long Offset; + public uint Size; + private MemoryMappedViewAccessor view; + + public WasmSection(WasmSectionId id, long offset, uint size, MemoryMappedViewAccessor view) + { + this.Id = id; + this.Size = size; + this.Offset = offset; + this.view = view; + } + } + + public enum WasmSectionId : byte + { + // order matters: enum values must match the WebAssembly spec + Custom = 0, + Type = 1, + Import = 2, + Function = 3, + Table = 4, + Memory = 5, + Global = 6, + Export = 7, + Start = 8, + Element = 9, + Code = 10, + Data = 11, + DataCount = 12, + } + } +} diff --git a/ICSharpCode.Decompiler/NRExtensions.cs b/ICSharpCode.Decompiler/NRExtensions.cs index 7d98e27b44..2d978a7778 100644 --- a/ICSharpCode.Decompiler/NRExtensions.cs +++ b/ICSharpCode.Decompiler/NRExtensions.cs @@ -94,7 +94,7 @@ public override IType VisitTypeDefinition(ITypeDefinition type) internal static string GetDocumentation(this IEntity entity) { - var docProvider = XmlDocLoader.LoadDocumentation(entity.ParentModule.PEFile); + var docProvider = XmlDocLoader.LoadDocumentation(entity.ParentModule.MetadataFile); if (docProvider == null) return null; return docProvider.GetDocumentation(entity); diff --git a/ICSharpCode.Decompiler/Output/ITextOutput.cs b/ICSharpCode.Decompiler/Output/ITextOutput.cs index c099df6092..db896fa863 100644 --- a/ICSharpCode.Decompiler/Output/ITextOutput.cs +++ b/ICSharpCode.Decompiler/Output/ITextOutput.cs @@ -34,7 +34,7 @@ public interface ITextOutput void Write(string text); void WriteLine(); void WriteReference(OpCodeInfo opCode, bool omitSuffix = false); - void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false); + void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false); void WriteReference(IType type, string text, bool isDefinition = false); void WriteReference(IMember member, string text, bool isDefinition = false); void WriteLocalReference(string text, object reference, bool isDefinition = false); diff --git a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs index 4daff8ffd9..2af592b931 100644 --- a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs +++ b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs @@ -123,7 +123,7 @@ public void WriteReference(Disassembler.OpCodeInfo opCode, bool omitSuffix = fal } } - public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) + public void WriteReference(MetadataFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) { Write(text); } @@ -225,7 +225,7 @@ public void WriteReference(OpCodeInfo opCode, bool omitSuffix = false) actions.Add(target => target.WriteReference(opCode)); } - public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) + public void WriteReference(MetadataFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) { actions.Add(target => target.WriteReference(module, handle, text, protocol, isDefinition)); } diff --git a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs index 3271d1034a..5472ee6d0b 100644 --- a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs +++ b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs @@ -1,10 +1,10 @@ public static class DecompilerVersionInfo { - public const string Major = "8"; - public const string Minor = "2"; + public const string Major = "9"; + public const string Minor = "0"; public const string Build = "0"; public const string Revision = "$INSERTREVISION$"; - public const string VersionName = null; + public const string VersionName = "preview1"; public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$"; public const string FullVersionWithShortCommitHash = FullVersion + "-$INSERTSHORTCOMMITHASH$"; diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index dff5dcef2d..750f49f42a 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Immutable; +using System.IO; +using System.IO.MemoryMappedFiles; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -624,7 +627,7 @@ internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataRea } #endregion - public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, + public static unsafe BlobReader GetInitialValue(this FieldDefinition field, MetadataFile pefile, ICompilation typeSystem) { if (!field.HasFlag(FieldAttributes.HasFieldRVA)) @@ -650,10 +653,10 @@ sealed class FieldValueSizeDecoder : ISignatureTypeProvider public FieldValueSizeDecoder(ICompilation typeSystem = null) { this.module = (MetadataModule)typeSystem?.MainModule; - if (module == null) + if (module?.MetadataFile is not PEFile pefile) this.pointerSize = IntPtr.Size; else - this.pointerSize = module.PEFile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; + this.pointerSize = pefile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; } public int GetArrayType(int elementType, ArrayShape shape) => @@ -710,7 +713,7 @@ public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handl var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition(); if (typeDef == null || typeDef.MetadataToken.IsNil) return 0; - reader = typeDef.ParentModule.PEFile.Metadata; + reader = typeDef.ParentModule.MetadataFile.Metadata; var td = reader.GetTypeDefinition((TypeDefinitionHandle)typeDef.MetadataToken); return td.GetLayout().Size; } @@ -747,5 +750,11 @@ public static string ToILSyntax(this SignatureCallingConvention callConv) _ => callConv.ToString().ToLowerInvariant() }; } + + public static UnmanagedMemoryStream AsStream(this MemoryMappedViewAccessor view) + { + long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength); + return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size); + } } } diff --git a/ICSharpCode.Decompiler/SingleFileBundle.cs b/ICSharpCode.Decompiler/SingleFileBundle.cs index c92af8b352..b898639edd 100644 --- a/ICSharpCode.Decompiler/SingleFileBundle.cs +++ b/ICSharpCode.Decompiler/SingleFileBundle.cs @@ -104,18 +104,12 @@ public struct Entry public string RelativePath; // Path of an embedded file, relative to the Bundle source-directory. } - static UnmanagedMemoryStream AsStream(MemoryMappedViewAccessor view) - { - long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength); - return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size); - } - /// /// Reads the manifest header from the memory mapping. /// public static Header ReadManifest(MemoryMappedViewAccessor view, long bundleHeaderOffset) { - using var stream = AsStream(view); + using var stream = view.AsStream(); stream.Seek(bundleHeaderOffset, SeekOrigin.Begin); return ReadManifest(stream); } diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 5a46088f68..536b00cacd 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -208,17 +208,17 @@ private DecompilerTypeSystem() { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver) : this(mainModule, assemblyResolver, TypeSystemOptions.Default) { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings) : this(mainModule, assemblyResolver, GetOptions(settings ?? throw new ArgumentNullException(nameof(settings)))) { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) { if (mainModule == null) throw new ArgumentNullException(nameof(mainModule)); @@ -232,16 +232,16 @@ public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolve "System.Runtime.CompilerServices.Unsafe" }; - private async Task InitializeAsync(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) + private async Task InitializeAsync(MetadataFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) { // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. - var referencedAssemblies = new List(); - var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference, Task ResolveTask)>(); - var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => + var referencedAssemblies = new List(); + var assemblyReferenceQueue = new Queue<(bool IsAssembly, MetadataFile MainModule, object Reference, Task ResolveTask)>(); + var comparer = KeyComparer.Create(((bool IsAssembly, MetadataFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); - var assemblyReferencesInQueue = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); + var assemblyReferencesInQueue = new HashSet<(bool IsAssembly, MetadataFile Parent, object Reference)>(comparer); var mainMetadata = mainModule.Metadata; var tfm = mainModule.DetectTargetFrameworkId(); var (identifier, version) = UniversalAssemblyResolver.ParseTargetFramework(tfm); @@ -334,13 +334,13 @@ private async Task InitializeAsync(PEFile mainModule, IAssemblyResolver assembly } this.mainModule = (MetadataModule)base.MainModule; - void AddToQueue(bool isAssembly, PEFile mainModule, object reference) + void AddToQueue(bool isAssembly, MetadataFile mainModule, object reference) { if (assemblyReferencesInQueue.Add((isAssembly, mainModule, reference))) { // Immediately start loading the referenced module as we add the entry to the queue. // This allows loading multiple modules in parallel. - Task asm; + Task asm; if (isAssembly) { asm = assemblyResolver.ResolveAsync((IAssemblyReference)reference); diff --git a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs index 9df4bf8a41..36712ee645 100644 --- a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs +++ b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs @@ -165,6 +165,22 @@ public string ReflectionName { } } + public string FullName { + get { + if (nestedTypes == null) + return topLevelType.Namespace + "." + topLevelType.Name; + StringBuilder b = new StringBuilder(topLevelType.Namespace); + b.Append('.'); + b.Append(topLevelType.Name); + foreach (NestedTypeName nt in nestedTypes) + { + b.Append('.'); + b.Append(nt.Name); + } + return b.ToString(); + } + } + /// /// Gets the total type parameter count. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs index b14a5566d7..d7845bc4b1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs @@ -54,7 +54,7 @@ public interface IModule : ISymbol, ICompilationProvider /// /// Gets the underlying metadata file. May return null, if the IAssembly was not created from a PE file. /// - PEFile? PEFile { get; } + MetadataFile? MetadataFile { get; } /// /// Gets whether this assembly is the main assembly of the compilation. diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index ee86a531d6..0232760718 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -168,14 +168,14 @@ public override bool Equals(object obj) { if (obj is MetadataEvent ev) { - return handle == ev.handle && module.PEFile == ev.module.PEFile; + return handle == ev.handle && module.MetadataFile == ev.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x7937039a ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x7937039a ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index d561e3be21..4486c90f54 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -299,14 +299,14 @@ public override bool Equals(object obj) { if (obj is MetadataField f) { - return handle == f.handle && module.PEFile == f.module.PEFile; + return handle == f.handle && module.MetadataFile == f.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x11dda32b ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x11dda32b ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index 7964a590ed..83946c9fa0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -64,7 +64,7 @@ internal MetadataMethod(MetadataModule module, MethodDefinitionHandle handle) this.attributes = def.Attributes; this.symbolKind = SymbolKind.Method; - var (accessorOwner, semanticsAttribute) = module.PEFile.MethodSemanticsLookup.GetSemantics(handle); + var (accessorOwner, semanticsAttribute) = module.MetadataFile.MethodSemanticsLookup.GetSemantics(handle); const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig); this.typeParameters = MetadataTypeParameter.Create(module, this, def.GetGenericParameters()); if (semanticsAttribute != 0 && !accessorOwner.IsNil @@ -606,14 +606,14 @@ public override bool Equals(object obj) { if (obj is MetadataMethod m) { - return handle == m.handle && module.PEFile == m.module.PEFile; + return handle == m.handle && module.MetadataFile == m.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x5a00d671 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x5a00d671 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 0dd339b994..da2d8a4cf6 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -267,7 +267,7 @@ Accessibility ComputeAccessibility() // "protected internal" (ProtectedOrInternal) accessibility is "reduced" // to "protected" accessibility across assembly boundaries. if (baseMember.Accessibility == Accessibility.ProtectedOrInternal - && this.ParentModule?.PEFile != baseMember.ParentModule?.PEFile) + && this.ParentModule?.MetadataFile != baseMember.ParentModule?.MetadataFile) { return Accessibility.Protected; } @@ -302,14 +302,14 @@ public override bool Equals(object obj) { if (obj is MetadataProperty p) { - return handle == p.handle && module.PEFile == p.module.PEFile; + return handle == p.handle && module.MetadataFile == p.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x32b6a76c ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x32b6a76c ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index 3eff3c1423..632a3e4cc7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -258,7 +258,7 @@ public IEnumerable Methods { var metadata = module.metadata; var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods(); var methodsList = new List(methodsCollection.Count); - var methodSemantics = module.PEFile.MethodSemanticsLookup; + var methodSemantics = module.MetadataFile.MethodSemanticsLookup; bool hasDefaultCtor = false; foreach (MethodDefinitionHandle h in methodsCollection) { @@ -553,14 +553,14 @@ public override bool Equals(object obj) { if (obj is MetadataTypeDefinition td) { - return handle == td.handle && module.PEFile == td.module.PEFile; + return handle == td.handle && module.MetadataFile == td.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x2e0520f2 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x2e0520f2 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IEquatable.Equals(IType other) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index 58bc4ca1b9..282e5c2bf9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -248,12 +248,12 @@ private IReadOnlyList DecodeConstraints() public override int GetHashCode() { - return 0x51fc5b83 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x51fc5b83 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } public override bool Equals(IType other) { - return other is MetadataTypeParameter tp && handle == tp.handle && module.PEFile == tp.module.PEFile; + return other is MetadataTypeParameter tp && handle == tp.handle && module.MetadataFile == tp.module.MetadataFile; } public override string ToString() diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs index 28737d6700..4f1b9cc8af 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs @@ -62,7 +62,7 @@ private MinimalCorlib(ICompilation compilation, IEnumerable string ISymbol.Name => "corlib"; SymbolKind ISymbol.SymbolKind => SymbolKind.Module; - Metadata.PEFile IModule.PEFile => null; + Metadata.MetadataFile IModule.MetadataFile => null; INamespace IModule.RootNamespace => rootNamespace; public IEnumerable TopLevelTypeDefinitions => typeDefinitions.Where(td => td != null); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs index 28a0f33b7e..9489194bf4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs @@ -95,6 +95,10 @@ public override string ReflectionName { get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; } } + public override string FullName { + get { return namespaceKnown ? fullTypeName.FullName : "?"; } + } + public FullTypeName FullTypeName => fullTypeName; public override int TypeParameterCount => fullTypeName.TypeParameterCount; diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index a7f4943736..bc7ff1bb43 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -51,10 +51,10 @@ public class MetadataModule : IModule readonly MetadataEvent[] eventDefs; readonly IModule[] referencedAssemblies; - internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options) + internal MetadataModule(ICompilation compilation, MetadataFile peFile, TypeSystemOptions options) { this.Compilation = compilation; - this.PEFile = peFile; + this.MetadataFile = peFile; this.metadata = peFile.Metadata; this.options = options; this.TypeProvider = new TypeProvider(this); @@ -112,8 +112,8 @@ internal string GetString(StringHandle name) public TypeSystemOptions TypeSystemOptions => options; - #region IAssembly interface - public PEFile PEFile { get; } + #region IModule interface + public MetadataFile MetadataFile { get; } public bool IsMainModule => this == Compilation.MainModule; @@ -129,10 +129,10 @@ internal string GetString(StringHandle name) public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) { - var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName); + var typeDefHandle = MetadataFile.GetTypeDefinition(topLevelTypeName); if (typeDefHandle.IsNil) { - var forwarderHandle = PEFile.GetTypeForwarder(topLevelTypeName); + var forwarderHandle = MetadataFile.GetTypeForwarder(topLevelTypeName); if (!forwarderHandle.IsNil) { var forwarder = metadata.GetExportedType(forwarderHandle); diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 3ce5d01805..e26781cfbf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -699,14 +699,14 @@ public static IType WithoutNullability(this IType type) public static bool IsDirectImportOf(this ITypeDefinition type, IModule module) { var moduleReference = type.ParentModule; - foreach (var asmRef in module.PEFile.AssemblyReferences) + foreach (var asmRef in module.MetadataFile.AssemblyReferences) { if (asmRef.FullName == moduleReference.FullAssemblyName) return true; if (asmRef.Name == "netstandard" && asmRef.GetPublicKeyToken() != null) { var referencedModule = module.Compilation.FindModuleByReference(asmRef); - if (referencedModule != null && !referencedModule.PEFile.GetTypeForwarder(type.FullTypeName).IsNil) + if (referencedModule != null && !referencedModule.MetadataFile.GetTypeForwarder(type.FullTypeName).IsNil) return true; } } diff --git a/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj b/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj index c97d0e6505..ca25d2eef7 100644 --- a/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj +++ b/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 true true true @@ -37,8 +37,6 @@ NU1605 - - @@ -49,9 +47,9 @@ - - - + + + diff --git a/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs b/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs index 425357cac2..57e08d5e38 100644 --- a/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs +++ b/ICSharpCode.ILSpyCmd/IlspyCmdProgram.cs @@ -24,8 +24,6 @@ using Microsoft.Extensions.Hosting; -using NuGet.Versioning; - namespace ICSharpCode.ILSpyCmd { [Command(Name = "ilspycmd", Description = "dotnet tool for decompiling .NET assemblies and generating portable PDBs", @@ -314,7 +312,7 @@ ProjectId DecompileAsProject(string assemblyFileName, string projectFileName) { resolver.AddSearchDirectory(path); } - var decompiler = new WholeProjectDecompiler(GetSettings(module), resolver, resolver, TryLoadPDB(module)); + var decompiler = new WholeProjectDecompiler(GetSettings(module), resolver, null, resolver, TryLoadPDB(module)); using (var projectFileWriter = new StreamWriter(File.OpenWrite(projectFileName))) return decompiler.DecompileProject(module, Path.GetDirectoryName(projectFileName), projectFileWriter); } diff --git a/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs b/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs index 1947b0cc3f..f05c6ded3a 100644 --- a/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs +++ b/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -24,7 +26,8 @@ namespace ICSharpCode.ILSpyX.Abstractions public interface ILanguage { bool ShowMember(IEntity member); - string GetEntityName(PEFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics); + CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member); + string GetEntityName(MetadataFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics); string GetTooltip(IEntity entity); string TypeToString(IType type, bool includeNamespace); diff --git a/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs b/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs index 836e43e221..b3732ae78a 100644 --- a/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs +++ b/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs @@ -38,7 +38,7 @@ public interface IResourcesFileTreeNode : ITreeNode public interface ITreeNodeFactory { - ITreeNode CreateResourcesList(PEFile module); + ITreeNode CreateResourcesList(MetadataFile module); ITreeNode Create(Resource resource); } } diff --git a/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs new file mode 100644 index 0000000000..09112056f4 --- /dev/null +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerContext.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Concurrent; +using System.Reflection.Metadata; +using System.Threading; + +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX.Abstractions; + +namespace ICSharpCode.ILSpyX.Analyzers +{ + /// + /// Provides additional context for analyzers. + /// + public class AnalyzerContext + { + public required AssemblyList AssemblyList { get; init; } + + /// + /// CancellationToken. Currently Analyzers do not support cancellation from the UI, but it should be checked nonetheless. + /// + public CancellationToken CancellationToken { get; init; } + + /// + /// Currently used language. + /// + public required ILanguage Language { get; init; } + +/// +/// Allows the analyzer to control whether the tree nodes will be sorted. +/// Must be set within +/// before the results are enumerated. +/// +public bool SortResults { get; set; } + +public MethodBodyBlock? GetMethodBody(IMethod method) +{ + if (!method.HasBody || method.MetadataToken.IsNil || method.ParentModule?.MetadataFile == null) + return null; + var module = method.ParentModule.MetadataFile; + var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); + try + { + return module.GetMethodBody(md.RelativeVirtualAddress); + } + catch (BadImageFormatException) + { + return null; + } +} + +public AnalyzerScope GetScopeOf(IEntity entity) +{ + return new AnalyzerScope(AssemblyList, entity); +} + +readonly ConcurrentDictionary typeSystemCache = new(); + +public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module) +{ + return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); +} + } +} diff --git a/ILSpy/Analyzers/AnalyzerHelpers.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs similarity index 91% rename from ILSpy/Analyzers/AnalyzerHelpers.cs rename to ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs index 9126dd6151..4c5217ef6a 100644 --- a/ILSpy/Analyzers/AnalyzerHelpers.cs +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerHelpers.cs @@ -21,11 +21,11 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers +namespace ICSharpCode.ILSpyX.Analyzers { internal static class AnalyzerHelpers { - public static bool IsPossibleReferenceTo(EntityHandle member, PEFile module, IMethod analyzedMethod) + public static bool IsPossibleReferenceTo(EntityHandle member, MetadataFile module, IMethod analyzedMethod) { if (member.IsNil) return false; @@ -34,7 +34,7 @@ public static bool IsPossibleReferenceTo(EntityHandle member, PEFile module, IMe { case HandleKind.MethodDefinition: return member == analyzedMethod.MetadataToken - && module == analyzedMethod.ParentModule.PEFile; + && module == analyzedMethod.ParentModule?.MetadataFile; case HandleKind.MemberReference: var mr = metadata.GetMemberReference((MemberReferenceHandle)member); if (mr.GetKind() != MemberReferenceKind.Method) @@ -48,9 +48,9 @@ public static bool IsPossibleReferenceTo(EntityHandle member, PEFile module, IMe } } - public static ISymbol GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute) + public static ISymbol? GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute) { - var metadata = ts.MainModule.PEFile.Metadata; + var metadata = ts.MainModule.MetadataFile.Metadata; switch (customAttribute.Parent.Kind) { case HandleKind.MethodDefinition: diff --git a/ILSpy/Analyzers/AnalyzerScope.cs b/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs similarity index 76% rename from ILSpy/Analyzers/AnalyzerScope.cs rename to ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs index 6377549b2e..8f01faf0f7 100644 --- a/ILSpy/Analyzers/AnalyzerScope.cs +++ b/ICSharpCode.ILSpyX/Analyzers/AnalyzerScope.cs @@ -24,9 +24,8 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; -using ICSharpCode.ILSpyX; -namespace ICSharpCode.ILSpy.Analyzers +namespace ICSharpCode.ILSpyX.Analyzers { using ICSharpCode.Decompiler.TypeSystem; @@ -54,38 +53,29 @@ public AnalyzerScope(AssemblyList assemblyList, IEntity entity) AssemblyList = assemblyList; assemblyListSnapshot = assemblyList.GetSnapshot(); AnalyzedSymbol = entity; - if (entity is ITypeDefinition type) - { - typeScope = type; - effectiveAccessibility = DetermineEffectiveAccessibility(ref typeScope, Accessibility.Public); - } - else - { - typeScope = entity.DeclaringTypeDefinition; - effectiveAccessibility = DetermineEffectiveAccessibility(ref typeScope, entity.Accessibility); - } + DetermineEffectiveAccessibility(entity, out typeScope, out effectiveAccessibility); IsLocal = effectiveAccessibility.LessThanOrEqual(Accessibility.Private); } - public IEnumerable GetModulesInScope(CancellationToken ct) + public IEnumerable GetModulesInScope(CancellationToken ct) { if (IsLocal) - return new[] { TypeScope.ParentModule.PEFile }; + return new[] { TypeScope.ParentModule!.MetadataFile! }; if (effectiveAccessibility.LessThanOrEqual(Accessibility.Internal)) return GetModuleAndAnyFriends(TypeScope, ct); - return GetReferencingModules(TypeScope.ParentModule.PEFile, ct); + return GetReferencingModules(TypeScope.ParentModule!.MetadataFile!, ct); } - public IEnumerable GetAllModules() + public IEnumerable GetAllModules() { return assemblyListSnapshot.GetAllAssembliesAsync().GetAwaiter().GetResult() - .Select(asm => asm.GetPEFileOrNull()) - .Where(x => x != null); + .Select(asm => asm.GetMetadataFileOrNull()) + .Where(x => x != null)!; } - public DecompilerTypeSystem ConstructTypeSystem(PEFile module) + public DecompilerTypeSystem ConstructTypeSystem(MetadataFile module) { return new DecompilerTypeSystem(module, module.GetAssemblyResolver(assemblyListSnapshot, loadOnDemand: false)); } @@ -112,24 +102,36 @@ public IEnumerable GetTypesInScope(CancellationToken ct) } } - static Accessibility DetermineEffectiveAccessibility(ref ITypeDefinition typeScope, Accessibility memberAccessibility) + static void DetermineEffectiveAccessibility(IEntity input, out ITypeDefinition typeScope, out Accessibility accessibility) { - Accessibility accessibility = memberAccessibility; - var ts = typeScope; - while (ts != null && !accessibility.LessThanOrEqual(Accessibility.Private)) + if (input is ITypeDefinition td) + { + accessibility = Accessibility.Public; + typeScope = td; + } + else { - accessibility = accessibility.Intersect(ts.Accessibility); - typeScope = ts; - ts = ts.DeclaringTypeDefinition; + accessibility = input.Accessibility; + typeScope = input.DeclaringTypeDefinition!; } // Once we reach a private entity, we leave the loop with typeScope set to the class that // contains the private entity = the scope that needs to be searched. // Otherwise (if we don't find a private entity) we return the top-level class. - return accessibility; + var prevTypeScope = typeScope; + while (typeScope != null && !accessibility.LessThanOrEqual(Accessibility.Private)) + { + accessibility = accessibility.Intersect(typeScope.Accessibility); + prevTypeScope = typeScope; + typeScope = prevTypeScope.DeclaringTypeDefinition!; + } + if (typeScope == null) + { + typeScope = prevTypeScope; + } } #region Find modules - IEnumerable GetReferencingModules(PEFile self, CancellationToken ct) + IEnumerable GetReferencingModules(MetadataFile self, CancellationToken ct) { yield return self; @@ -137,8 +139,8 @@ IEnumerable GetReferencingModules(PEFile self, CancellationToken ct) if (typeScope.TypeParameterCount > 0) reflectionTypeScopeName += "`" + typeScope.TypeParameterCount; - var toWalkFiles = new Stack(); - var checkedFiles = new HashSet(); + var toWalkFiles = new Stack(); + var checkedFiles = new HashSet(); toWalkFiles.Push(self); checkedFiles.Add(self); @@ -146,12 +148,12 @@ IEnumerable GetReferencingModules(PEFile self, CancellationToken ct) do { - PEFile curFile = toWalkFiles.Pop(); + MetadataFile curFile = toWalkFiles.Pop(); foreach (var assembly in assemblies) { ct.ThrowIfCancellationRequested(); bool found = false; - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null || !module.IsAssembly) continue; if (checkedFiles.Contains(module)) @@ -176,9 +178,9 @@ IEnumerable GetReferencingModules(PEFile self, CancellationToken ct) } while (toWalkFiles.Count > 0); } - IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct) + IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct) { - var self = typeScope.ParentModule.PEFile; + var self = typeScope.ParentModule!.MetadataFile!; yield return self; @@ -188,9 +190,10 @@ IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, Cancellati var friendAssemblies = new HashSet(); foreach (var attribute in attributes) { - string assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string; - assemblyName = assemblyName.Split(',')[0]; // strip off any public key info - friendAssemblies.Add(assemblyName); + string? assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string; + assemblyName = assemblyName?.Split(',')[0]; // strip off any public key info + if (assemblyName != null) + friendAssemblies.Add(assemblyName); } if (friendAssemblies.Count > 0) @@ -203,7 +206,7 @@ IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, Cancellati ct.ThrowIfCancellationRequested(); if (friendAssemblies.Contains(assembly.ShortName)) { - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null) continue; if (ModuleReferencesScopeType(module.Metadata, typeScope.Name, typeScope.Namespace)) diff --git a/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs similarity index 99% rename from ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs index 6007253a60..fa925c9b43 100644 --- a/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs @@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { [ExportAnalyzer(Header = "Applied To", Order = 10)] class AttributeAppliedToAnalyzer : IAnalyzer diff --git a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs index 4e87a0f30d..e928f531a5 100644 --- a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventImplementedByAnalyzer.cs @@ -17,13 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows events that implement an interface event. @@ -44,17 +43,19 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IEvent analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var @event in type.Events) { var baseMembers = InheritanceHelper.GetBaseMembers(@event, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module)) yield return @event; } } diff --git a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs index f6c41dc184..5db8f0841b 100644 --- a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/EventOverriddenByAnalyzer.cs @@ -17,13 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows events that override an event. @@ -44,11 +43,13 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IEvent analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var @event in type.Events) @@ -56,7 +57,7 @@ IEnumerable AnalyzeType(IEvent analyzedEntity, ITypeDefinition type) if (!@event.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(@event, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module)) { yield return @event; } diff --git a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs index 38228bc721..ba829b0fc2 100644 --- a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/FieldAccessAnalyzer.cs @@ -17,24 +17,19 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; -using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpy.Analyzers; using ILOpCode = System.Reflection.Metadata.ILOpCode; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Finds methods where this field is read. @@ -79,7 +74,9 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var scope = context.GetScopeOf((IEntity)analyzedSymbol); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { - var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); + if (type.ParentModule?.MetadataFile == null) + continue; + var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -124,9 +121,9 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont bool IsUsedInMethod(IField analyzedField, IMethod method, CodeMappingInfo mappingInfo, AnalyzerContext context) { - if (method.MetadataToken.IsNil) + if (method.MetadataToken.IsNil || method.ParentModule?.MetadataFile == null) return false; - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; foreach (var part in mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken)) { var md = module.Metadata.GetMethodDefinition(part); @@ -135,7 +132,7 @@ bool IsUsedInMethod(IField analyzedField, IMethod method, CodeMappingInfo mappin MethodBodyBlock body; try { - body = module.Reader.GetMethodBody(md.RelativeVirtualAddress); + body = module.GetMethodBody(md.RelativeVirtualAddress); } catch (BadImageFormatException) { @@ -149,7 +146,7 @@ bool IsUsedInMethod(IField analyzedField, IMethod method, CodeMappingInfo mappin bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock methodBody) { - if (methodBody == null) + if (methodBody == null || method.ParentModule?.MetadataFile == null) return false; var mainModule = (MetadataModule)method.ParentModule; @@ -175,7 +172,7 @@ bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock method EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (!fieldHandle.Kind.IsMemberKind()) continue; - IField field; + IField? field; try { field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField; @@ -188,7 +185,7 @@ bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock method continue; if (field.MetadataToken == analyzedField.MetadataToken - && field.ParentModule.PEFile == analyzedField.ParentModule.PEFile) + && field.ParentModule?.MetadataFile == analyzedField.ParentModule!.MetadataFile) return true; } diff --git a/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs similarity index 94% rename from ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs index 1431e3cee3..0b7e0f0275 100644 --- a/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { public enum TokenSearchResult : byte { @@ -54,7 +54,7 @@ public enum TokenSearchResult : byte class FindTypeInAttributeDecoder : ICustomAttributeTypeProvider { - readonly PEFile declaringModule; + readonly MetadataFile declaringModule; readonly MetadataModule currentModule; readonly TypeDefinitionHandle handle; readonly PrimitiveTypeCode primitiveType; @@ -65,7 +65,7 @@ class FindTypeInAttributeDecoder : ICustomAttributeTypeProvider /// Shows members from all corresponding interfaces the selected member implements. @@ -38,7 +38,7 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont Debug.Assert(!member.IsStatic); var baseMembers = InheritanceHelper.GetBaseMembers(member, includeImplementedInterfaces: true); - return baseMembers.Where(m => m.DeclaringTypeDefinition.Kind == TypeKind.Interface); + return baseMembers.Where(m => m.DeclaringTypeDefinition?.Kind == TypeKind.Interface); } public bool Show(ISymbol symbol) diff --git a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs index db9073e2a7..89da791ed6 100644 --- a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodImplementedByAnalyzer.cs @@ -16,17 +16,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows methods that implement an interface method. @@ -47,17 +43,19 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IMethod analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var method in type.Methods) { var baseMembers = InheritanceHelper.GetBaseMembers(method, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module)) yield return method; } } diff --git a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs index 7a90f48fa6..ab9c4fe71f 100644 --- a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs @@ -17,13 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows methods that override a method. @@ -46,11 +45,13 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IMethod analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var method in type.Methods) @@ -58,7 +59,7 @@ IEnumerable AnalyzeType(IMethod analyzedEntity, ITypeDefinition type) if (!method.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(method, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module)) { yield return method; } diff --git a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs similarity index 89% rename from ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs index a2b698080b..702d77a7d9 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsedByAnalyzer.cs @@ -18,17 +18,15 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; -using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows entities that are used by a method. @@ -46,9 +44,11 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var analyzedMethod = (IMethod)analyzedSymbol; var analyzedBaseMethod = (IMethod)InheritanceHelper.GetBaseMember(analyzedMethod); + if (analyzedMethod.ParentModule?.MetadataFile == null) + yield break; var mapping = context.Language - .GetCodeMappingInfo(analyzedMethod.ParentModule.PEFile, - analyzedMethod.DeclaringTypeDefinition.MetadataToken); + .GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile, + analyzedMethod.DeclaringTypeDefinition!.MetadataToken); var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken); if (parentMethod != analyzedMethod.MetadataToken) @@ -57,6 +57,8 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var scope = context.GetScopeOf(analyzedMethod); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + if (type.ParentModule?.MetadataFile == null) + continue; var parentModule = (MetadataModule)type.ParentModule; mapping = null; var methods = type.GetMembers(m => m is IMethod, Options).OfType(); @@ -64,7 +66,7 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont { if (IsUsedInMethod(analyzedMethod, analyzedBaseMethod, method, context)) { - mapping ??= context.Language.GetCodeMappingInfo(parentModule.PEFile, type.MetadataToken); + mapping ??= context.Language.GetCodeMappingInfo(parentModule.MetadataFile, type.MetadataToken); var parent = mapping.GetParentMethod((MethodDefinitionHandle)method.MetadataToken); yield return parentModule.GetDefinition(parent); } @@ -110,9 +112,9 @@ bool IsUsedInMethod(IMethod analyzedEntity, IMethod analyzedBaseMethod, IMethod return ScanMethodBody(analyzedEntity, method, analyzedBaseMethod, context.GetMethodBody(method)); } - static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analyzedBaseMethod, MethodBodyBlock methodBody) + static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analyzedBaseMethod, MethodBodyBlock? methodBody) { - if (methodBody == null) + if (methodBody == null || method.ParentModule?.MetadataFile == null) return false; var mainModule = (MetadataModule)method.ParentModule; @@ -137,15 +139,15 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, IMethod analy return false; // unexpected end of blob } var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (!AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.PEFile, analyzedMethod)) + if (!AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.MetadataFile, analyzedMethod)) { - if (analyzedBaseMethod == null || !AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.PEFile, analyzedBaseMethod)) + if (analyzedBaseMethod == null || !AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.MetadataFile, analyzedBaseMethod)) { continue; } } - IMember m; + IMember? m; try { m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; @@ -192,7 +194,7 @@ static bool IsSupportedOpCode(ILOpCode opCode) static bool IsSameMember(IMember analyzedMethod, IMember m) { return m.MetadataToken == analyzedMethod.MetadataToken - && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile; + && m.ParentModule?.MetadataFile == analyzedMethod.ParentModule!.MetadataFile; } } } diff --git a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs similarity index 89% rename from ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs index c3e8924199..2b361ec000 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodUsesAnalyzer.cs @@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows entities that are used by a method. @@ -38,10 +38,10 @@ class MethodUsesAnalyzer : IAnalyzer public IEnumerable Analyze(ISymbol symbol, AnalyzerContext context) { - if (symbol is IMethod method) + if (symbol is IMethod method && method.ParentModule?.MetadataFile is MetadataFile corFile) { - var typeSystem = context.GetOrCreateTypeSystem(method.ParentModule.PEFile); - return context.Language.GetCodeMappingInfo(method.ParentModule.PEFile, method.MetadataToken) + var typeSystem = context.GetOrCreateTypeSystem(corFile); + return context.Language.GetCodeMappingInfo(corFile, method.MetadataToken) .GetMethodParts((MethodDefinitionHandle)method.MetadataToken) .SelectMany(h => ScanMethod(h, typeSystem)).Distinct(); } @@ -51,14 +51,14 @@ public IEnumerable Analyze(ISymbol symbol, AnalyzerContext context) IEnumerable ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSystem typeSystem) { var module = typeSystem.MainModule; - var md = module.PEFile.Metadata.GetMethodDefinition(handle); + var md = module.MetadataFile.Metadata.GetMethodDefinition(handle); if (!md.HasBody()) yield break; BlobReader blob; try { - blob = module.PEFile.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); + blob = module.MetadataFile.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); } catch (BadImageFormatException) { @@ -95,7 +95,7 @@ IEnumerable ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSys case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: - IType ty; + IType? ty; try { ty = module.ResolveType(member, genericContext); @@ -110,7 +110,7 @@ IEnumerable ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSys case HandleKind.MethodSpecification: case HandleKind.MemberReference: case HandleKind.FieldDefinition: - IEntity m; + IEntity? m; try { m = module.ResolveEntity(member, genericContext); diff --git a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs similarity index 86% rename from ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs index bf806416c2..a24787a880 100644 --- a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows entities that are used by a method. @@ -41,9 +41,16 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont { Debug.Assert(analyzedSymbol is IMethod); var analyzedMethod = (IMethod)analyzedSymbol; + + if (analyzedMethod.ParentModule?.MetadataFile == null) + yield break; + + if (analyzedMethod.DeclaringTypeDefinition?.MetadataToken.IsNil != true) + yield break; + var mapping = context.Language - .GetCodeMappingInfo(analyzedMethod.ParentModule.PEFile, - analyzedMethod.DeclaringTypeDefinition.MetadataToken); + .GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile, + analyzedMethod.DeclaringTypeDefinition?.MetadataToken ?? default); var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken); if (parentMethod != analyzedMethod.MetadataToken) @@ -52,8 +59,10 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var scope = context.GetScopeOf(analyzedMethod); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { - var parentModule = (MetadataModule)type.ParentModule; - mapping = context.Language.GetCodeMappingInfo(parentModule.PEFile, type.MetadataToken); + var parentModule = (MetadataModule?)type.ParentModule; + if (parentModule?.MetadataFile == null) + continue; + mapping = context.Language.GetCodeMappingInfo(parentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -105,9 +114,9 @@ bool IsUsedInMethod(IMethod analyzedEntity, IMethod method, AnalyzerContext cont return ScanMethodBody(analyzedEntity, method, context.GetMethodBody(method)); } - static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlock methodBody) + static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlock? methodBody) { - if (methodBody == null) + if (methodBody == null || method.ParentModule?.MetadataFile == null) return false; var mainModule = (MetadataModule)method.ParentModule; var blob = methodBody.GetILReader(); @@ -131,7 +140,7 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo case HandleKind.MethodSpecification: case HandleKind.MemberReference: var m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; - if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile) + if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule?.MetadataFile == analyzedMethod.ParentModule!.MetadataFile) { return true; } diff --git a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs index 2b8cb8f845..4188822f40 100644 --- a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs @@ -17,13 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows properties that implement an interface property. @@ -44,17 +43,19 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IProperty analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var property in type.Properties) { var baseMembers = InheritanceHelper.GetBaseMembers(property, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule?.MetadataFile == module)) yield return property; } } diff --git a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs similarity index 91% rename from ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs index 7ec8b5cee5..1eb0d4a004 100644 --- a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs @@ -16,17 +16,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows properties that override a property. @@ -47,11 +43,13 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont IEnumerable AnalyzeType(IProperty analyzedEntity, ITypeDefinition type) { + if (analyzedEntity.DeclaringTypeDefinition?.ParentModule?.MetadataFile == null) + yield break; var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule?.MetadataFile == module)) yield break; foreach (var property in type.Properties) @@ -59,7 +57,7 @@ IEnumerable AnalyzeType(IProperty analyzedEntity, ITypeDefinition type) if (!property.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(property, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule?.MetadataFile == module)) { yield return property; } diff --git a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs similarity index 94% rename from ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs index 2b91096385..3f4fd59b21 100644 --- a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExposedByAnalyzer.cs @@ -16,16 +16,11 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { using ICSharpCode.Decompiler.TypeSystem; @@ -52,7 +47,7 @@ IEnumerable ScanType(ITypeDefinition analyzedType, ITypeDefinition type { if (analyzedType.Kind == TypeKind.Enum && type.MetadataToken == analyzedType.MetadataToken - && type.ParentModule.PEFile == analyzedType.ParentModule.PEFile) + && type.ParentModule?.MetadataFile == analyzedType.ParentModule?.MetadataFile) yield break; if (!context.Language.ShowMember(type)) diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs new file mode 100644 index 0000000000..b557110212 --- /dev/null +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs @@ -0,0 +1,66 @@ +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Diagnostics; + +using ICSharpCode.Decompiler.TypeSystem; + +namespace ICSharpCode.ILSpyX.Analyzers.Builtin +{ + /// + /// Finds all extension methods defined for a type. + /// + [ExportAnalyzer(Header = "Extension Methods", Order = 50)] + class TypeExtensionMethodsAnalyzer : IAnalyzer + { + public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic; + + public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context) + { + Debug.Assert(analyzedSymbol is ITypeDefinition); + var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { + foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context)) + yield return result; + } + } + + IEnumerable ScanType(ITypeDefinition analyzedType, ITypeDefinition type, AnalyzerContext context) + { + if (!type.HasExtensionMethods) + yield break; + + if (analyzedType.ParentModule?.MetadataFile == null) + yield break; + + foreach (IMethod method in type.Methods) + { + if (!method.IsExtensionMethod) + continue; + + var firstParamType = method.Parameters[0].Type.GetDefinition(); + if (firstParamType != null && + firstParamType.MetadataToken == analyzedType.MetadataToken && + firstParamType.ParentModule?.MetadataFile == analyzedType.ParentModule.MetadataFile) + yield return method; + } + } + } +} diff --git a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs similarity index 93% rename from ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs index cd5b68f1f6..603f3e5b0f 100644 --- a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs @@ -18,19 +18,16 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows methods that instantiate a type. @@ -46,7 +43,9 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { - var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); + if (type.ParentModule?.MetadataFile == null) + continue; + var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -94,9 +93,9 @@ bool IsUsedInMethod(ITypeDefinition analyzedEntity, IMethod method, CodeMappingI return ScanMethodBody(analyzedEntity, method, context.GetMethodBody(method)); } - bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock methodBody) + bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock? methodBody) { - if (methodBody == null) + if (methodBody == null || method.ParentModule?.MetadataFile == null) return false; var blob = methodBody.GetILReader(); var module = (MetadataModule)method.ParentModule; @@ -134,7 +133,7 @@ bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBl continue; if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken - && ctor.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile) + && ctor.ParentModule?.MetadataFile == analyzedEntity.ParentModule!.MetadataFile) return true; } diff --git a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs similarity index 95% rename from ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs rename to ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs index ef7ef3fee6..e4a10801f2 100644 --- a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/TypeUsedByAnalyzer.cs @@ -28,7 +28,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy.Analyzers.Builtin +namespace ICSharpCode.ILSpyX.Analyzers.Builtin { /// /// Shows entities that use a type. @@ -47,7 +47,7 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont .AsParallel().AsOrdered() .SelectMany(AnalyzeModuleAndFilter); - IEnumerable AnalyzeModuleAndFilter(PEFile module) + IEnumerable AnalyzeModuleAndFilter(MetadataFile module) { return AnalyzeModule(analyzedType, scope, module) .Distinct() @@ -55,7 +55,7 @@ IEnumerable AnalyzeModuleAndFilter(PEFile module) } } - static IEnumerable AnalyzeModule(ITypeDefinition analyzedType, AnalyzerScope scope, PEFile module) + static IEnumerable AnalyzeModule(ITypeDefinition analyzedType, AnalyzerScope scope, MetadataFile module) { var metadata = module.Metadata; var typeSystem = scope.ConstructTypeSystem(module); @@ -107,7 +107,7 @@ static IEnumerable AnalyzeModule(ITypeDefinition analyzedType, Analyzer if (found || ScanMethodBody(analyzedType, module, md, decoder)) { var method = typeSystem.MainModule.GetDefinition(h); - yield return method?.AccessorOwner ?? method; + yield return method.AccessorOwner ?? method; } } @@ -221,7 +221,7 @@ private static bool AnalyzeCustomAttributeValue(CustomAttributeValue /// Base interface for all analyzers. You can register an analyzer for any by implementing diff --git a/ICSharpCode.ILSpyX/AssemblyList.cs b/ICSharpCode.ILSpyX/AssemblyList.cs index 90123d6432..b52e791173 100644 --- a/ICSharpCode.ILSpyX/AssemblyList.cs +++ b/ICSharpCode.ILSpyX/AssemblyList.cs @@ -23,7 +23,6 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -31,6 +30,7 @@ using System.Xml.Linq; using ICSharpCode.ILSpyX.Extensions; +using ICSharpCode.ILSpyX.FileLoaders; namespace ICSharpCode.ILSpyX { @@ -129,6 +129,7 @@ public event NotifyCollectionChangedEventHandler CollectionChanged { public bool ApplyWinRTProjections { get; set; } public bool UseDebugSymbols { get; set; } + public FileLoaderRegistry LoaderRegistry => this.manager.LoaderRegistry; /// /// Gets the loaded assemblies. This method is thread-safe. @@ -280,7 +281,7 @@ public LoadedAssembly OpenAssembly(string file, bool isAutoLoaded = false) { file = Path.GetFullPath(file); return OpenAssembly(file, () => { - var newAsm = new LoadedAssembly(this, file, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); + var newAsm = new LoadedAssembly(this, file, fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = isAutoLoaded; return newAsm; }); @@ -294,6 +295,7 @@ public LoadedAssembly OpenAssembly(string file, Stream? stream, bool isAutoLoade file = Path.GetFullPath(file); return OpenAssembly(file, () => { var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream), + fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = isAutoLoaded; return newAsm; @@ -346,6 +348,7 @@ LoadedAssembly OpenAssembly(string file, Func load) return null; var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream), + fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = target.IsAutoLoaded; @@ -375,6 +378,7 @@ LoadedAssembly OpenAssembly(string file, Func load) if (index < 0) return null; var newAsm = new LoadedAssembly(this, target.FileName, pdbFileName: target.PdbFileName, + fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = target.IsAutoLoaded; lock (lockObj) @@ -395,6 +399,16 @@ public void Unload(LoadedAssembly assembly) } } + public void Clear() + { + VerifyAccess(); + lock (lockObj) + { + dirty = true; + assemblies.Clear(); + byFilename.Clear(); + } + } public void Sort(IComparer comparer) { Sort(0, int.MaxValue, comparer); diff --git a/ICSharpCode.ILSpyX/AssemblyListManager.cs b/ICSharpCode.ILSpyX/AssemblyListManager.cs index 5791ee8d08..83f264f6d0 100644 --- a/ICSharpCode.ILSpyX/AssemblyListManager.cs +++ b/ICSharpCode.ILSpyX/AssemblyListManager.cs @@ -23,6 +23,7 @@ using System.Xml.Linq; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.ILSpyX.FileLoaders; using ICSharpCode.ILSpyX.Settings; namespace ICSharpCode.ILSpyX @@ -59,6 +60,8 @@ public AssemblyListManager(ISettingsProvider settingsProvider) public ObservableCollection AssemblyLists { get; } = new ObservableCollection(); + public FileLoaderRegistry LoaderRegistry { get; } = new FileLoaderRegistry(); + /// /// Loads an assembly list from the ILSpySettings. /// If no list with the specified name is found, the default list is loaded instead. diff --git a/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs index 7f6821eda0..485a52a08b 100644 --- a/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs +++ b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs @@ -27,15 +27,16 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpyX.Extensions; +using ICSharpCode.ILSpyX.FileLoaders; namespace ICSharpCode.ILSpyX { class AssemblyListSnapshot { readonly ImmutableArray assemblies; - Dictionary? asmLookupByFullName; - Dictionary? asmLookupByShortName; - Dictionary>? asmLookupByShortNameGrouped; + Dictionary? asmLookupByFullName; + Dictionary? asmLookupByShortName; + Dictionary>? asmLookupByShortNameGrouped; public ImmutableArray Assemblies => assemblies; public AssemblyListSnapshot(ImmutableArray assemblies) @@ -43,7 +44,7 @@ public AssemblyListSnapshot(ImmutableArray assemblies) this.assemblies = assemblies; } - public async Task TryGetModuleAsync(IAssemblyReference reference, string tfm) + public async Task TryGetModuleAsync(IAssemblyReference reference, string tfm) { bool isWinRT = reference.IsWindowsRuntime; if (tfm.StartsWith(".NETFramework,Version=v4.", StringComparison.Ordinal)) @@ -57,12 +58,12 @@ public AssemblyListSnapshot(ImmutableArray assemblies) lookup = await CreateLoadedAssemblyLookupAsync(shortNames: isWinRT).ConfigureAwait(false); lookup = LazyInit.GetOrSet(ref isWinRT ? ref asmLookupByShortName : ref asmLookupByFullName, lookup); } - if (lookup.TryGetValue(key, out PEFile? module)) + if (lookup.TryGetValue(key, out MetadataFile? module)) return module; return null; } - public async Task TryGetSimilarModuleAsync(IAssemblyReference reference) + public async Task TryGetSimilarModuleAsync(IAssemblyReference reference) { var lookup = LazyInit.VolatileRead(ref asmLookupByShortNameGrouped); if (lookup == null) @@ -76,14 +77,14 @@ public AssemblyListSnapshot(ImmutableArray assemblies) return candidates.FirstOrDefault(c => c.version >= reference.Version).module ?? candidates.Last().module; } - private async Task> CreateLoadedAssemblyLookupAsync(bool shortNames) + private async Task> CreateLoadedAssemblyLookupAsync(bool shortNames) { - var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (LoadedAssembly loaded in assemblies) { try { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); if (module == null) continue; var reader = module.Metadata; @@ -109,15 +110,15 @@ private async Task> CreateLoadedAssemblyLookupAsync(b return result; } - private async Task>> CreateLoadedAssemblyShortNameGroupLookupAsync() + private async Task>> CreateLoadedAssemblyShortNameGroupLookupAsync() { - var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); + var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (LoadedAssembly loaded in assemblies) { try { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); var reader = module?.Metadata; if (reader == null || !reader.IsAssembly) continue; @@ -128,7 +129,7 @@ private async Task> CreateLoadedAssemblyLookupAsync(b if (!result.TryGetValue(asmDefName, out var existing)) { - existing = new List<(PEFile module, Version version)>(); + existing = new List<(MetadataFile module, Version version)>(); result.Add(asmDefName, existing); existing.Add(line); continue; @@ -156,7 +157,7 @@ public async Task> GetAllAssembliesAsync() foreach (var asm in assemblies) { - LoadedAssembly.LoadResult result; + LoadResult result; try { result = await asm.GetLoadResultAsync().ConfigureAwait(false); @@ -170,7 +171,7 @@ public async Task> GetAllAssembliesAsync() { AddDescendants(result.Package.RootFolder); } - else if (result.PEFile != null) + else if (result.MetadataFile != null) { results.Add(asm); } diff --git a/ICSharpCode.ILSpyX/FileLoaders/ArchiveFileLoader.cs b/ICSharpCode.ILSpyX/FileLoaders/ArchiveFileLoader.cs new file mode 100644 index 0000000000..6d6cda73a2 --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/ArchiveFileLoader.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.IO; +using System.Threading.Tasks; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class ArchiveFileLoader : IFileLoader + { + public Task Load(string fileName, Stream stream, FileLoadSettings settings) + { + try + { + var zip = LoadedPackage.FromZipFile(fileName); + var result = zip != null ? new LoadResult { Package = zip } : null; + return Task.FromResult(result); + } + catch (InvalidDataException) + { + return Task.FromResult(null); + } + } + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/BundleFileLoader.cs b/ICSharpCode.ILSpyX/FileLoaders/BundleFileLoader.cs new file mode 100644 index 0000000000..4f0ec5bfef --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/BundleFileLoader.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.IO; +using System.Threading.Tasks; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class BundleFileLoader : IFileLoader + { + public Task Load(string fileName, Stream stream, FileLoadSettings settings) + { + var bundle = LoadedPackage.FromBundle(fileName); + var result = bundle != null ? new LoadResult { Package = bundle } : null; + return Task.FromResult(result); + } + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/FileLoaderRegistry.cs b/ICSharpCode.ILSpyX/FileLoaders/FileLoaderRegistry.cs new file mode 100644 index 0000000000..8117b4b940 --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/FileLoaderRegistry.cs @@ -0,0 +1,49 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class FileLoaderRegistry + { + readonly List registeredLoaders = new List(); + + public IReadOnlyList RegisteredLoaders => registeredLoaders; + + public void Register(IFileLoader loader) + { + if (loader is null) + { + throw new ArgumentNullException(nameof(loader)); + } + + registeredLoaders.Add(loader); + } + + public FileLoaderRegistry() + { + Register(new XamarinCompressedFileLoader()); + Register(new WebCilFileLoader()); + Register(new MetadataFileLoader()); + Register(new BundleFileLoader()); + Register(new ArchiveFileLoader()); + } + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/LoadResult.cs b/ICSharpCode.ILSpyX/FileLoaders/LoadResult.cs new file mode 100644 index 0000000000..73c771a8d6 --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/LoadResult.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using System.Threading.Tasks; + +using ICSharpCode.Decompiler.Metadata; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class LoadResult + { + public MetadataFile? MetadataFile { get; init; } + public Exception? FileLoadException { get; init; } + public LoadedPackage? Package { get; init; } + } + + public record FileLoadSettings(bool ApplyWinRTProjections); + + public interface IFileLoader + { + Task Load(string fileName, Stream stream, FileLoadSettings settings); + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/MetadataFileLoader.cs b/ICSharpCode.ILSpyX/FileLoaders/MetadataFileLoader.cs new file mode 100644 index 0000000000..c7de1fb8dd --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/MetadataFileLoader.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using System.Reflection.Metadata; +using System.Threading.Tasks; + +using ICSharpCode.Decompiler.Metadata; + +using static ICSharpCode.Decompiler.Metadata.MetadataFile; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class MetadataFileLoader : IFileLoader + { + public Task Load(string fileName, Stream stream, FileLoadSettings settings) + { + try + { + var kind = Path.GetExtension(fileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) + ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata; + var metadata = MetadataReaderProvider.FromMetadataStream(stream, MetadataStreamOptions.PrefetchMetadata | MetadataStreamOptions.LeaveOpen); + var metadataFile = new MetadataFile(kind, fileName, metadata); + return Task.FromResult(new LoadResult { MetadataFile = metadataFile }); + } + catch (BadImageFormatException) + { + return Task.FromResult(null); + } + } + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/WebCilFileLoader.cs b/ICSharpCode.ILSpyX/FileLoaders/WebCilFileLoader.cs new file mode 100644 index 0000000000..441ff10fbe --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/WebCilFileLoader.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.IO; +using System.Reflection.Metadata; +using System.Threading.Tasks; + +using ICSharpCode.Decompiler.Metadata; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class WebCilFileLoader : IFileLoader + { + public Task Load(string fileName, Stream stream, FileLoadSettings settings) + { + MetadataReaderOptions options = settings.ApplyWinRTProjections + ? MetadataReaderOptions.ApplyWindowsRuntimeProjections + : MetadataReaderOptions.None; + + var wasm = WebCilFile.FromStream(fileName, options); + var result = wasm != null ? new LoadResult { MetadataFile = wasm } : null; + return Task.FromResult(result); + } + } +} diff --git a/ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs b/ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs new file mode 100644 index 0000000000..bce1c8918e --- /dev/null +++ b/ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs @@ -0,0 +1,73 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Buffers; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; +using System.Threading.Tasks; + +using ICSharpCode.Decompiler.Metadata; + +using K4os.Compression.LZ4; + +namespace ICSharpCode.ILSpyX.FileLoaders +{ + public sealed class XamarinCompressedFileLoader : IFileLoader + { + public async Task Load(string fileName, Stream stream, FileLoadSettings settings) + { + const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian) + using var fileReader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true); + // Read compressed file header + var magic = fileReader.ReadUInt32(); + if (magic != CompressedDataMagic) + return null; + _ = fileReader.ReadUInt32(); // skip index into descriptor table, unused + int uncompressedLength = (int)fileReader.ReadUInt32(); + int compressedLength = (int)stream.Length; // Ensure we read all of compressed data + ArrayPool pool = ArrayPool.Shared; + var src = pool.Rent(compressedLength); + var dst = pool.Rent(uncompressedLength); + try + { + // fileReader stream position is now at compressed module data + await stream.ReadAsync(src, 0, compressedLength).ConfigureAwait(false); + // Decompress + LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength); + // Load module from decompressed data buffer + using (var uncompressedStream = new MemoryStream(dst, writable: false)) + { + MetadataReaderOptions options = settings.ApplyWinRTProjections + ? MetadataReaderOptions.ApplyWindowsRuntimeProjections + : MetadataReaderOptions.None; + + return new LoadResult { + MetadataFile = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options) + }; + } + } + finally + { + pool.Return(dst); + pool.Return(src); + } + } + } +} diff --git a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj index 86b9a2503b..bde8d593a7 100644 --- a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj +++ b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable true nullable @@ -44,8 +44,6 @@ - - @@ -64,12 +62,13 @@ - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ICSharpCode.ILSpyX/LoadedAssembly.cs b/ICSharpCode.ILSpyX/LoadedAssembly.cs index 5ca6529495..cee8561412 100644 --- a/ICSharpCode.ILSpyX/LoadedAssembly.cs +++ b/ICSharpCode.ILSpyX/LoadedAssembly.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Buffers; using System.Diagnostics; using System.IO; using System.Reflection.Metadata; @@ -31,9 +30,9 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX.FileLoaders; using ICSharpCode.ILSpyX.PdbProvider; -using K4os.Compression.LZ4; #nullable enable @@ -50,52 +49,41 @@ namespace ICSharpCode.ILSpyX /// * a non-existant file /// * a file of unknown format that could not be loaded /// * a .nupkg file or .NET core bundle + /// * a standalone portable pdb file or metadata stream /// * a file that is still being loaded in the background /// [DebuggerDisplay("[LoadedAssembly {shortName}]")] public sealed class LoadedAssembly { /// - /// Maps from PEFile (successfully loaded .NET module) back to the LoadedAssembly instance + /// Maps from MetadataFile (successfully loaded .NET module) back to the LoadedAssembly instance /// that was used to load the module. /// - internal static readonly ConditionalWeakTable loadedAssemblies = new ConditionalWeakTable(); - - public sealed class LoadResult - { - public PEFile? PEFile { get; } - public Exception? PEFileLoadException { get; } - public LoadedPackage? Package { get; } - - public LoadResult(PEFile peFile) - { - this.PEFile = peFile ?? throw new ArgumentNullException(nameof(peFile)); - } - public LoadResult(Exception peFileLoadException, LoadedPackage package) - { - this.PEFileLoadException = peFileLoadException ?? throw new ArgumentNullException(nameof(peFileLoadException)); - this.Package = package ?? throw new ArgumentNullException(nameof(package)); - } - } + internal static readonly ConditionalWeakTable loadedAssemblies = new ConditionalWeakTable(); readonly Task loadingTask; readonly AssemblyList assemblyList; readonly string fileName; readonly string shortName; readonly IAssemblyResolver? providedAssemblyResolver; + readonly FileLoaderRegistry? fileLoaders; readonly bool applyWinRTProjections; readonly bool useDebugSymbols; public LoadedAssembly? ParentBundle { get; } public LoadedAssembly(AssemblyList assemblyList, string fileName, - Task? stream = null, IAssemblyResolver? assemblyResolver = null, string? pdbFileName = null, + Task? stream = null, + FileLoaderRegistry? fileLoaders = null, + IAssemblyResolver? assemblyResolver = null, + string? pdbFileName = null, bool applyWinRTProjections = false, bool useDebugSymbols = false) { this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList)); this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); this.PdbFileName = pdbFileName; this.providedAssemblyResolver = assemblyResolver; + this.fileLoaders = fileLoaders; this.applyWinRTProjections = applyWinRTProjections; this.useDebugSymbols = useDebugSymbols; @@ -104,9 +92,10 @@ public LoadedAssembly(AssemblyList assemblyList, string fileName, } public LoadedAssembly(LoadedAssembly bundle, string fileName, Task? stream, + FileLoaderRegistry? fileLoaders = null, IAssemblyResolver? assemblyResolver = null, bool applyWinRTProjections = false, bool useDebugSymbols = false) - : this(bundle.assemblyList, fileName, stream, assemblyResolver, null, + : this(bundle.assemblyList, fileName, stream, fileLoaders, assemblyResolver, null, applyWinRTProjections, useDebugSymbols) { this.ParentBundle = bundle; @@ -126,7 +115,7 @@ public async Task GetTargetFrameworkIdAsync() var value = LazyInit.VolatileRead(ref targetFrameworkId); if (value == null) { - var assembly = await GetPEFileAsync().ConfigureAwait(false); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); value = assembly.DetectTargetFrameworkId() ?? string.Empty; value = LazyInit.GetOrSet(ref targetFrameworkId, value); } @@ -141,7 +130,7 @@ public async Task GetRuntimePackAsync() var value = LazyInit.VolatileRead(ref runtimePack); if (value == null) { - var assembly = await GetPEFileAsync().ConfigureAwait(false); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); value = assembly.DetectRuntimePack() ?? string.Empty; value = LazyInit.GetOrSet(ref runtimePack, value); } @@ -162,27 +151,27 @@ public Task GetLoadResultAsync() } /// - /// Gets the . + /// Gets the . /// - public async Task GetPEFileAsync() + public async Task GetMetadataFileAsync() { var loadResult = await loadingTask.ConfigureAwait(false); - if (loadResult.PEFile != null) - return loadResult.PEFile; + if (loadResult.MetadataFile != null) + return loadResult.MetadataFile; else - throw loadResult.PEFileLoadException!; + throw loadResult.FileLoadException ?? new MetadataFileNotSupportedException(); } /// /// Gets the . /// Returns null in case of load errors. /// - public PEFile? GetPEFileOrNull() + public MetadataFile? GetMetadataFileOrNull() { try { var loadResult = loadingTask.GetAwaiter().GetResult(); - return loadResult.PEFile; + return loadResult.MetadataFile; } catch (Exception ex) { @@ -192,15 +181,15 @@ public async Task GetPEFileAsync() } /// - /// Gets the . + /// Gets the . /// Returns null in case of load errors. /// - public async Task GetPEFileOrNullAsync() + public async Task GetMetadataFileOrNullAsync() { try { var loadResult = await loadingTask.ConfigureAwait(false); - return loadResult.PEFile; + return loadResult.MetadataFile; } catch (Exception ex) { @@ -221,7 +210,7 @@ public async Task GetPEFileAsync() public ICompilation? GetTypeSystemOrNull() { return LazyInitializer.EnsureInitialized(ref this.typeSystem, () => { - var module = GetPEFileOrNull(); + var module = GetMetadataFileOrNull(); if (module == null) return null!; return new SimpleCompilation( @@ -240,7 +229,7 @@ public async Task GetPEFileAsync() { if (typeSystemWithOptions != null && options == currentTypeSystemOptions) return typeSystemWithOptions; - var module = GetPEFileOrNull(); + var module = GetMetadataFileOrNull(); if (module == null) return null; currentTypeSystemOptions = options; @@ -260,31 +249,38 @@ public string Text { get { if (IsLoaded && !HasLoadError) { - PEFile? module = GetPEFileOrNull(); - var metadata = module?.Metadata; - string? versionOrInfo = null; - if (metadata != null) + var result = GetLoadResultAsync().GetAwaiter().GetResult(); + if (result.MetadataFile != null) { - if (metadata.IsAssembly) + switch (result.MetadataFile.Kind) { - versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString(); - string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult(); - if (!string.IsNullOrEmpty(tfId)) - versionOrInfo += ", " + tfId.Replace("Version=", " "); - } - else - { - versionOrInfo = ".netmodule"; + case MetadataFile.MetadataFileKind.PortableExecutable: + var metadata = result.MetadataFile.Metadata; + string? versionOrInfo; + if (metadata.IsAssembly) + { + versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString(); + string tfId = GetTargetFrameworkIdAsync().GetAwaiter().GetResult(); + if (!string.IsNullOrEmpty(tfId)) + versionOrInfo += ", " + tfId.Replace("Version=", " "); + } + else + { + versionOrInfo = ".netmodule"; + } + if (versionOrInfo == null) + return ShortName; + return string.Format("{0} ({1})", ShortName, versionOrInfo); + case MetadataFile.MetadataFileKind.ProgramDebugDatabase: + return ShortName + " (Debug Metadata)"; + case MetadataFile.MetadataFileKind.Metadata: + return ShortName + " (Metadata)"; + default: + return ShortName; } } - if (versionOrInfo == null) - return ShortName; - return string.Format("{0} ({1})", ShortName, versionOrInfo); - } - else - { - return ShortName; } + return ShortName; } } @@ -298,7 +294,7 @@ public string Text { /// public bool IsLoadedAsValidAssembly { get { - return loadingTask.Status == TaskStatus.RanToCompletion && loadingTask.Result.PEFile != null; + return loadingTask.Status == TaskStatus.RanToCompletion && loadingTask.Result.MetadataFile != null; } } @@ -317,122 +313,94 @@ public bool IsLoadedAsValidAssembly { async Task LoadAsync(Task? streamTask) { - // runs on background thread - var stream = streamTask != null ? await streamTask.ConfigureAwait(false) : null; - if (stream != null) + using var stream = await PrepareStream(); + FileLoadSettings settings = new FileLoadSettings(applyWinRTProjections); + + LoadResult? result = null; + + if (fileLoaders != null) { - // Read the module from a precrafted stream - if (!stream.CanSeek) + foreach (var loader in fileLoaders.RegisteredLoaders) { - var memoryStream = new MemoryStream(); - stream.CopyTo(memoryStream); - stream.Close(); - memoryStream.Position = 0; - stream = memoryStream; + stream.Position = 0; + result = await loader.Load(fileName, stream, settings).ConfigureAwait(false); + if (result != null) + { + break; + } } - var streamOptions = stream is MemoryStream ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default; - return LoadAssembly(stream, streamOptions, applyWinRTProjections); } - // Read the module from disk - Exception loadAssemblyException; - try + + if (result == null) { - using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) + stream.Position = 0; + try { - return LoadAssembly(fileStream, PEStreamOptions.PrefetchEntireImage, applyWinRTProjections); + MetadataReaderOptions options = applyWinRTProjections + ? MetadataReaderOptions.ApplyWindowsRuntimeProjections + : MetadataReaderOptions.None; + + PEFile module = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options); + result = new LoadResult { MetadataFile = module }; + } + catch (Exception ex) + { + result = new LoadResult { FileLoadException = ex }; } } - catch (PEFileNotSupportedException ex) - { - loadAssemblyException = ex; - } - catch (BadImageFormatException ex) - { - loadAssemblyException = ex; - } - // Maybe its a compressed Xamarin/Mono assembly, see https://github.com/xamarin/xamarin-android/pull/4686 - try - { - return LoadCompressedAssembly(fileName); - } - catch (InvalidDataException) - { - // Not a compressed module, try other options below - } - // If it's not a .NET module, maybe it's a single-file bundle - var bundle = LoadedPackage.FromBundle(fileName); - if (bundle != null) - { - bundle.LoadedAssembly = this; - return new LoadResult(loadAssemblyException, bundle); - } - // If it's not a .NET module, maybe it's a zip archive (e.g. .nupkg) - try + + if (result.MetadataFile != null) { - var zip = LoadedPackage.FromZipFile(fileName); - zip.LoadedAssembly = this; - return new LoadResult(loadAssemblyException, zip); + lock (loadedAssemblies) + { + loadedAssemblies.Add(result.MetadataFile, this); + } + + if (result.MetadataFile is PEFile module) + { + debugInfoProvider = LoadDebugInfo(module); + } } - catch (InvalidDataException) + else if (result.Package != null) { - throw loadAssemblyException; + result.Package.LoadedAssembly = this; } - } - - LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions, bool applyWinRTProjections) - { - MetadataReaderOptions options = applyWinRTProjections - ? MetadataReaderOptions.ApplyWindowsRuntimeProjections - : MetadataReaderOptions.None; - - PEFile module = new PEFile(fileName, stream, streamOptions, metadataOptions: options); - - debugInfoProvider = LoadDebugInfo(module); - lock (loadedAssemblies) + else if (result.FileLoadException != null) { - loadedAssemblies.Add(module, this); + throw result.FileLoadException; } - return new LoadResult(module); - } + return result; - LoadResult LoadCompressedAssembly(string fileName) - { - const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian) - using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) - using (var fileReader = new BinaryReader(fileStream)) + async Task PrepareStream() { - // Read compressed file header - var magic = fileReader.ReadUInt32(); - if (magic != CompressedDataMagic) - throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}"); - _ = fileReader.ReadUInt32(); // skip index into descriptor table, unused - int uncompressedLength = (int)fileReader.ReadUInt32(); - int compressedLength = (int)fileStream.Length; // Ensure we read all of compressed data - ArrayPool pool = ArrayPool.Shared; - var src = pool.Rent(compressedLength); - var dst = pool.Rent(uncompressedLength); - try + // runs on background thread + var stream = streamTask != null ? await streamTask.ConfigureAwait(false) : null; + if (stream != null) { - // fileReader stream position is now at compressed module data - fileStream.Read(src, 0, compressedLength); - // Decompress - LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength); - // Load module from decompressed data buffer - using (var uncompressedStream = new MemoryStream(dst, writable: false)) + // Read the module from a precrafted stream + if (!stream.CanSeek) { - return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage, applyWinRTProjections); + var memoryStream = new MemoryStream(); + stream.CopyTo(memoryStream); + stream.Close(); + memoryStream.Position = 0; + stream = memoryStream; } + return stream; } - finally + else { - pool.Return(dst); - pool.Return(src); + return new FileStream(fileName, FileMode.Open, FileAccess.Read); } } } - IDebugInfoProvider? LoadDebugInfo(PEFile module) + IDebugInfoProvider? LoadDebugInfo(PEFile? module) { + if (module == null) + { + return null; + } if (useDebugSymbols) { try @@ -457,8 +425,8 @@ LoadResult LoadCompressedAssembly(string fileName) public async Task LoadDebugInfo(string fileName) { this.PdbFileName = fileName; - var assembly = await GetPEFileAsync().ConfigureAwait(false); - debugInfoProvider = await Task.Run(() => LoadDebugInfo(assembly)); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); + debugInfoProvider = await Task.Run(() => LoadDebugInfo(assembly as PEFile)); return debugInfoProvider; } @@ -493,7 +461,7 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi this.referenceLoadInfo = parent.LoadedAssemblyReferencesInfo; } - public PEFile? Resolve(IAssemblyReference reference) + public MetadataFile? Resolve(IAssemblyReference reference) { return ResolveAsync(reference).GetAwaiter().GetResult(); } @@ -510,9 +478,9 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi /// 8) search C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /// 9) try to find match by asm name (no tfm/version) in loaded assemblies /// - public async Task ResolveAsync(IAssemblyReference reference) + public async Task ResolveAsync(IAssemblyReference reference) { - PEFile? module; + MetadataFile? module; // 0) if we're inside a package, look for filename.dll in parent directories if (providedAssemblyResolver != null) { @@ -548,7 +516,7 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi if (asm != null) { referenceLoadInfo.AddMessage(reference.FullName, MessageKind.Info, "Success - Loading from: " + file); - return await asm.GetPEFileOrNullAsync().ConfigureAwait(false); + return await asm.GetMetadataFileOrNullAsync().ConfigureAwait(false); } return null; } @@ -568,12 +536,12 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi } } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { return ResolveModuleAsync(mainModule, moduleName).GetAwaiter().GetResult(); } - public async Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public async Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { if (providedAssemblyResolver != null) { @@ -600,7 +568,7 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi } if (asm != null) { - return await asm.GetPEFileOrNullAsync().ConfigureAwait(false); + return await asm.GetMetadataFileOrNullAsync().ConfigureAwait(false); } } } @@ -608,7 +576,7 @@ public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyLi // Module does not exist on disk, look for one with a matching name in the assemblylist: foreach (LoadedAssembly loaded in alreadyLoadedAssemblies.Assemblies) { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); var reader = module?.Metadata; if (reader == null || reader.IsAssembly) continue; @@ -662,7 +630,7 @@ public AssemblyReferenceClassifier GetAssemblyReferenceClassifier(bool applyWinR /// public IDebugInfoProvider? GetDebugInfoOrNull() { - if (GetPEFileOrNull() == null) + if (GetMetadataFileOrNull() == null) return null; return debugInfoProvider; } diff --git a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs index 8fe549b28b..0f07f6c105 100644 --- a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs +++ b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs @@ -27,32 +27,32 @@ public unsafe static Mono.Cecil.ModuleDefinition CreateCecilObjectModel(this PEF return Mono.Cecil.ModuleDefinition.ReadModule(new UnmanagedMemoryStream(image.Pointer, image.Length)); } - public static IAssemblyResolver GetAssemblyResolver(this PEFile file, bool loadOnDemand = true) + public static IAssemblyResolver GetAssemblyResolver(this MetadataFile file, bool loadOnDemand = true) { return GetLoadedAssembly(file).GetAssemblyResolver(loadOnDemand); } - internal static IAssemblyResolver GetAssemblyResolver(this PEFile file, AssemblyListSnapshot snapshot, bool loadOnDemand = true) + internal static IAssemblyResolver GetAssemblyResolver(this MetadataFile file, AssemblyListSnapshot snapshot, bool loadOnDemand = true) { return GetLoadedAssembly(file).GetAssemblyResolver(snapshot, loadOnDemand); } - public static IDebugInfoProvider? GetDebugInfoOrNull(this PEFile file) + public static IDebugInfoProvider? GetDebugInfoOrNull(this MetadataFile file) { return GetLoadedAssembly(file).GetDebugInfoOrNull(); } - public static ICompilation? GetTypeSystemOrNull(this PEFile file) + public static ICompilation? GetTypeSystemOrNull(this MetadataFile file) { return GetLoadedAssembly(file).GetTypeSystemOrNull(); } - public static ICompilation? GetTypeSystemWithDecompilerSettingsOrNull(this PEFile file, DecompilerSettings settings) + public static ICompilation? GetTypeSystemWithDecompilerSettingsOrNull(this MetadataFile file, DecompilerSettings settings) { return GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(settings)); } - public static LoadedAssembly GetLoadedAssembly(this PEFile file) + public static LoadedAssembly GetLoadedAssembly(this MetadataFile file) { if (file == null) throw new ArgumentNullException(nameof(file)); diff --git a/ICSharpCode.ILSpyX/LoadedPackage.cs b/ICSharpCode.ILSpyX/LoadedPackage.cs index 8d0d99f905..47e80b962d 100644 --- a/ICSharpCode.ILSpyX/LoadedPackage.cs +++ b/ICSharpCode.ILSpyX/LoadedPackage.cs @@ -71,7 +71,10 @@ public LoadedPackage(PackageKind kind, IEnumerable entries) foreach (var entry in this.Entries) { var (dirname, filename) = SplitName(entry.Name); - GetFolder(dirname).Entries.Add(new FolderEntry(filename, entry)); + if (!string.IsNullOrEmpty(filename)) + { + GetFolder(dirname).Entries.Add(new FolderEntry(filename, entry)); + } } this.RootFolder = rootFolder; @@ -123,6 +126,10 @@ public static LoadedPackage FromZipFile(string file) view = null; // don't dispose the view, we're still using it in the bundle entries return result; } + catch (InvalidDataException) + { + return null; + } finally { view?.Dispose(); @@ -269,52 +276,52 @@ internal PackageFolder(LoadedPackage package, PackageFolder? parent, string name public List Folders { get; } = new List(); public List Entries { get; } = new List(); - public PEFile? Resolve(IAssemblyReference reference) + public MetadataFile? Resolve(IAssemblyReference reference) { var asm = ResolveFileName(reference.Name + ".dll"); if (asm != null) { - return asm.GetPEFileOrNull(); + return asm.GetMetadataFileOrNull(); } return parent?.Resolve(reference); } - public Task ResolveAsync(IAssemblyReference reference) + public Task ResolveAsync(IAssemblyReference reference) { var asm = ResolveFileName(reference.Name + ".dll"); if (asm != null) { - return asm.GetPEFileOrNullAsync(); + return asm.GetMetadataFileOrNullAsync(); } if (parent != null) { return parent.ResolveAsync(reference); } - return Task.FromResult(null); + return Task.FromResult(null); } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { var asm = ResolveFileName(moduleName + ".dll"); if (asm != null) { - return asm.GetPEFileOrNull(); + return asm.GetMetadataFileOrNull(); } return parent?.ResolveModule(mainModule, moduleName); } - public Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { var asm = ResolveFileName(moduleName + ".dll"); if (asm != null) { - return asm.GetPEFileOrNullAsync(); + return asm.GetMetadataFileOrNullAsync(); } if (parent != null) { return parent.ResolveModuleAsync(mainModule, moduleName); } - return Task.FromResult(null); + return Task.FromResult(null); } readonly Dictionary assemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -332,6 +339,7 @@ internal PackageFolder(LoadedPackage package, PackageFolder? parent, string name { asm = new LoadedAssembly( package.LoadedAssembly, entry.Name, + fileLoaders: package.LoadedAssembly.AssemblyList.LoaderRegistry, assemblyResolver: this, stream: Task.Run(entry.TryOpenStream), applyWinRTProjections: package.LoadedAssembly.AssemblyList.ApplyWinRTProjections, diff --git a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs index cf1cca9130..d01257876f 100644 --- a/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs @@ -39,7 +39,7 @@ public static class DebugInfoUtils // try to open portable pdb file/embedded pdb info: if (TryOpenPortablePdb(module, out var provider, out var pdbFileName)) { - return new PortableDebugInfoProvider(module.FileName, provider, pdbFileName); + return new PortableDebugInfoProvider(module.FileName, provider, MetadataReaderOptions.Default, pdbFileName); } else { @@ -80,7 +80,7 @@ public static class DebugInfoUtils { stream.Position = 0; var provider = MetadataReaderProvider.FromPortablePdbStream(stream); - return new PortableDebugInfoProvider(module.FileName, provider, pdbFileName); + return new PortableDebugInfoProvider(module.FileName, provider, MetadataReaderOptions.Default, pdbFileName); } } diff --git a/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs index c7e09d3053..6fe3021bbb 100644 --- a/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Siegfried Pammer +// Copyright (c) 2018 Siegfried Pammer // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software @@ -135,5 +135,13 @@ public bool TryGetName(SRM.MethodDefinitionHandle handle, int index, [NotNullWhe name = variable.Name; return name != null; } + + public bool TryGetExtraTypeInfo(SRM.MethodDefinitionHandle method, int index, out PdbExtraTypeInfo extraTypeInfo) + { + // Mono.Cecil's WindowsPDB reader is unable to read tuple element names + // and dynamic flags custom debug information. + extraTypeInfo = default; + return false; + } } } diff --git a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs index 0f64997ea6..8ebdba9d1f 100644 --- a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Siegfried Pammer +// Copyright (c) 2018 Siegfried Pammer // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software @@ -23,8 +23,11 @@ using System.Reflection.Metadata; using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; +using static ICSharpCode.Decompiler.Metadata.MetadataFile; + #nullable enable namespace ICSharpCode.ILSpyX.PdbProvider @@ -34,15 +37,18 @@ class PortableDebugInfoProvider : IDebugInfoProvider string? pdbFileName; string moduleFileName; readonly MetadataReaderProvider provider; + MetadataReaderOptions options; bool hasError; internal bool IsEmbedded => pdbFileName == null; public PortableDebugInfoProvider(string moduleFileName, MetadataReaderProvider provider, + MetadataReaderOptions options = MetadataReaderOptions.Default, string? pdbFileName = null) { this.moduleFileName = moduleFileName ?? throw new ArgumentNullException(nameof(moduleFileName)); this.provider = provider ?? throw new ArgumentNullException(nameof(provider)); + this.options = options; this.pdbFileName = pdbFileName; } @@ -161,5 +167,83 @@ public bool TryGetName(MethodDefinitionHandle method, int index, [NotNullWhen(tr } return false; } + + public bool TryGetExtraTypeInfo(MethodDefinitionHandle method, int index, out PdbExtraTypeInfo extraTypeInfo) + { + var metadata = GetMetadataReader(); + extraTypeInfo = default; + + if (metadata == null) + return false; + + LocalVariableHandle localVariableHandle = default; + foreach (var h in metadata.GetLocalScopes(method)) + { + var scope = metadata.GetLocalScope(h); + foreach (var v in scope.GetLocalVariables()) + { + var var = metadata.GetLocalVariable(v); + if (var.Index == index) + { + localVariableHandle = v; + break; + } + } + + if (!localVariableHandle.IsNil) + break; + } + + foreach (var h in metadata.CustomDebugInformation) + { + var cdi = metadata.GetCustomDebugInformation(h); + if (cdi.Parent.IsNil || cdi.Parent.Kind != HandleKind.LocalVariable) + continue; + if (localVariableHandle != (LocalVariableHandle)cdi.Parent) + continue; + if (cdi.Value.IsNil || cdi.Kind.IsNil) + continue; + var kind = metadata.GetGuid(cdi.Kind); + if (kind == KnownGuids.TupleElementNames && extraTypeInfo.TupleElementNames is null) + { + var reader = metadata.GetBlobReader(cdi.Value); + var list = new List(); + while (reader.RemainingBytes > 0) + { + // Read a UTF8 null-terminated string + int length = reader.IndexOf(0); + string s = reader.ReadUTF8(length); + // Skip null terminator + reader.ReadByte(); + list.Add(string.IsNullOrWhiteSpace(s) ? null : s); + } + + extraTypeInfo.TupleElementNames = list.ToArray(); + } + else if (kind == KnownGuids.DynamicLocalVariables && extraTypeInfo.DynamicFlags is null) + { + var reader = metadata.GetBlobReader(cdi.Value); + extraTypeInfo.DynamicFlags = new bool[reader.Length * 8]; + int j = 0; + while (reader.RemainingBytes > 0) + { + int b = reader.ReadByte(); + for (int i = 1; i < 0x100; i <<= 1) + extraTypeInfo.DynamicFlags[j++] = (b & i) != 0; + } + } + + if (extraTypeInfo.TupleElementNames != null && extraTypeInfo.DynamicFlags != null) + break; + } + + return extraTypeInfo.TupleElementNames != null || extraTypeInfo.DynamicFlags != null; + } + + public MetadataFile ToMetadataFile() + { + var kind = IsEmbedded || Path.GetExtension(SourceFileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata; + return new MetadataFile(kind, SourceFileName, provider, options, 0, IsEmbedded); + } } } diff --git a/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs index 803c5f9528..933ef3eba4 100644 --- a/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs @@ -67,8 +67,8 @@ protected bool IsInNamespaceOrAssembly(IEntity entity) { if (searchRequest.InAssembly != null) { - if (entity.ParentModule?.PEFile == null || - !(Path.GetFileName(entity.ParentModule.PEFile.FileName).Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase) + if (entity.ParentModule?.MetadataFile == null || + !(Path.GetFileName(entity.ParentModule.MetadataFile.FileName).Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase) || entity.ParentModule.FullAssemblyName.Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase))) { return false; diff --git a/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs index 0607a71e51..61de7b7149 100644 --- a/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs @@ -78,7 +78,7 @@ protected AbstractSearchStrategy(SearchRequest request, IProducerConsumerCollect this.omitGenerics = request.OmitGenerics; } - public abstract void Search(PEFile module, CancellationToken cancellationToken); + public abstract void Search(MetadataFile module, CancellationToken cancellationToken); protected virtual bool IsMatch(string name) { diff --git a/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs index 3d0b1fb876..c164f43742 100644 --- a/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.IO; using System.Threading; @@ -35,7 +34,7 @@ public AssemblySearchStrategy(SearchRequest request, this.searchKind = searchKind; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -61,7 +60,7 @@ public override void Search(PEFile module, CancellationToken cancellationToken) OnFoundResult(module); } - string? GetNameToMatch(PEFile module, AssemblySearchKind kind) + string? GetNameToMatch(MetadataFile module, AssemblySearchKind kind) { switch (kind) { @@ -98,7 +97,7 @@ public override void Search(PEFile module, CancellationToken cancellationToken) return null; } - void OnFoundResult(PEFile module) + void OnFoundResult(MetadataFile module) { OnFoundResult(searchRequest.SearchResultFactory.Create(module)); } diff --git a/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs index dfb83fc697..f0c0c20f82 100644 --- a/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs @@ -28,8 +28,6 @@ using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpyX.Abstractions; -using static System.Reflection.Metadata.PEReaderExtensions; - using ILOpCode = System.Reflection.Metadata.ILOpCode; namespace ICSharpCode.ILSpyX.Search @@ -78,7 +76,7 @@ public LiteralSearchStrategy(ILanguage language, ApiVisibility apiVisibility, Se // Note: if searchTermLiteralType remains TypeCode.Empty, we'll do a substring search via base.IsMatch } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; @@ -143,9 +141,9 @@ bool IsLiteralMatch(MetadataReader metadata, object? val) } } - bool MethodIsLiteralMatch(PEFile module, MethodDefinition methodDefinition) + bool MethodIsLiteralMatch(MetadataFile module, MethodDefinition methodDefinition) { - var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); + var blob = module.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); if (searchTermLiteralType == TypeCode.Int64) { Debug.Assert(searchTermLiteralValue != null); diff --git a/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs index 3af2e86f8b..4d28fa27ea 100644 --- a/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Threading; @@ -36,7 +35,7 @@ public MemberSearchStrategy(ILanguage language, ApiVisibility apiVisibility, Sea this.searchKind = searchKind; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; diff --git a/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs index b9a4a86eb8..f1f48480df 100644 --- a/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Globalization; using System.Reflection.Metadata; @@ -44,7 +43,7 @@ public MetadataTokenSearchStrategy(ILanguage language, ApiVisibility apiVisibili } } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (searchTermToken.IsNil) diff --git a/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs index b9090b34d9..030caa9470 100644 --- a/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs @@ -33,7 +33,7 @@ public NamespaceSearchStrategy(SearchRequest request, IProducerConsumerCollectio { } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var typeSystem = module.GetTypeSystemWithDecompilerSettingsOrNull(searchRequest.DecompilerSettings); @@ -44,7 +44,7 @@ public override void Search(PEFile module, CancellationToken cancellationToken) Search(module, root); } - private void Search(PEFile module, INamespace ns) + private void Search(MetadataFile module, INamespace ns) { if (ns.Types.Any()) { @@ -56,7 +56,7 @@ private void Search(PEFile module, INamespace ns) Search(module, child); } - void OnFoundResult(PEFile module, INamespace ns) + void OnFoundResult(MetadataFile module, INamespace ns) { OnFoundResult(searchRequest.SearchResultFactory.Create(module, ns)); } diff --git a/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs index 46c4558b8d..a0419f50f0 100644 --- a/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Reflection; using System.Threading; @@ -50,7 +49,7 @@ protected bool CheckVisibility(Resource resource) return true; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var resourcesNode = treeNodeFactory.CreateResourcesList(module); @@ -59,7 +58,7 @@ public override void Search(PEFile module, CancellationToken cancellationToken) Search(module, resource, resourcesNode, treeNodeFactory.Create(resource), cancellationToken); } - void Search(PEFile module, Resource resource, ITreeNode parent, ITreeNode node, CancellationToken cancellationToken) + void Search(MetadataFile module, Resource resource, ITreeNode parent, ITreeNode node, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -81,7 +80,7 @@ void Search(PEFile module, Resource resource, ITreeNode parent, ITreeNode node, Search(module, resource, node, child, cancellationToken); } - void OnFoundResult(PEFile module, Resource resource, ITreeNode node, ITreeNode parent) + void OnFoundResult(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent) { OnFoundResult(searchRequest.SearchResultFactory.Create(module, resource, node, parent)); } diff --git a/ICSharpCode.ILSpyX/Search/SearchResult.cs b/ICSharpCode.ILSpyX/Search/SearchResult.cs index abe18ae0d6..38b618a2dc 100644 --- a/ICSharpCode.ILSpyX/Search/SearchResult.cs +++ b/ICSharpCode.ILSpyX/Search/SearchResult.cs @@ -28,9 +28,9 @@ namespace ICSharpCode.ILSpyX.Search public interface ISearchResultFactory { MemberSearchResult Create(IEntity entity); - ResourceSearchResult Create(PEFile module, Resource resource, ITreeNode node, ITreeNode parent); - AssemblySearchResult Create(PEFile module); - NamespaceSearchResult Create(PEFile module, INamespace @namespace); + ResourceSearchResult Create(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent); + AssemblySearchResult Create(MetadataFile module); + NamespaceSearchResult Create(MetadataFile module, INamespace @namespace); } public class SearchResult @@ -42,18 +42,14 @@ public class SearchResult public float Fitness { get; set; } -#nullable disable - public string Name { get; set; } - public string Location { get; set; } - public string Assembly { get; set; } -#nullable enable + public required string Name { get; set; } + public required string Location { get; set; } + public required string Assembly { get; set; } public object? ToolTip { get; set; } -#nullable disable - public object Image { get; set; } - public object LocationImage { get; set; } + public required object Image { get; set; } + public required object LocationImage { get; set; } - public object AssemblyImage { get; set; } -#nullable enable + public required object AssemblyImage { get; set; } public override string ToString() { @@ -97,7 +93,7 @@ public class ResourceSearchResult : SearchResult public class AssemblySearchResult : SearchResult { #nullable disable - public PEFile Module { get; set; } + public MetadataFile Module { get; set; } public override object Reference => Module; #nullable enable } diff --git a/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj b/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj index 5d09db6572..e0d1db28c2 100644 --- a/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj +++ b/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj @@ -34,7 +34,9 @@ true - + + false + @@ -45,14 +47,14 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + @@ -74,8 +76,8 @@ - ..\ILSpy\bin\$(Configuration)\net6.0-windows\win-x64\publish\fwdependent\ - ..\ILSpy\bin\$(Configuration)\net6.0-windows\win-arm64\publish\fwdependent\ + ..\ILSpy\bin\$(Configuration)\net8.0-windows\win-x64\publish\fwdependent\ + ..\ILSpy\bin\$(Configuration)\net8.0-windows\win-arm64\publish\fwdependent\ diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 0b9b3e9bef..5ad17dfb59 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -39,7 +39,9 @@ - + + false + @@ -51,14 +53,14 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + @@ -80,7 +82,7 @@ - ..\ILSpy\bin\$(Configuration)\net6.0-windows\win-x64\publish\fwdependent\ + ..\ILSpy\bin\$(Configuration)\net8.0-windows\win-x64\publish\fwdependent\ diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 27acff4ca8..970618e8ef 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -23,6 +23,7 @@ using System.Threading; using System.Xml.Linq; +using ICSharpCode.BamlDecompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Util; @@ -179,7 +180,7 @@ void RunTest(string name, string asmPath, string sourcePath) resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); var res = module.Resources.First(); Stream bamlStream = LoadBaml(res, name + ".baml"); - Assert.IsNotNull(bamlStream); + Assert.That(bamlStream, Is.Not.Null); BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(module, resolver); var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings()); diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj index dc979f1526..0c00fb98c1 100644 --- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj +++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -2,7 +2,7 @@ - net6.0-windows + net8.0-windows win-x64 false AutoGeneratedProgram @@ -28,15 +28,16 @@ true - - - - - - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index 4c9a93cf82..788b32ce1c 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -23,6 +23,7 @@ using System.Threading.Tasks; using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.BamlDecompiler; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; @@ -65,7 +66,7 @@ void LoadBaml(AvalonEditTextOutput output, CancellationToken cancellationToken) { var asm = this.Ancestors().OfType().First().LoadedAssembly; using var data = OpenStream(); - BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetPEFileOrNull(), asm.GetAssemblyResolver()); + BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetMetadataFileOrNull(), asm.GetAssemblyResolver()); var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings()); decompiler.CancellationToken = cancellationToken; var result = decompiler.Decompile(data); diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs index 4ac408de5e..32f71afa95 100644 --- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -19,8 +19,8 @@ using System; using System.ComponentModel.Composition; using System.IO; -using System.Linq; +using ICSharpCode.BamlDecompiler; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.Metadata; @@ -51,7 +51,7 @@ public sealed class BamlResourceFileHandler : IResourceFileHandler public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, ResourceFileHandlerContext context) { - BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver()); + BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetMetadataFileOrNull(), assembly.GetAssemblyResolver()); var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings() { ThrowOnAssemblyResolveErrors = context.DecompilationOptions.DecompilerSettings.ThrowOnAssemblyResolveErrors }); diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index e222ba25a0..2a16add843 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -2,7 +2,7 @@ ILSpy.BamlDecompiler.Plugin - net6.0-windows + net8.0-windows win-x64;win-arm64 false False @@ -26,13 +26,8 @@ ..\ILSpy\bin\$(Configuration)\ - - - - - - + diff --git a/ILSpy.Installer/ILSpy.Installer.csproj b/ILSpy.Installer/ILSpy.Installer.csproj index 0697d38728..d5cab6a357 100644 --- a/ILSpy.Installer/ILSpy.Installer.csproj +++ b/ILSpy.Installer/ILSpy.Installer.csproj @@ -10,9 +10,13 @@ $(DefineConstants);$(PlatformForInstaller) + + false + + - - + + diff --git a/ILSpy.Installer/setup.cs b/ILSpy.Installer/setup.cs index ce15c30891..0bcc418d63 100644 --- a/ILSpy.Installer/setup.cs +++ b/ILSpy.Installer/setup.cs @@ -25,7 +25,7 @@ static public void Main() #else var buildPlatform = "x64"; #endif - var buildOutputDir = $@"ILSpy\bin\{buildConfiguration}\net6.0-windows\win-{buildPlatform}\publish\fwdependent"; + var buildOutputDir = $@"ILSpy\bin\{buildConfiguration}\net8.0-windows\win-{buildPlatform}\publish\fwdependent"; var project = new Project("ILSpy", new InstallDir(@"%LocalAppData%\Programs\ILSpy", diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index f0a708b217..5b894464ad 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -3,7 +3,7 @@ ILSpy.ReadyToRun.Plugin - net6.0-windows + net8.0-windows win-x64;win-arm64 False en-US @@ -34,18 +34,16 @@ - - - - + + - - + + diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 95b0f3c765..cadd1217bc 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -30,7 +30,6 @@ using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; @@ -98,7 +97,7 @@ public void WriteReference(IMember member, string text, bool isDefinition = fals [Export(typeof(Language))] internal class ReadyToRunLanguage : Language { - private static readonly ConditionalWeakTable readyToRunReaders = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable readyToRunReaders = new ConditionalWeakTable(); public override string Name => "ReadyToRun"; @@ -113,7 +112,7 @@ public override void WriteCommentLine(ITextOutput output, string comment) public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { - PEFile module = assembly.GetPEFileAsync().GetAwaiter().GetResult(); + PEFile module = assembly.GetMetadataFileAsync().GetAwaiter().GetResult() as PEFile; ReadyToRunReaderCacheEntry cacheEntry = GetReader(assembly, module); if (cacheEntry.readyToRunReader == null) { @@ -136,7 +135,7 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - PEFile module = method.ParentModule.PEFile; + PEFile module = method.ParentModule.MetadataFile as PEFile; ReadyToRunReaderCacheEntry cacheEntry = GetReader(module.GetLoadedAssembly(), module); if (cacheEntry.readyToRunReader == null) { @@ -196,7 +195,7 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi if (cacheEntry.compositeReadyToRunReader == null) { disassemblingReader = reader; - file = method.ParentModule.PEFile; + file = method.ParentModule.MetadataFile as PEFile; } else { @@ -220,33 +219,41 @@ public override RichText GetRichTextTooltip(IEntity entity) return Languages.ILLanguage.GetRichTextTooltip(entity); } - private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, PEFile module) + private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, MetadataFile file) { ReadyToRunReaderCacheEntry result; lock (readyToRunReaders) { - if (!readyToRunReaders.TryGetValue(module, out result)) + if (!readyToRunReaders.TryGetValue(file, out result)) { result = new ReadyToRunReaderCacheEntry(); try { - result.readyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), new StandaloneAssemblyMetadata(module.Reader), module.Reader, module.FileName); - if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) + if (file is not PEFile module) { - result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; result.readyToRunReader = null; + result.failureReason = "File is not a valid PE file."; } - else if (result.readyToRunReader.OwnerCompositeExecutable != null) + else { - string compositePath = Path.Combine(Path.GetDirectoryName(module.FileName), result.readyToRunReader.OwnerCompositeExecutable); - result.compositeReadyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), compositePath); + result.readyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), new StandaloneAssemblyMetadata(module.Reader), module.Reader, module.FileName); + if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) + { + result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; + result.readyToRunReader = null; + } + else if (result.readyToRunReader.OwnerCompositeExecutable != null) + { + string compositePath = Path.Combine(Path.GetDirectoryName(module.FileName), result.readyToRunReader.OwnerCompositeExecutable); + result.compositeReadyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), compositePath); + } } } catch (BadImageFormatException e) { result.failureReason = e.Message; } - readyToRunReaders.Add(module, result); + readyToRunReaders.Add(file, result); } } return result; @@ -270,18 +277,18 @@ public IAssemblyMetadata FindAssembly(MetadataReader metadataReader, AssemblyRef public IAssemblyMetadata FindAssembly(string simpleName, string parentFile) { - return GetAssemblyMetadata(assemblyResolver.ResolveModule(loadedAssembly.GetPEFileOrNull(), simpleName + ".dll")); + return GetAssemblyMetadata(assemblyResolver.ResolveModule(loadedAssembly.GetMetadataFileOrNull(), simpleName + ".dll")); } - private IAssemblyMetadata GetAssemblyMetadata(PEFile module) + private IAssemblyMetadata GetAssemblyMetadata(MetadataFile module) { - if (module.Reader == null) + if (module is not PEFile peFile || peFile.Reader == null) { return null; } else { - return new IlSpyAssemblyMetadata(module); + return new IlSpyAssemblyMetadata(peFile); } } } diff --git a/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs b/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs new file mode 100644 index 0000000000..43c74ce85d --- /dev/null +++ b/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2024 Yuriy Zatuchnyy +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Linq; +using System.Threading.Tasks; + +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.CSharp.Resolver; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX.Analyzers; + +using NUnit.Framework; + +namespace ICSharpCode.ILSpy.Tests.Analyzers +{ + [TestFixture] + public class AnalyzerScopeTests + { + public class TestClass + { + + } + + + [Test] + public void WhenPublicNestedClass_ThenNotInfiniteLoop() + { + // Given + ILSpyX.AssemblyList assemblyList = new ILSpyX.AssemblyList(); + var file = new PEFile(this.GetType().Assembly.Location); + var td = file.Metadata.TypeDefinitions.First(td => td.GetFullTypeName(file.Metadata).Name == nameof(TestClass)); + + Decompiler.Metadata.IAssemblyResolver assemblyResolver = new UniversalAssemblyResolver(null, false, null); + ICompilation compilation = new DecompilerTypeSystem(file, assemblyResolver); + ITypeResolveContext context = new CSharpResolver(compilation); + var module = ((IModuleReference)file).Resolve(context) as MetadataModule; + IEntity entity = module.GetDefinition(td); + + // When + var task = Task.Run(() => { + var target = new AnalyzerScope(assemblyList, entity); + }); + + var result = Task.WaitAny(new[] { task, Task.Delay(500) }); // 0.5 seconds + + // Then + Assert.That(result == 0, "The constructor should complete in less than 10 seconds"); + } + + } +} diff --git a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs index f9616006c3..1149418e86 100644 --- a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs @@ -25,8 +25,8 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; -using ICSharpCode.ILSpy.Analyzers; -using ICSharpCode.ILSpy.Analyzers.Builtin; +using ICSharpCode.ILSpyX.Analyzers; +using ICSharpCode.ILSpyX.Analyzers.Builtin; using NSubstitute; @@ -69,7 +69,7 @@ public void VerifyDoesNotShowForNoSymbol() var shouldShow = analyzer.Show(symbol: null); // Assert - Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for no symbol"); + Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for no symbol"); } [Test] @@ -85,7 +85,7 @@ public void VerifyDoesNotShowForNonMembers(SymbolKind symbolKind) var shouldShow = analyzer.Show(symbolMock); // Assert - Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}'"); + Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}'"); } [Test] @@ -100,7 +100,7 @@ public void VerifyDoesNotShowForStaticMembers(SymbolKind symbolKind) var shouldShow = analyzer.Show(memberMock); // Assert - Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for static symbol '{symbolKind}'"); + Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for static symbol '{symbolKind}'"); } [Test] @@ -117,7 +117,7 @@ public void VerifyDoesNotShowForUnsupportedTypes( var shouldShow = analyzer.Show(memberMock); // Assert - Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}' and '{typeKind}'"); + Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}' and '{typeKind}'"); } [Test] @@ -134,7 +134,7 @@ public void VerifyShowsForSupportedTypes( var shouldShow = analyzer.Show(memberMock); // Assert - Assert.IsTrue(shouldShow, $"The analyzer will not be shown for symbol '{symbolKind}' and '{typeKind}'"); + Assert.That(shouldShow, $"The analyzer will not be shown for symbol '{symbolKind}' and '{typeKind}'"); } [Test] @@ -145,16 +145,16 @@ public void VerifyReturnsOnlyInterfaceMembers() var analyzer = new MemberImplementsInterfaceAnalyzer(); // Act - var results = analyzer.Analyze(symbol, new AnalyzerContext()); + var results = analyzer.Analyze(symbol, new AnalyzerContext() { AssemblyList = new ILSpyX.AssemblyList(), Language = new CSharpLanguage() }); // Assert - Assert.IsNotNull(results); - Assert.AreEqual(1, results.Count()); + Assert.That(results, Is.Not.Null); + Assert.That(results.Count(), Is.EqualTo(1)); var result = results.FirstOrDefault() as IMethod; - Assert.IsNotNull(result); - Assert.IsNotNull(result.DeclaringTypeDefinition); - Assert.AreEqual(TypeKind.Interface, result.DeclaringTypeDefinition.Kind); - Assert.AreEqual(nameof(ITestInterface), result.DeclaringTypeDefinition.Name); + Assert.That(result, Is.Not.Null); + Assert.That(result.DeclaringTypeDefinition, Is.Not.Null); + Assert.That(result.DeclaringTypeDefinition.Kind, Is.EqualTo(TypeKind.Interface)); + Assert.That(result.DeclaringTypeDefinition.Name, Is.EqualTo(nameof(ITestInterface))); } private ISymbol SetupSymbolForAnalysis(Type type, string methodName) diff --git a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs index 0f9f46cbbf..033deaa1d1 100644 --- a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs @@ -6,9 +6,9 @@ using System.Windows; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpy.Analyzers; -using ICSharpCode.ILSpy.Analyzers.Builtin; using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.Analyzers; +using ICSharpCode.ILSpyX.Analyzers.Builtin; using NUnit.Framework; @@ -42,11 +42,11 @@ public void MainAssemblyUsesSystemStringEmpty() var results = new MethodUsesAnalyzer().Analyze(symbol, context).ToList(); - Assert.IsTrue(results.Count == 1); + Assert.That(results.Count == 1); var field = results.Single() as IField; - Assert.IsNotNull(field); - Assert.IsFalse(field.MetadataToken.IsNil); - Assert.AreEqual(field.FullName, "System.String.Empty"); + Assert.That(field, Is.Not.Null); + Assert.That(!field.MetadataToken.IsNil); + Assert.That("System.String.Empty", Is.EqualTo(field.FullName)); } } } diff --git a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs index 76af5ca9c9..972cb6fc7c 100644 --- a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs @@ -16,19 +16,12 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.TypeSystem.Implementation; -using ICSharpCode.ILSpy.Analyzers; -using ICSharpCode.ILSpy.Analyzers.Builtin; using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.Analyzers; +using ICSharpCode.ILSpyX.Analyzers.Builtin; using NUnit.Framework; @@ -47,7 +40,7 @@ public void Setup() { assemblyList = new AssemblyList(); testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); - testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetPEFileOrNull(), testAssembly.GetAssemblyResolver()); + testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetMetadataFileOrNull(), testAssembly.GetAssemblyResolver()); language = new CSharpLanguage(); } @@ -59,10 +52,10 @@ public void SystemInt32UsedByMainAssembly() var results = new TypeUsedByAnalyzer().Analyze(symbol, context).ToList(); - Assert.IsNotEmpty(results); + Assert.That(results, Is.Not.Empty); var method = results.OfType().SingleOrDefault(m => m.FullName == "ICSharpCode.ILSpy.Tests.Analyzers.TestCases.Main.MainAssembly.UsesInt32"); - Assert.IsNotNull(method); - Assert.IsFalse(method.MetadataToken.IsNil); + Assert.That(method, Is.Not.Null); + Assert.That(!method.MetadataToken.IsNil); } } } diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj index 9178ceb434..79e95586a9 100644 --- a/ILSpy.Tests/ILSpy.Tests.csproj +++ b/ILSpy.Tests/ILSpy.Tests.csproj @@ -2,7 +2,7 @@ - net6.0-windows + net8.0-windows false AutoGeneratedProgram @@ -34,31 +34,33 @@ + - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - + + + diff --git a/ILSpy.Wpf.slnf b/ILSpy.Wpf.slnf index 48681d712b..831214ce7f 100644 --- a/ILSpy.Wpf.slnf +++ b/ILSpy.Wpf.slnf @@ -8,6 +8,7 @@ "ICSharpCode.ILSpyX\\ICSharpCode.ILSpyX.csproj", "ILSpy.BamlDecompiler.Tests\\ILSpy.BamlDecompiler.Tests.csproj", "ILSpy.BamlDecompiler\\ILSpy.BamlDecompiler.csproj", + "ICSharpCode.BamlDecompiler\\ICSharpCode.BamlDecompiler.csproj", "ILSpy.ReadyToRun\\ILSpy.ReadyToRun.csproj", "ILSpy.Tests\\ILSpy.Tests.csproj", "ILSpy\\ILSpy.csproj", diff --git a/ILSpy.sln b/ILSpy.sln index 692222f9ae..604606ee37 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSharpCode.ILSpyX\ICSharpCode.ILSpyX.csproj", "{F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.BamlDecompiler", "ICSharpCode.BamlDecompiler\ICSharpCode.BamlDecompiler.csproj", "{81A30182-3378-4952-8880-F44822390040}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -94,6 +96,10 @@ Global {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.Build.0 = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ILSpy/Analyzers/AnalyzerContext.cs b/ILSpy/Analyzers/AnalyzerContext.cs deleted file mode 100644 index 2e36571032..0000000000 --- a/ILSpy/Analyzers/AnalyzerContext.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2018 Siegfried Pammer -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Concurrent; -using System.Reflection.Metadata; -using System.Threading; - -using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpyX; - -namespace ICSharpCode.ILSpy.Analyzers -{ - /// - /// Provides additional context for analyzers. - /// - public class AnalyzerContext - { - public AssemblyList AssemblyList { get; internal set; } - - /// - /// CancellationToken. Currently Analyzers do not support cancellation from the UI, but it should be checked nonetheless. - /// - public CancellationToken CancellationToken { get; internal set; } - - /// - /// Currently used language. - /// - public Language Language { get; internal set; } - - /// - /// Allows the analyzer to control whether the tree nodes will be sorted. - /// Must be set within - /// before the results are enumerated. - /// - public bool SortResults { get; set; } - - public MethodBodyBlock GetMethodBody(IMethod method) - { - if (!method.HasBody || method.MetadataToken.IsNil) - return null; - var module = method.ParentModule.PEFile; - var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - try - { - return module.Reader.GetMethodBody(md.RelativeVirtualAddress); - } - catch (BadImageFormatException) - { - return null; - } - } - - public AnalyzerScope GetScopeOf(IEntity entity) - { - return new AnalyzerScope(AssemblyList, entity); - } - - readonly ConcurrentDictionary typeSystemCache = new ConcurrentDictionary(); - - public DecompilerTypeSystem GetOrCreateTypeSystem(PEFile module) - { - return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); - } - } -} diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index 782821c47c..38d94c1c59 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -36,19 +36,19 @@ public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; - if (this.Member.MetadataToken.IsNil) + if (this.Member == null || this.Member.MetadataToken.IsNil) { MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); return; } - MainWindow.Instance.JumpToReference(new EntityReference(this.Member.ParentModule.PEFile, this.Member.MetadataToken)); + MainWindow.Instance.JumpToReference(new EntityReference(this.Member.ParentModule.MetadataFile, this.Member.MetadataToken)); } public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { foreach (LoadedAssembly asm in removedAssemblies) { - if (this.Member.ParentModule.PEFile == asm.GetPEFileOrNull()) + if (this.Member.ParentModule.MetadataFile == asm.GetMetadataFileOrNull()) return false; // remove this node } this.Children.RemoveAll( diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs index 6b908d1ffe..490bf5ec2a 100644 --- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs @@ -25,6 +25,7 @@ using ICSharpCode.ILSpy.Analyzers.TreeNodes; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers { diff --git a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs deleted file mode 100644 index 4d1d5bc301..0000000000 --- a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.Diagnostics; - -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.ILSpy.Analyzers.Builtin -{ - /// - /// Finds all extension methods defined for a type. - /// - [ExportAnalyzer(Header = "Extension Methods", Order = 50)] - class TypeExtensionMethodsAnalyzer : IAnalyzer - { - public bool Show(ISymbol symbol) => symbol is ITypeDefinition entity && !entity.IsStatic; - - public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context) - { - Debug.Assert(analyzedSymbol is ITypeDefinition); - var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) - { - foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context)) - yield return result; - } - } - - IEnumerable ScanType(ITypeDefinition analyzedType, ITypeDefinition type, AnalyzerContext context) - { - if (!type.HasExtensionMethods) - yield break; - - foreach (IMethod method in type.Methods) - { - if (!method.IsExtensionMethod) - continue; - - var firstParamType = method.Parameters[0].Type.GetDefinition(); - if (firstParamType != null && - firstParamType.MetadataToken == analyzedType.MetadataToken && - firstParamType.ParentModule.PEFile == analyzedType.ParentModule.PEFile) - yield return method; - } - } - } -} diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs index 923ba56028..8b6ff6f033 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs @@ -24,6 +24,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { using ICSharpCode.Decompiler.TypeSystem; + using ICSharpCode.ILSpyX.Analyzers; internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs index a3619b7bf8..1f2b9b9a3f 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs @@ -21,6 +21,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs index 19ce7fa8e8..b7cee8ede4 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs @@ -21,6 +21,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs index 23bb562e98..9a8558e4cc 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs @@ -18,9 +18,10 @@ using System; using System.Linq; +using System.Windows; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { @@ -51,6 +52,17 @@ protected override void LoadChildren() } } + public override void ActivateItem(RoutedEventArgs e) + { + e.Handled = true; + if (analyzedModule.MetadataFile == null) + { + MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); + return; + } + MainWindow.Instance.JumpToReference(analyzedModule.MetadataFile); + } + public override IEntity Member => null; } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs index d6504f6b97..d19bc3e730 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs @@ -21,6 +21,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs index 52757d1347..6836944eb2 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs @@ -21,6 +21,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Analyzers; namespace ICSharpCode.ILSpy.Analyzers.TreeNodes { diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index d04697de41..0e88f19caa 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -31,6 +31,7 @@ using System.Windows.Threading; using ICSharpCode.ILSpy.Options; +using ICSharpCode.ILSpyX.Analyzers; using ICSharpCode.ILSpyX.Settings; using Microsoft.VisualStudio.Composition; @@ -131,9 +132,13 @@ private static async Task InitializeMef() } } } - // Add the built-in parts + // Add the built-in parts: First, from ILSpyX + var xParts = await discovery.CreatePartsAsync(typeof(IAnalyzer).Assembly); + catalog = catalog.AddParts(xParts); + // Then from ILSpy itself var createdParts = await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()); catalog = catalog.AddParts(createdParts); + // If/When the project switches to .NET Standard/Core, this will be needed to allow metadata interfaces (as opposed // to metadata classes). When running on .NET Framework, it's automatic. // catalog.WithDesktopSupport(); diff --git a/ILSpy/Commands/ExportCommandAttribute.cs b/ILSpy/Commands/ExportCommandAttribute.cs index df72bb0464..282774bff1 100644 --- a/ILSpy/Commands/ExportCommandAttribute.cs +++ b/ILSpy/Commands/ExportCommandAttribute.cs @@ -56,8 +56,6 @@ public interface IMainMenuCommandMetadata string MenuIcon { get; } string Header { get; } string ParentMenuID { get; } - [Obsolete("Please use ParentMenuID instead. We decided to rename the property for clarity. It will be removed in ILSpy 8.0.")] - string Menu { get; } string MenuCategory { get; } string InputGestureText { get; } bool IsEnabled { get; } @@ -93,8 +91,6 @@ public ExportMainMenuCommandAttribute() /// will lead to a stack-overflow and crash of ILSpy at startup. /// public string ParentMenuID { get; set; } - [Obsolete("Please use ParentMenuID instead. We decided to rename the property for clarity. It will be removed in ILSpy 8.0.")] - public string Menu { get => ParentMenuID; set => ParentMenuID = value; } public string MenuCategory { get; set; } public string InputGestureText { get; set; } public bool IsEnabled { get; set; } = true; diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index 84bafc4239..773c7cd4c9 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -27,6 +27,7 @@ using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; @@ -58,7 +59,7 @@ public bool IsVisible(TextViewContext context) internal static void GeneratePdbForAssembly(LoadedAssembly assembly) { - var file = assembly.GetPEFileOrNull(); + var file = assembly.GetMetadataFileOrNull() as PEFile; if (!PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file)) { MessageBox.Show(string.Format(Resources.CannotCreatePDBFile, Path.GetFileName(assembly.FileName))); @@ -80,7 +81,7 @@ internal static void GeneratePdbForAssembly(LoadedAssembly assembly) { try { - var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(), options.DecompilerSettings); + var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences), options.DecompilerSettings); decompiler.CancellationToken = ct; PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream, progress: options.Progress); } diff --git a/ILSpy/Commands/IProtocolHandler.cs b/ILSpy/Commands/IProtocolHandler.cs index 251b6b5f54..53f6e7ef37 100644 --- a/ILSpy/Commands/IProtocolHandler.cs +++ b/ILSpy/Commands/IProtocolHandler.cs @@ -1,18 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Linq; +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System.Reflection.Metadata; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy { public interface IProtocolHandler { - ILSpyTreeNode Resolve(string protocol, PEFile module, Handle handle, out bool newTabPage); + ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage); } } diff --git a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs index a0ca794791..a2a4430be0 100644 --- a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs +++ b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs @@ -16,8 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; using System.Linq; using ICSharpCode.ILSpy.Properties; @@ -44,4 +42,18 @@ public override void Execute(object parameter) } } } + + [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ClearAssemblyList), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)] + class ClearAssemblyList : SimpleCommand + { + public override bool CanExecute(object parameter) + { + return MainWindow.Instance.CurrentAssemblyList?.Count > 0; + } + + public override void Execute(object parameter) + { + MainWindow.Instance.CurrentAssemblyList?.Clear(); + } + } } diff --git a/ILSpy/Commands/SimpleCommand.cs b/ILSpy/Commands/SimpleCommand.cs index 8822482e76..67c7f517e1 100644 --- a/ILSpy/Commands/SimpleCommand.cs +++ b/ILSpy/Commands/SimpleCommand.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.ComponentModel; using System.Windows.Input; namespace ICSharpCode.ILSpy @@ -35,4 +36,39 @@ public virtual bool CanExecute(object parameter) return true; } } + + public abstract class ToggleableCommand : ICommand, INotifyPropertyChanged + { + private bool isChecked; + + public event EventHandler CanExecuteChanged { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public event PropertyChangedEventHandler PropertyChanged; + + void ICommand.Execute(object parameter) + { + IsChecked = Execute(parameter); + } + + public bool IsChecked { + get => isChecked; + set { + if (isChecked != value) + { + isChecked = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsChecked))); + } + } + } + + public abstract bool Execute(object parameter); + + public virtual bool CanExecute(object parameter) + { + return true; + } + } } diff --git a/ILSpy/EntityReference.cs b/ILSpy/EntityReference.cs index 86ebd55a29..d5cfff4040 100644 --- a/ILSpy/EntityReference.cs +++ b/ILSpy/EntityReference.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy [DebuggerDisplay("EntityReference Module={Module}, Handle={Handle}, Protocol={Protocol}")] public class EntityReference { - readonly PEFile? peFile; + readonly MetadataFile? peFile; public string Module { get; } public Handle Handle { get; } public string Protocol { get; } @@ -46,7 +46,7 @@ public EntityReference(string? protocol, string moduleFileName, Handle handle) this.Protocol = protocol ?? "decompile"; } - public EntityReference(PEFile module, Handle handle, string protocol = "decompile") + public EntityReference(MetadataFile module, Handle handle, string protocol = "decompile") { this.peFile = module; this.Module = module.FileName; @@ -54,9 +54,9 @@ public EntityReference(PEFile module, Handle handle, string protocol = "decompil this.Protocol = protocol; } - public PEFile? ResolveAssembly(AssemblyList context) + public MetadataFile? ResolveAssembly(AssemblyList context) { - return peFile ?? context.FindAssembly(Module)?.GetPEFileOrNull(); + return peFile ?? context.FindAssembly(Module)?.GetMetadataFileOrNull(); } } } diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs index f08fc8e117..68c604a0d6 100644 --- a/ILSpy/ExtensionMethods.cs +++ b/ILSpy/ExtensionMethods.cs @@ -19,17 +19,13 @@ #nullable enable using System; -using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; -using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy @@ -76,7 +72,7 @@ public static U[] SelectArray(this ICollection collection, Func f return result; } - public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this PEFile file) + public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this MetadataFile file) { return LoadedAssemblyExtensions.GetLoadedAssembly(file) .GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(MainWindow.Instance.CurrentDecompilerSettings)); diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index d33163bad0..5e8184796c 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -3,7 +3,7 @@ WinExe - net6.0-windows + net8.0-windows win-x64;win-arm64 False false @@ -19,9 +19,14 @@ True ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk true + 1 true + + + + full true @@ -37,15 +42,13 @@ ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.ruleset - - - - - - - - + + + + + + @@ -86,7 +89,9 @@ - + + + diff --git a/ILSpy/Images/ExportOverlay.svg b/ILSpy/Images/ExportOverlay.svg new file mode 100644 index 0000000000..d396359683 --- /dev/null +++ b/ILSpy/Images/ExportOverlay.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Images/ExportOverlay.xaml b/ILSpy/Images/ExportOverlay.xaml new file mode 100644 index 0000000000..387c04fb4e --- /dev/null +++ b/ILSpy/Images/ExportOverlay.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/Header.svg b/ILSpy/Images/Header.svg new file mode 100644 index 0000000000..44056d1b88 --- /dev/null +++ b/ILSpy/Images/Header.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/Header.xaml b/ILSpy/Images/Header.xaml new file mode 100644 index 0000000000..ea115bdd72 --- /dev/null +++ b/ILSpy/Images/Header.xaml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/Heap.svg b/ILSpy/Images/Heap.svg new file mode 100644 index 0000000000..72f0dc2650 --- /dev/null +++ b/ILSpy/Images/Heap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/Heap.xaml b/ILSpy/Images/Heap.xaml new file mode 100644 index 0000000000..2e96c9a8f9 --- /dev/null +++ b/ILSpy/Images/Heap.xaml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index 3222281bae..49dfde0fd6 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -27,6 +27,8 @@ namespace ICSharpCode.ILSpy { static class Images { + private static readonly Rect iconRect = new Rect(0, 0, 16, 16); + static ImageSource Load(string icon) { var image = new DrawingImage(LoadDrawingGroup(null, "Images/" + icon)); @@ -56,6 +58,17 @@ static ImageSource Load(string icon) public static readonly ImageSource ReferenceFolder = Load("ReferenceFolder"); public static readonly ImageSource NuGet = Load(null, "Images/NuGet.png"); + public static readonly ImageSource MetadataFile = Load("MetadataFile"); + public static readonly ImageSource WebAssemblyFile = Load("WebAssembly"); + public static readonly ImageSource ProgramDebugDatabase = Load("ProgramDebugDatabase"); + + public static readonly ImageSource Metadata = Load("Metadata"); + public static readonly ImageSource Heap = Load("Heap"); + public static readonly ImageSource Header = Load("Header"); + public static readonly ImageSource MetadataTable = Load("MetadataTable"); + public static readonly ImageSource MetadataTableGroup = Load("MetadataTableGroup"); + public static readonly ImageSource ListFolder = Load("ListFolder"); + public static readonly ImageSource ListFolderOpen = Load("ListFolder.Open"); public static readonly ImageSource SubTypes = Load("SubTypes"); public static readonly ImageSource SuperTypes = Load("SuperTypes"); @@ -75,6 +88,7 @@ static ImageSource Load(string icon) public static readonly ImageSource Interface = Load("Interface"); public static readonly ImageSource Delegate = Load("Delegate"); public static readonly ImageSource Enum = Load("Enum"); + public static readonly ImageSource Type = Load("ShowPublicOnly"); public static readonly ImageSource Field = Load("Field"); public static readonly ImageSource FieldReadOnly = Load("FieldReadOnly"); @@ -99,9 +113,15 @@ static ImageSource Load(string icon) private static readonly ImageSource OverlayPrivate = Load("OverlayPrivate"); private static readonly ImageSource OverlayPrivateProtected = Load("OverlayPrivateProtected"); private static readonly ImageSource OverlayCompilerControlled = Load("OverlayCompilerControlled"); + private static readonly ImageSource OverlayReference = Load("ReferenceOverlay"); private static readonly ImageSource OverlayStatic = Load("OverlayStatic"); + public static readonly ImageSource TypeReference = GetIcon("ShowPublicOnly", "ReferenceOverlay"); + public static readonly ImageSource MethodReference = GetIcon("Method", "ReferenceOverlay"); + public static readonly ImageSource FieldReference = GetIcon("Field", "ReferenceOverlay"); + public static readonly ImageSource ExportedType = GetIcon("ShowPublicOnly", "ExportOverlay"); + public static ImageSource Load(object part, string icon) { if (icon.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) @@ -192,6 +212,45 @@ public static ImageSource GetIcon(MemberIcon icon, AccessOverlayIcon overlay, bo return memberIconCache.GetIcon(icon, overlay, isStatic); } + private static ImageSource GetIcon(string baseImage, string overlay = null, bool isStatic = false) + { + ImageSource baseImageSource = Load(baseImage); + ImageSource overlayImageSource = overlay != null ? Load(overlay) : null; + + return CreateOverlayImage(baseImageSource, overlayImageSource, isStatic); + } + + private static ImageSource CreateOverlayImage(ImageSource baseImage, ImageSource overlay, bool isStatic) + { + var group = new DrawingGroup(); + + Drawing baseDrawing = new ImageDrawing(baseImage, iconRect); + + if (overlay != null) + { + var nestedGroup = new DrawingGroup { Transform = new ScaleTransform(0.8, 0.8) }; + nestedGroup.Children.Add(baseDrawing); + group.Children.Add(nestedGroup); + group.Children.Add(new ImageDrawing(overlay, iconRect)); + } + else + { + group.Children.Add(baseDrawing); + } + + if (isStatic) + { + group.Children.Add(new ImageDrawing(Images.OverlayStatic, iconRect)); + } + + var image = new DrawingImage(group); + if (image.CanFreeze) + { + image.Freeze(); + } + return image; + } + #region icon caches & overlay management private class TypeIconCache : IconCache @@ -370,39 +429,6 @@ private static ImageSource GetOverlayImage(AccessOverlayIcon overlay) } return overlayImage; } - - private static readonly Rect iconRect = new Rect(0, 0, 16, 16); - - private static ImageSource CreateOverlayImage(ImageSource baseImage, ImageSource overlay, bool isStatic) - { - var group = new DrawingGroup(); - - Drawing baseDrawing = new ImageDrawing(baseImage, iconRect); - - if (overlay != null) - { - var nestedGroup = new DrawingGroup { Transform = new ScaleTransform(0.8, 0.8) }; - nestedGroup.Children.Add(baseDrawing); - group.Children.Add(nestedGroup); - group.Children.Add(new ImageDrawing(overlay, iconRect)); - } - else - { - group.Children.Add(baseDrawing); - } - - if (isStatic) - { - group.Children.Add(new ImageDrawing(Images.OverlayStatic, iconRect)); - } - - var image = new DrawingImage(group); - if (image.CanFreeze) - { - image.Freeze(); - } - return image; - } } #endregion diff --git a/ILSpy/Images/ListFolder.Open.svg b/ILSpy/Images/ListFolder.Open.svg new file mode 100644 index 0000000000..b7b5c2bdce --- /dev/null +++ b/ILSpy/Images/ListFolder.Open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/ListFolder.Open.xaml b/ILSpy/Images/ListFolder.Open.xaml new file mode 100644 index 0000000000..e760832358 --- /dev/null +++ b/ILSpy/Images/ListFolder.Open.xaml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/ListFolder.svg b/ILSpy/Images/ListFolder.svg new file mode 100644 index 0000000000..b9c47a7ddc --- /dev/null +++ b/ILSpy/Images/ListFolder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/ListFolder.xaml b/ILSpy/Images/ListFolder.xaml new file mode 100644 index 0000000000..a154bef400 --- /dev/null +++ b/ILSpy/Images/ListFolder.xaml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/Metadata.svg b/ILSpy/Images/Metadata.svg new file mode 100644 index 0000000000..eb8ff38659 --- /dev/null +++ b/ILSpy/Images/Metadata.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/Metadata.xaml b/ILSpy/Images/Metadata.xaml new file mode 100644 index 0000000000..53d0ab957f --- /dev/null +++ b/ILSpy/Images/Metadata.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/MetadataFile.svg b/ILSpy/Images/MetadataFile.svg new file mode 100644 index 0000000000..ce9cb449ed --- /dev/null +++ b/ILSpy/Images/MetadataFile.svg @@ -0,0 +1,73 @@ + + diff --git a/ILSpy/Images/MetadataFile.xaml b/ILSpy/Images/MetadataFile.xaml new file mode 100644 index 0000000000..5122e7d207 --- /dev/null +++ b/ILSpy/Images/MetadataFile.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/MetadataTable.svg b/ILSpy/Images/MetadataTable.svg new file mode 100644 index 0000000000..b333a0a257 --- /dev/null +++ b/ILSpy/Images/MetadataTable.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/MetadataTable.xaml b/ILSpy/Images/MetadataTable.xaml new file mode 100644 index 0000000000..4866c51a2a --- /dev/null +++ b/ILSpy/Images/MetadataTable.xaml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/MetadataTableGroup.svg b/ILSpy/Images/MetadataTableGroup.svg new file mode 100644 index 0000000000..9af5cdc536 --- /dev/null +++ b/ILSpy/Images/MetadataTableGroup.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/MetadataTableGroup.xaml b/ILSpy/Images/MetadataTableGroup.xaml new file mode 100644 index 0000000000..df2cc7490c --- /dev/null +++ b/ILSpy/Images/MetadataTableGroup.xaml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/ProgramDebugDatabase.svg b/ILSpy/Images/ProgramDebugDatabase.svg new file mode 100644 index 0000000000..4c4e7b2415 --- /dev/null +++ b/ILSpy/Images/ProgramDebugDatabase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images/ProgramDebugDatabase.xaml b/ILSpy/Images/ProgramDebugDatabase.xaml new file mode 100644 index 0000000000..098b63518e --- /dev/null +++ b/ILSpy/Images/ProgramDebugDatabase.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/README.md b/ILSpy/Images/README.md index e258db4880..05dcc6f092 100644 --- a/ILSpy/Images/README.md +++ b/ILSpy/Images/README.md @@ -10,7 +10,7 @@ Icons used in ILSpy: | Back | x | x | VS 2017 Icon Pack (Backward) | | | Class | x | x | VS 2017 Icon Pack (Class) | | | Close | x | x | VS 2017 Icon Pack (Clear) | | -| CollapseAll | x | x | VS 2017 Icon Pack (CollapseAll) | | +| CollapseAll | x | x | VS 2017 Icon Pack (CollapseAll) | | | Constructor | x | x | based on VS 2017 Icon Pack (Method) using a different colour | | | Copy | x | x | VS 2017 Icon Pack (Copy) | | | Delegate | x | x | VS 2017 Icon Pack (Delegate) | | @@ -18,6 +18,7 @@ Icons used in ILSpy: | Enum | x | x | VS 2017 Icon Pack (Enumerator) | | | EnumValue | x | x | VS 2017 Icon Pack (EnumItem) | | | Event | x | x | VS 2017 Icon Pack (Event) | | +| ExportOverlay | x | x | slightly modified VS 2017 Icon Pack (Export) | | | ExtensionMethod | x | x | VS 2017 Icon Pack (ExtensionMethod) | | | Field | x | x | VS 2017 Icon Pack (Field) | | | FieldReadOnly | x | x | VS 2017 Icon Pack (Field) with different color | | @@ -25,10 +26,18 @@ Icons used in ILSpy: | Folder.Closed | x | x | VS 2017 Icon Pack (Folder) | | | Folder.Open | x | x | VS 2017 Icon Pack (FolderOpen) | | | Forward | x | x | VS 2017 Icon Pack (Forward) | | +| Header | x | x | VS 2017 Icon Pack (PageHeader) | | +| Heap | x | x | VS 2017 Icon Pack (Datalist) | | | Indexer | x | x | VS 2017 Icon Pack (Indexer) | | | Interface | x | x | VS 2017 Icon Pack (Interface) | | | Library | x | x | VS 2017 Icon Pack (Library) | | +| ListFolder | x | x | VS 2017 Icon Pack (ListFolder) | | +| ListFolder.Open | x | x | VS 2017 Icon Pack (ListFolderOpen) | | | Literal | x | x | VS 2017 Icon Pack (Literal) | | +| Metadata | x | x | VS 2017 Icon Pack (Metadata) | | +| MetadataFile | x | x | combined ProgramDebugDatabase + Metadata | | +| MetadataTable | x | x | VS 2017 Icon Pack (LinkedTable) | | +| MetadataTableGroup | x | x | VS 2017 Icon Pack (LinkedTableGroup) | | | Method | x | x | VS 2017 Icon Pack (Method) | | | Namespace | x | x | VS 2017 Icon Pack (Namespace) | | | OK | x | x | VS 2017 Icon Pack (StatusOK) | | @@ -42,14 +51,16 @@ Icons used in ILSpy: | OverlayProtectedInternal | x | x | combined OverlayProtected and OverlayInternal | | | OverlayStatic | x | x | custom | | | PInvokeMethod | x | x | based on VS 2017 Icon Pack (ExtensionMethod) with rotated arrow | | +| ProgramDebugDatabase | x | x | VS 2017 Icon Pack (ProgramDebugDatabase) | | | Property | x | x | VS 2017 Icon Pack (Property) | | | ReferenceFolder | x | x | combined VS 2017 Icon Pack (Reference) two times | | +| ReferenceOverlay | x | x | extracted arrow from VS 2017 Icon Pack (TypeShortcut) | | | Refresh | x | x | VS 2017 Icon Pack (Refresh) | | | Resource | x | x | VS 2017 Icon Pack (Document) | | | ResourceImage | x | x | VS 2017 Icon Pack (Image) | | | ResourceResourcesFile | x | x | VS 2017 Icon Pack (LocalResources) | | | ResourceXml | x | x | VS 2017 Icon Pack (XMLFile) | | -| ResourceXsd | x | x | combined VS 2017 Icon Pack (XMLSchema) with the "file symbol in ResourceXslt | | +| ResourceXsd | x | x | combined VS 2017 Icon Pack (XMLSchema) with the file symbol in ResourceXslt | | | ResourceXsl | x | x | VS 2017 Icon Pack (XMLTransformation) | | | ResourceXslt | x | x | VS 2017 Icon Pack (XSLTTemplate) | | | Save | x | x | VS 2017 Icon Pack (Save) | | diff --git a/ILSpy/Images/ReferenceOverlay.svg b/ILSpy/Images/ReferenceOverlay.svg new file mode 100644 index 0000000000..8d6a8ef7af --- /dev/null +++ b/ILSpy/Images/ReferenceOverlay.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + diff --git a/ILSpy/Images/ReferenceOverlay.xaml b/ILSpy/Images/ReferenceOverlay.xaml new file mode 100644 index 0000000000..a07e0cb790 --- /dev/null +++ b/ILSpy/Images/ReferenceOverlay.xaml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/WebAssembly.svg b/ILSpy/Images/WebAssembly.svg new file mode 100644 index 0000000000..f2d67d77a3 --- /dev/null +++ b/ILSpy/Images/WebAssembly.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/WebAssembly.xaml b/ILSpy/Images/WebAssembly.xaml new file mode 100644 index 0000000000..302c838256 --- /dev/null +++ b/ILSpy/Images/WebAssembly.xaml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index b54a161bad..6ad3bb54e3 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -23,8 +23,6 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; -using System.Threading; -using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Highlighting; @@ -64,7 +62,7 @@ protected override ReflectionDisassembler CreateDisassembler(ITextOutput output, }; } - static CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options) + static CSharpDecompiler CreateDecompiler(MetadataFile module, DecompilationOptions options) { CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; @@ -93,7 +91,7 @@ public MixedMethodBodyDisassembler(ITextOutput output, DecompilationOptions opti this.options = options; } - public override void Disassemble(PEFile module, MethodDefinitionHandle handle) + public override void Disassemble(MetadataFile module, MethodDefinitionHandle handle) { try { @@ -113,7 +111,7 @@ public override void Disassemble(PEFile module, MethodDefinitionHandle handle) } } - protected override void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) + protected override void WriteInstruction(ITextOutput output, MetadataFile metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) { int index = sequencePoints.BinarySearch(blob.Offset, seq => seq.Offset); if (index >= 0) diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index b098c8c4ad..a7fc1cb554 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -120,9 +120,9 @@ public override IReadOnlyList LanguageVersions { } } - CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options) + CSharpDecompiler CreateDecompiler(MetadataFile module, DecompilationOptions options) { - CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings); + CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences), options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; decompiler.DebugInfoProvider = module.GetDebugInfoOrNull(); while (decompiler.AstTransforms.Count > transformCount) @@ -148,7 +148,7 @@ void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree synta public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - PEFile assembly = method.ParentModule.PEFile; + MetadataFile assembly = method.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -230,7 +230,7 @@ public void Run(AstNode rootNode, TransformContext context) public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options) { - PEFile assembly = property.ParentModule.PEFile; + MetadataFile assembly = property.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -241,7 +241,7 @@ public override void DecompileProperty(IProperty property, ITextOutput output, D public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options) { - PEFile assembly = field.ParentModule.PEFile; + MetadataFile assembly = field.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -310,7 +310,7 @@ public void Run(AstNode rootNode, TransformContext context) public override void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options) { - PEFile assembly = @event.ParentModule.PEFile; + MetadataFile assembly = @event.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -321,7 +321,7 @@ public override void DecompileEvent(IEvent @event, ITextOutput output, Decompila public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options) { - PEFile assembly = type.ParentModule.PEFile; + MetadataFile assembly = type.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -330,9 +330,9 @@ public override void DecompileType(ITypeDefinition type, ITextOutput output, Dec WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type.MetadataToken), decompiler.TypeSystem); } - void AddReferenceWarningMessage(PEFile module, ITextOutput output) + void AddReferenceWarningMessage(MetadataFile module, ITextOutput output) { - var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetPEFileOrNull() == module); + var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetMetadataFileOrNull() == module); if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.HasErrors) return; string line1 = Properties.Resources.WarningSomeAssemblyReference; @@ -344,7 +344,7 @@ void AddReferenceWarningMessage(PEFile module, ITextOutput output) }); } - void AddReferenceAssemblyWarningMessage(PEFile module, ITextOutput output) + void AddReferenceAssemblyWarningMessage(MetadataFile module, ITextOutput output) { var metadata = module.Metadata; if (!metadata.GetCustomAttributes(Handle.AssemblyDefinition).HasKnownAttribute(metadata, KnownAttribute.ReferenceAssembly)) @@ -353,7 +353,7 @@ void AddReferenceAssemblyWarningMessage(PEFile module, ITextOutput output) AddWarningMessage(module, output, line1); } - void AddWarningMessage(PEFile module, ITextOutput output, string line1, string line2 = null, + void AddWarningMessage(MetadataFile module, ITextOutput output, string line1, string line2 = null, string buttonText = null, System.Windows.Media.ImageSource buttonImage = null, RoutedEventHandler buttonClickHandler = null) { if (output is ISmartTextOutput fancyOutput) @@ -393,7 +393,7 @@ void AddWarningMessage(PEFile module, ITextOutput output, string line1, string l public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null) { return null; @@ -416,7 +416,7 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput base.DecompileAssembly(assembly, output, options); // don't automatically load additional assemblies when an assembly node is selected in the tree view - IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(loadOnDemand: options.FullDecompilation); + IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(loadOnDemand: options.FullDecompilation && options.DecompilerSettings.AutoLoadAssemblyReferences); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings); var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault(); if (globalType != null) @@ -426,39 +426,50 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output.WriteLine(); } var metadata = module.Metadata; - var corHeader = module.Reader.PEHeaders.CorHeader; - var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); - if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) + var corHeader = module.CorHeader; + if (module is PEFile peFile && corHeader != null) { - var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); - if (entrypoint != null) + var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); + if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) { - output.Write("// Entry point: "); - output.WriteReference(entrypoint, EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name)); - output.WriteLine(); + var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); + if (entrypoint != null) + { + output.Write("// Entry point: "); + output.WriteReference(entrypoint, EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name)); + output.WriteLine(); + } + } + output.WriteLine("// Architecture: " + GetPlatformDisplayName(peFile)); + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) + { + output.WriteLine("// This assembly contains unmanaged code."); + } + string runtimeName = GetRuntimeDisplayName(module); + if (runtimeName != null) + { + output.WriteLine("// Runtime: " + runtimeName); + } + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) + { + output.WriteLine("// This assembly is signed with a strong name key."); + } + if (peFile.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible)) + { + output.WriteLine("// This assembly was compiled using the /deterministic option."); + } + if (module.Metadata.MetadataKind != MetadataKind.Ecma335) + { + output.WriteLine("// This assembly was loaded with Windows Runtime projections applied."); } } - output.WriteLine("// Architecture: " + GetPlatformDisplayName(module)); - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) - { - output.WriteLine("// This assembly contains unmanaged code."); - } - string runtimeName = GetRuntimeDisplayName(module); - if (runtimeName != null) - { - output.WriteLine("// Runtime: " + runtimeName); - } - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) - { - output.WriteLine("// This assembly is signed with a strong name key."); - } - if (module.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible)) - { - output.WriteLine("// This assembly was compiled using the /deterministic option."); - } - if (module.Metadata.MetadataKind != MetadataKind.Ecma335) + else { - output.WriteLine("// This assembly was loaded with Windows Runtime projections applied."); + string runtimeName = GetRuntimeDisplayName(module); + if (runtimeName != null) + { + output.WriteLine("// Runtime: " + runtimeName); + } } if (metadata.IsAssembly) { @@ -507,7 +518,7 @@ class ILSpyWholeProjectDecompiler : WholeProjectDecompiler readonly DecompilationOptions options; public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options) - : base(options.DecompilerSettings, assembly.GetAssemblyResolver(), assembly.GetAssemblyReferenceClassifier(options.DecompilerSettings.ApplyWindowsRuntimeProjections), assembly.GetDebugInfoOrNull()) + : base(options.DecompilerSettings, assembly.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences, options.DecompilerSettings.ApplyWindowsRuntimeProjections), null, assembly.GetAssemblyReferenceClassifier(options.DecompilerSettings.ApplyWindowsRuntimeProjections), assembly.GetDebugInfoOrNull()) { this.assembly = assembly; this.options = options; @@ -664,7 +675,7 @@ static string ToCSharpString(MetadataReader metadata, TypeDefinitionHandle handl } } - public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) + public override string GetEntityName(MetadataFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; switch (handle.Kind) @@ -737,7 +748,7 @@ public override string GetEntityName(PEFile module, EntityHandle handle, bool fu public override bool ShowMember(IEntity member) { - PEFile assembly = member.ParentModule.PEFile; + MetadataFile assembly = member.ParentModule.MetadataFile; return showAllMembers || !CSharpDecompiler.MemberIsHidden(assembly, member.MetadataToken, MainWindow.Instance.CurrentDecompilerSettings); } @@ -782,7 +793,7 @@ public override RichText GetRichTextTooltip(IEntity entity) return new RichText(output.ToString(), writer.HighlightingModel); } - public override CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public override CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { return CSharpDecompiler.GetCodeMappingInfo(module, member); } diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index 918558451a..b0f467b4b5 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -18,8 +18,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; @@ -31,8 +29,6 @@ using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; -using static System.Reflection.Metadata.PEReaderExtensions; - using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy @@ -77,7 +73,7 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi { base.DecompileMethod(method, output, options); new ReflectionDisassembler(output, options.CancellationToken) - .DisassembleMethodHeader(method.ParentModule.PEFile, (SRM.MethodDefinitionHandle)method.MetadataToken); + .DisassembleMethodHeader(method.ParentModule.MetadataFile, (SRM.MethodDefinitionHandle)method.MetadataToken); output.WriteLine(); output.WriteLine(); } @@ -89,13 +85,13 @@ public TypedIL() : base("Typed IL") { } public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { base.DecompileMethod(method, output, options); - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; var methodDef = module.Metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken); if (!methodDef.HasBody()) return; var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); ILReader reader = new ILReader(typeSystem.MainModule); - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); reader.WriteTypedIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, output, cancellationToken: options.CancellationToken); } } @@ -112,7 +108,7 @@ public BlockIL(IReadOnlyList transforms) : base("ILAst") public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { base.DecompileMethod(method, output, options); - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; var metadata = module.Metadata; var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken); if (!methodDef.HasBody()) @@ -121,7 +117,7 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi var typeSystem = new DecompilerTypeSystem(module, assemblyResolver); var reader = new ILReader(typeSystem.MainModule); reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols; - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); ILFunction il = reader.ReadIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, kind: ILFunctionKind.TopLevelFunction, cancellationToken: options.CancellationToken); var decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings) { CancellationToken = options.CancellationToken }; ILTransformContext context = decompiler.CreateILTransformContext(il); diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs index 7117785818..95c881bb40 100644 --- a/ILSpy/Languages/ILLanguage.cs +++ b/ILSpy/Languages/ILLanguage.cs @@ -71,7 +71,7 @@ protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = method.ParentModule.PEFile; + MetadataFile module = method.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleMethod(module, (MethodDefinitionHandle)method.MetadataToken); @@ -80,7 +80,7 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = field.ParentModule.PEFile; + MetadataFile module = field.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleField(module, (FieldDefinitionHandle)field.MetadataToken); @@ -89,7 +89,7 @@ public override void DecompileField(IField field, ITextOutput output, Decompilat public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = property.ParentModule.PEFile; + MetadataFile module = property.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleProperty(module, (PropertyDefinitionHandle)property.MetadataToken); @@ -115,7 +115,7 @@ public override void DecompileProperty(IProperty property, ITextOutput output, D public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = ev.ParentModule.PEFile; + MetadataFile module = ev.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleEvent(module, (EventDefinitionHandle)ev.MetadataToken); @@ -146,7 +146,7 @@ public override void DecompileEvent(IEvent ev, ITextOutput output, Decompilation public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = type.ParentModule.PEFile; + MetadataFile module = type.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleType(module, (TypeDefinitionHandle)type.MetadataToken); @@ -155,7 +155,7 @@ public override void DecompileType(ITypeDefinition type, ITextOutput output, Dec public override void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = types.FirstOrDefault()?.ParentModule.PEFile; + MetadataFile module = types.FirstOrDefault()?.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken)); @@ -165,15 +165,16 @@ public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput { output.WriteLine("// " + assembly.FileName); output.WriteLine(); - var module = assembly.GetPEFileAsync().GetAwaiter().GetResult(); - var metadata = module.Metadata; - var dis = CreateDisassembler(output, options); + var module = assembly.GetMetadataFileOrNull(); if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { throw new NotSupportedException($"Language '{Name}' does not support exporting assemblies as projects!"); } + var metadata = module.Metadata; + var dis = CreateDisassembler(output, options); + // don't automatically load additional assemblies when an assembly node is selected in the tree view dis.AssemblyResolver = module.GetAssemblyResolver(loadOnDemand: options.FullDecompilation); dis.DebugInfo = module.GetDebugInfoOrNull(); @@ -196,7 +197,7 @@ public override RichText GetRichTextTooltip(IEntity entity) { var output = new AvalonEditTextOutput() { IgnoreNewLineAndIndent = true }; var disasm = CreateDisassembler(output, MainWindow.Instance.CreateDecompilationOptions()); - PEFile module = entity.ParentModule?.PEFile; + MetadataFile module = entity.ParentModule?.MetadataFile; if (module == null) { return null; diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs index b47acbaad0..26410fe243 100644 --- a/ILSpy/Languages/Language.cs +++ b/ILSpy/Languages/Language.cs @@ -110,7 +110,7 @@ public virtual void DecompileNamespace(string nameSpace, IEnumerable /// This should produce a string representation of the entity for search to match search strings against. /// - public virtual string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) + public virtual string GetEntityName(MetadataFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; switch (handle.Kind) @@ -522,7 +522,7 @@ public virtual string GetEntityName(PEFile module, EntityHandle handle, bool ful } } - public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public virtual CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { var declaringType = (TypeDefinitionHandle)member.GetDeclaringType(module.Metadata); @@ -561,7 +561,7 @@ public static string GetPlatformDisplayName(PEFile module) } } - public static string GetRuntimeDisplayName(PEFile module) + public static string GetRuntimeDisplayName(MetadataFile module) { return module.Metadata.MetadataVersion; } diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index c31d35affe..999abdca36 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -29,6 +29,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Data; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; @@ -53,6 +54,7 @@ using ICSharpCode.ILSpy.Updates; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.FileLoaders; using ICSharpCode.ILSpyX.Settings; using ICSharpCode.TreeView; @@ -151,6 +153,7 @@ public MainWindow() InitMainMenu(); InitWindowMenu(); InitToolbar(); + InitFileLoaders(); ContextMenuProvider.Add(AssemblyTreeView); this.Loaded += MainWindow_Loaded; @@ -299,6 +302,12 @@ void InitMainMenu() } menuItem.IsEnabled = entry.Metadata.IsEnabled; + if (entry.Value is ToggleableCommand toggle) + { + menuItem.IsCheckable = true; + menuItem.SetBinding(MenuItem.IsCheckedProperty, new Binding("IsChecked") { Source = entry.Value, Mode = BindingMode.OneWay }); + } + menuItem.InputGestureText = entry.Metadata.InputGestureText; parentMenuItem.Items.Add(menuItem); } @@ -572,6 +581,19 @@ public void ShowInBottomPane(string title, object content) } #endregion + #region File Loader extensibility + + void InitFileLoaders() + { + // TODO + foreach (var loader in App.ExportProvider.GetExportedValues()) + { + + } + } + + #endregion + #region Message Hook protected override void OnSourceInitialized(EventArgs e) { @@ -703,7 +725,7 @@ async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSp { // FindNamespaceNode() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. - await asm.GetPEFileAsync().Catch(ex => { }); + await asm.GetMetadataFileAsync().Catch(ex => { }); NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName); if (nsNode != null) { @@ -729,7 +751,7 @@ async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSp // Make sure we wait for assemblies being loaded... // BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal await Dispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal); - if (mr != null && mr.ParentModule.PEFile != null) + if (mr != null && mr.ParentModule.MetadataFile != null) { found = true; if (AssemblyTreeView.SelectedItem == initialSelection) @@ -766,7 +788,7 @@ async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSp { // FindNodeByPath() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. - await asm.GetPEFileAsync().Catch(ex => { }); + await asm.GetMetadataFileAsync().Catch(ex => { }); } } node = FindNodeByPath(activeTreeViewPath, true); @@ -803,12 +825,12 @@ internal static IEntity FindEntityInRelevantAssemblies(string navigateTo, IEnume } foreach (LoadedAssembly asm in relevantAssemblies.ToList()) { - var module = asm.GetPEFileOrNull(); + var module = asm.GetMetadataFileOrNull(); if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) { ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType ? new DecompilerTypeSystem(module, module.GetAssemblyResolver()) - : new SimpleCompilation(module, MinimalCorlib.Instance); + : new SimpleCompilation((PEFile)module, MinimalCorlib.Instance); return memberRef == null ? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition : (IEntity)memberRef.Resolve(new SimpleTypeResolveContext(compilation)); @@ -817,14 +839,8 @@ internal static IEntity FindEntityInRelevantAssemblies(string navigateTo, IEnume return null; } - static bool CanResolveTypeInPEFile(PEFile module, ITypeReference typeRef, out EntityHandle typeHandle) + static bool CanResolveTypeInPEFile(MetadataFile module, ITypeReference typeRef, out EntityHandle typeHandle) { - if (module == null) - { - typeHandle = default; - return false; - } - // We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition. if (module.IsReferenceAssembly()) { @@ -1252,7 +1268,7 @@ public ILSpyTreeNode FindTreeNode(object reference) { case LoadedAssembly lasm: return assemblyListTreeNode.FindAssemblyNode(lasm); - case PEFile asm: + case MetadataFile asm: return assemblyListTreeNode.FindAssemblyNode(asm); case Resource res: return assemblyListTreeNode.FindResourceNode(res); @@ -1307,7 +1323,7 @@ public Task JumpToReferenceAsync(object reference, bool inNewTabPage) break; case EntityReference unresolvedEntity: string protocol = unresolvedEntity.Protocol ?? "decompile"; - PEFile file = unresolvedEntity.ResolveAssembly(assemblyList); + var file = unresolvedEntity.ResolveAssembly(assemblyList); if (file == null) { break; @@ -1378,7 +1394,7 @@ void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e) { e.Handled = true; OpenFileDialog dlg = new OpenFileDialog(); - dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd|Nuget Packages (*.nupkg)|*.nupkg|All files|*.*"; + dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*"; dlg.Multiselect = true; dlg.RestoreDirectory = true; if (dlg.ShowDialog() == true) diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs index d7c25fa858..bcce1ef1a4 100644 --- a/ILSpy/Metadata/CoffHeaderTreeNode.cs +++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs @@ -41,7 +41,7 @@ public CoffHeaderTreeNode(PEFile module) public override object Text => "COFF Header"; - public override object Icon => Images.Literal; + public override object Icon => Images.Header; public override bool View(TabPageModel tabPage) { diff --git a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs index 4ad56815d7..43cc98f869 100644 --- a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs @@ -29,14 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class AssemblyRefTableTreeNode : MetadataTableTreeNode { - public AssemblyRefTableTreeNode(PEFile module) - : base(HandleKind.AssemblyReference, module) + public AssemblyRefTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.AssemblyReference, metadataFile) { } - public override object Text => $"23 AssemblyRef ({module.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"23 AssemblyRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,13 +42,12 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; var list = new List(); AssemblyRefEntry scrollTargetEntry = default; - foreach (var row in metadata.AssemblyReferences) + foreach (var row in metadataFile.Metadata.AssemblyReferences) { - AssemblyRefEntry entry = new AssemblyRefEntry(module, row); + AssemblyRefEntry entry = new AssemblyRefEntry(metadataFile, row); if (scrollTarget == MetadataTokens.GetRowNumber(row)) { scrollTargetEntry = entry; @@ -71,9 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct AssemblyRefEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly AssemblyReferenceHandle handle; readonly System.Reflection.Metadata.AssemblyReference assemblyRef; @@ -81,9 +76,9 @@ struct AssemblyRefEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.AssemblyRef) - + metadata.GetTableRowSize(TableIndex.AssemblyRef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.AssemblyRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.AssemblyRef) * (RID - 1); public Version Version => assemblyRef.Version; @@ -101,26 +96,24 @@ public string PublicKeyOrTokenTooltip { get { if (assemblyRef.PublicKeyOrToken.IsNil) return null; - System.Collections.Immutable.ImmutableArray token = metadata.GetBlobContent(assemblyRef.PublicKeyOrToken); + System.Collections.Immutable.ImmutableArray token = metadataFile.Metadata.GetBlobContent(assemblyRef.PublicKeyOrToken); return token.ToHexString(token.Length); } } public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyRef.Name):X} \"{Name}\""; - public string Name => metadata.GetString(assemblyRef.Name); + public string Name => metadataFile.Metadata.GetString(assemblyRef.Name); public string CultureTooltip => $"{MetadataTokens.GetHeapOffset(assemblyRef.Culture):X} \"{Culture}\""; - public string Culture => metadata.GetString(assemblyRef.Culture); + public string Culture => metadataFile.Metadata.GetString(assemblyRef.Culture); - public AssemblyRefEntry(PEFile module, AssemblyReferenceHandle handle) + public AssemblyRefEntry(MetadataFile metadataFile, AssemblyReferenceHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.assemblyRef = metadata.GetAssemblyReference(handle); + this.assemblyRef = metadataFile.Metadata.GetAssemblyReference(handle); } } diff --git a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs index 5d8409657d..f4f2f52ab5 100644 --- a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs @@ -17,7 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -29,14 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class AssemblyTableTreeNode : MetadataTableTreeNode { - public AssemblyTableTreeNode(PEFile module) - : base(HandleKind.AssemblyDefinition, module) + public AssemblyTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.AssemblyDefinition, metadataFile) { } - public override object Text => $"20 Assembly ({module.Metadata.GetTableRowCount(TableIndex.Assembly)})"; - - public override object Icon => Images.Literal; + public override object Text => $"20 Assembly ({metadataFile.Metadata.GetTableRowCount(TableIndex.Assembly)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,9 +41,9 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - if (module.IsAssembly) + if (metadataFile.Metadata.IsAssembly) { - view.ItemsSource = new[] { new AssemblyEntry(module) }; + view.ItemsSource = new[] { new AssemblyEntry(metadataFile.Metadata, metadataFile.MetadataOffset) }; } else { @@ -57,10 +54,9 @@ public override bool View(ViewModels.TabPageModel tabPage) return true; } - struct AssemblyEntry + readonly struct AssemblyEntry { readonly int metadataOffset; - readonly PEFile module; readonly MetadataReader metadata; readonly AssemblyDefinition assembly; @@ -96,11 +92,10 @@ struct AssemblyEntry public string Culture => metadata.GetString(assembly.Culture); - public AssemblyEntry(PEFile module) + public AssemblyEntry(MetadataReader metadata, int metadataOffset) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadata = metadata; + this.metadataOffset = metadataOffset; this.assembly = metadata.GetAssemblyDefinition(); } } diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs index bc939f1bca..6607b16b51 100644 --- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs @@ -23,22 +23,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class ClassLayoutTableTreeNode : MetadataTableTreeNode { - public ClassLayoutTableTreeNode(PEFile module) - : base((HandleKind)0x0F, module) + public ClassLayoutTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x0F, metadataFile) { } - public override object Text => $"0F ClassLayout ({module.Metadata.GetTableRowCount(TableIndex.ClassLayout)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0F ClassLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -46,18 +42,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; var list = new List(); - var length = metadata.GetTableRowCount(TableIndex.ClassLayout); - ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + var length = metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout); + ReadOnlySpan ptr = metadataFile.Metadata.AsReadOnlySpan(); ClassLayoutEntry scrollTargetEntry = default; for (int rid = 1; rid <= length; rid++) { - ClassLayoutEntry entry = new ClassLayoutEntry(module, ptr, metadataOffset, rid); + ClassLayoutEntry entry = new ClassLayoutEntry(metadataFile, ptr, rid); if (scrollTarget == rid) { scrollTargetEntry = entry; @@ -92,8 +86,7 @@ public ClassLayout(ReadOnlySpan ptr, int typeDefSize) struct ClassLayoutEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ClassLayout classLayout; public int RID { get; } @@ -107,11 +100,11 @@ struct ClassLayoutEntry public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, classLayout.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference("metadata", classLayout.Parent)); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, classLayout.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, classLayout.Parent); [ColumnInfo("X4", Kind = ColumnKind.Other)] public ushort PackingSize => classLayout.PackingSize; @@ -119,14 +112,14 @@ public void OnParentClick() [ColumnInfo("X8", Kind = ColumnKind.Other)] public uint ClassSize => classLayout.ClassSize; - public ClassLayoutEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public ClassLayoutEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; + var metadata = metadataFile.Metadata; var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ClassLayout) + metadata.GetTableRowSize(TableIndex.ClassLayout) * (row - 1); - this.Offset = metadataOffset + rowOffset; + this.Offset = metadataFile.MetadataOffset + rowOffset; this.classLayout = new ClassLayout(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4); this.parentTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs index 3f9dc97c8a..f51aa9a85c 100644 --- a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs @@ -21,8 +21,6 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.ViewModels; @@ -30,14 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class ConstantTableTreeNode : MetadataTableTreeNode { - public ConstantTableTreeNode(PEFile module) - : base((HandleKind)0x0B, module) + public ConstantTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x0B, metadataFile) { } - public override object Text => $"0B Constant ({module.Metadata.GetTableRowCount(TableIndex.Constant)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0B Constant ({metadataFile.Metadata.GetTableRowCount(TableIndex.Constant)})"; public override bool View(TabPageModel tabPage) { @@ -45,14 +41,14 @@ public override bool View(TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); ConstantEntry scrollTargetEntry = default; for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++) { - ConstantEntry entry = new ConstantEntry(module, MetadataTokens.ConstantHandle(row)); + ConstantEntry entry = new ConstantEntry(metadataFile, MetadataTokens.ConstantHandle(row)); if (scrollTarget == row) { scrollTargetEntry = entry; @@ -73,9 +69,7 @@ public override bool View(TabPageModel tabPage) struct ConstantEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly EntityHandle handle; readonly Constant constant; @@ -83,9 +77,9 @@ struct ConstantEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Constant) - + metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Constant) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Constant) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public ConstantTypeCode Type => constant.TypeCode; @@ -97,11 +91,11 @@ struct ConstantEntry public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, constant.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, constant.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, constant.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, constant.Parent); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Value => MetadataTokens.GetHeapOffset(constant.Value); @@ -112,13 +106,11 @@ public string ValueTooltip { } } - public ConstantEntry(PEFile module, ConstantHandle handle) + public ConstantEntry(MetadataFile metadataFile, ConstantHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.constant = metadata.GetConstant(handle); + this.constant = metadataFile.Metadata.GetConstant(handle); this.parentTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs index 30a6cf47f0..706a1f34ec 100644 --- a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs @@ -21,22 +21,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class CustomAttributeTableTreeNode : MetadataTableTreeNode { - public CustomAttributeTableTreeNode(PEFile module) - : base(HandleKind.CustomAttribute, module) + public CustomAttributeTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.CustomAttribute, metadataFile) { } - public override object Text => $"0C CustomAttribute ({module.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0C CustomAttribute ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,14 +40,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); CustomAttributeEntry scrollTargetEntry = default; foreach (var row in metadata.CustomAttributes) { - CustomAttributeEntry entry = new CustomAttributeEntry(module, row); + CustomAttributeEntry entry = new CustomAttributeEntry(metadataFile, row); if (scrollTarget == MetadataTokens.GetRowNumber(row)) { scrollTargetEntry = entry; @@ -73,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct CustomAttributeEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly CustomAttributeHandle handle; readonly CustomAttribute customAttr; @@ -83,31 +77,31 @@ struct CustomAttributeEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.CustomAttribute) - + metadata.GetTableRowSize(TableIndex.CustomAttribute) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.CustomAttribute) + + metadataFile.Metadata.GetTableRowSize(TableIndex.CustomAttribute) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Parent => MetadataTokens.GetToken(customAttr.Parent); public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, customAttr.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, customAttr.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, customAttr.Parent); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Constructor => MetadataTokens.GetToken(customAttr.Constructor); public void OnConstructorClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, customAttr.Constructor, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Constructor, protocol: "metadata")); } string constructorTooltip; - public string ConstructorTooltip => GenerateTooltip(ref constructorTooltip, module, customAttr.Constructor); + public string ConstructorTooltip => GenerateTooltip(ref constructorTooltip, metadataFile, customAttr.Constructor); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Value => MetadataTokens.GetHeapOffset(customAttr.Value); @@ -118,13 +112,11 @@ public string ValueTooltip { } } - public CustomAttributeEntry(PEFile module, CustomAttributeHandle handle) + public CustomAttributeEntry(MetadataFile metadataFile, CustomAttributeHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.customAttr = metadata.GetCustomAttribute(handle); + this.customAttr = metadataFile.Metadata.GetCustomAttribute(handle); this.parentTooltip = null; this.constructorTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs index 601b7a8b13..b43a109fd5 100644 --- a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class DeclSecurityTableTreeNode : MetadataTableTreeNode { - public DeclSecurityTableTreeNode(PEFile module) - : base(HandleKind.DeclarativeSecurityAttribute, module) + public DeclSecurityTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.DeclarativeSecurityAttribute, metadataFile) { } - public override object Text => $"0E DeclSecurity ({module.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0E DeclSecurity ({metadataFile.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,14 +41,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); DeclSecurityEntry scrollTargetEntry = default; foreach (var row in metadata.DeclarativeSecurityAttributes) { - var entry = new DeclSecurityEntry(module, row); + var entry = new DeclSecurityEntry(metadataFile, row); if (scrollTarget == MetadataTokens.GetRowNumber(row)) { scrollTargetEntry = entry; @@ -74,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct DeclSecurityEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly DeclarativeSecurityAttributeHandle handle; readonly DeclarativeSecurityAttribute declSecAttr; @@ -84,20 +78,20 @@ struct DeclSecurityEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.DeclSecurity) - + metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.DeclSecurity) + + metadataFile.Metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Parent => MetadataTokens.GetToken(declSecAttr.Parent); public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, declSecAttr.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, declSecAttr.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, declSecAttr.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, declSecAttr.Parent); [ColumnInfo("X8", Kind = ColumnKind.Other)] public DeclarativeSecurityAction Action => declSecAttr.Action; @@ -117,13 +111,11 @@ public string PermissionSetTooltip { } } - public DeclSecurityEntry(PEFile module, DeclarativeSecurityAttributeHandle handle) + public DeclSecurityEntry(MetadataFile metadataFile, DeclarativeSecurityAttributeHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.declSecAttr = metadata.GetDeclarativeSecurityAttribute(handle); + this.declSecAttr = metadataFile.Metadata.GetDeclarativeSecurityAttribute(handle); this.parentTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs index 1d94b78c21..d5b822b79b 100644 --- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class EventMapTableTreeNode : MetadataTableTreeNode { - public EventMapTableTreeNode(PEFile module) - : base((HandleKind)0x12, module) + public EventMapTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x12, metadataFile) { } - public override object Text => $"12 EventMap ({module.Metadata.GetTableRowCount(TableIndex.EventMap)})"; - - public override object Icon => Images.Literal; + public override object Text => $"12 EventMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.EventMap)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,17 +41,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); EventMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.EventMap); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - EventMapEntry entry = new EventMapEntry(module, ptr, metadataOffset, rid); + EventMapEntry entry = new EventMapEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -89,8 +84,7 @@ public EventMap(ReadOnlySpan ptr, int typeDefSize, int eventDefSize) struct EventMapEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly EventMap eventMap; public int RID { get; } @@ -104,33 +98,32 @@ struct EventMapEntry public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, eventMap.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, eventMap.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, eventMap.Parent); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int EventList => MetadataTokens.GetToken(eventMap.EventList); public void OnEventListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, eventMap.EventList, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.EventList, protocol: "metadata")); } string eventListTooltip; - public string EventListTooltip => GenerateTooltip(ref eventListTooltip, module, eventMap.EventList); + public string EventListTooltip => GenerateTooltip(ref eventListTooltip, metadataFile, eventMap.EventList); - public EventMapEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public EventMapEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.EventMap) - + metadata.GetTableRowSize(TableIndex.EventMap) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; - int eventDefSize = metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.EventMap) + + metadataFile.Metadata.GetTableRowSize(TableIndex.EventMap) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; + int eventDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4; this.eventMap = new EventMap(ptr.Slice(rowOffset), typeDefSize, eventDefSize); this.parentTooltip = null; this.eventListTooltip = null; diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs index b24f093dc6..6809520902 100644 --- a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs @@ -22,8 +22,6 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -32,14 +30,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class EventTableTreeNode : MetadataTableTreeNode { - public EventTableTreeNode(PEFile module) - : base(HandleKind.EventDefinition, module) + public EventTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.EventDefinition, metadataFile) { } - public override object Text => $"14 Event ({module.Metadata.GetTableRowCount(TableIndex.Event)})"; - - public override object Icon => Images.Literal; + public override object Text => $"14 Event ({metadataFile.Metadata.GetTableRowCount(TableIndex.Event)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -47,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); EventDefEntry scrollTargetEntry = default; foreach (var row in metadata.EventDefinitions) { - EventDefEntry entry = new EventDefEntry(module, row); + EventDefEntry entry = new EventDefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -76,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct EventDefEntry : IMemberTreeNode { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly EventDefinitionHandle handle; readonly EventDefinition eventDef; @@ -86,9 +80,9 @@ struct EventDefEntry : IMemberTreeNode public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Event) - + metadata.GetTableRowSize(TableIndex.Event) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Event) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Event) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public EventAttributes Attributes => eventDef.Attributes; @@ -99,28 +93,30 @@ struct EventDefEntry : IMemberTreeNode public string NameTooltip => $"{MetadataTokens.GetHeapOffset(eventDef.Name):X} \"{Name}\""; - public string Name => metadata.GetString(eventDef.Name); + public string Name => metadataFile.Metadata.GetString(eventDef.Name); - IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); + IEntity IMemberTreeNode.Member { + get { + return ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle); + } + } [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Type => MetadataTokens.GetToken(eventDef.Type); public void OnTypeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, eventDef.Type, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventDef.Type, protocol: "metadata")); } string typeTooltip; - public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, eventDef.Type); + public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, eventDef.Type); - public EventDefEntry(PEFile module, EventDefinitionHandle handle) + public EventDefEntry(MetadataFile metadataFile, EventDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.eventDef = metadata.GetEventDefinition(handle); + this.eventDef = metadataFile.Metadata.GetEventDefinition(handle); this.typeTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs index b95a5a9e8e..4cf0784658 100644 --- a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs @@ -22,21 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class ExportedTypeTableTreeNode : MetadataTableTreeNode { - public ExportedTypeTableTreeNode(PEFile module) - : base(HandleKind.ExportedType, module) + public ExportedTypeTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.ExportedType, metadataFile) { } - public override object Text => $"27 ExportedType ({module.Metadata.GetTableRowCount(TableIndex.ExportedType)})"; - - public override object Icon => Images.Literal; + public override object Text => $"27 ExportedType ({metadataFile.Metadata.GetTableRowCount(TableIndex.ExportedType)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,13 +41,13 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); ExportedTypeEntry scrollTargetEntry = default; foreach (var row in metadata.ExportedTypes) { - ExportedTypeEntry entry = new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, module, row, metadata.GetExportedType(row)); + ExportedTypeEntry entry = new ExportedTypeEntry(metadataFile, row, metadataFile.Metadata.GetExportedType(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct ExportedTypeEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ExportedTypeHandle handle; readonly ExportedType type; @@ -82,9 +77,9 @@ struct ExportedTypeEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.ExportedType) - + metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ExportedType) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public TypeAttributes Attributes => type.Attributes; @@ -104,28 +99,26 @@ struct ExportedTypeEntry public string TypeNameTooltip => $"{MetadataTokens.GetHeapOffset(type.Name):X} \"{TypeName}\""; - public string TypeName => metadata.GetString(type.Name); + public string TypeName => metadataFile.Metadata.GetString(type.Name); public string TypeNamespaceTooltip => $"{MetadataTokens.GetHeapOffset(type.Namespace):X} \"{TypeNamespace}\""; - public string TypeNamespace => metadata.GetString(type.Namespace); + public string TypeNamespace => metadataFile.Metadata.GetString(type.Namespace); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Implementation => MetadataTokens.GetToken(type.Implementation); public void OnImplementationClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, type.Implementation, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, type.Implementation, protocol: "metadata")); } string implementationTooltip; - public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, module, type.Implementation); + public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, metadataFile, type.Implementation); - public ExportedTypeEntry(int metadataOffset, PEFile module, ExportedTypeHandle handle, ExportedType type) + public ExportedTypeEntry(MetadataFile metadataFile, ExportedTypeHandle handle, ExportedType type) { - this.metadataOffset = metadataOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; this.type = type; this.implementationTooltip = null; diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs index f5da959eb7..38c41bff74 100644 --- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs @@ -23,22 +23,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class FieldLayoutTableTreeNode : MetadataTableTreeNode { - public FieldLayoutTableTreeNode(PEFile module) - : base((HandleKind)0x10, module) + public FieldLayoutTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x10, metadataFile) { } - public override object Text => $"10 FieldLayout ({module.Metadata.GetTableRowCount(TableIndex.FieldLayout)})"; - - public override object Icon => Images.Literal; + public override object Text => $"10 FieldLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldLayout)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -46,17 +42,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); FieldLayoutEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldLayout); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - FieldLayoutEntry entry = new FieldLayoutEntry(module, ptr, metadataOffset, rid); + FieldLayoutEntry entry = new FieldLayoutEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -90,8 +85,7 @@ public FieldLayout(ReadOnlySpan ptr, int fieldDefSize) struct FieldLayoutEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly FieldLayout fieldLayout; public int RID { get; } @@ -105,24 +99,23 @@ struct FieldLayoutEntry public void OnFieldClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, fieldLayout.Field, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldLayout.Field, protocol: "metadata")); } string fieldTooltip; - public string FieldTooltip => GenerateTooltip(ref fieldTooltip, module, fieldLayout.Field); + public string FieldTooltip => GenerateTooltip(ref fieldTooltip, metadataFile, fieldLayout.Field); [ColumnInfo("X8", Kind = ColumnKind.Other)] public int FieldOffset => fieldLayout.Offset; - public FieldLayoutEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public FieldLayoutEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldLayout) - + metadata.GetTableRowSize(TableIndex.FieldLayout) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldLayout) + + metadataFile.Metadata.GetTableRowSize(TableIndex.FieldLayout) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int fieldDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; this.fieldLayout = new FieldLayout(ptr.Slice(rowOffset), fieldDefSize); this.fieldTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs index b6cc9771eb..db20911804 100644 --- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class FieldMarshalTableTreeNode : MetadataTableTreeNode { - public FieldMarshalTableTreeNode(PEFile module) - : base((HandleKind)0x0D, module) + public FieldMarshalTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x0D, metadataFile) { } - public override object Text => $"0D FieldMarshal ({module.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0D FieldMarshal ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,17 +41,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); FieldMarshalEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldMarshal); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - FieldMarshalEntry entry = new FieldMarshalEntry(module, ptr, metadataOffset, rid); + FieldMarshalEntry entry = new FieldMarshalEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -89,8 +84,7 @@ public FieldMarshal(ReadOnlySpan ptr, int blobHeapSize, int hasFieldMarsha struct FieldMarshalEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly FieldMarshal fieldMarshal; public int RID { get; } @@ -104,25 +98,24 @@ struct FieldMarshalEntry public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, fieldMarshal.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldMarshal.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, fieldMarshal.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, fieldMarshal.Parent); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int NativeType => MetadataTokens.GetHeapOffset(fieldMarshal.NativeType); - public FieldMarshalEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public FieldMarshalEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldMarshal) - + metadata.GetTableRowSize(TableIndex.FieldMarshal) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int hasFieldMarshalRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.Field | TableMask.Param); - int blobHeapSize = metadata.GetHeapSize(HeapIndex.Blob) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldMarshal) + + metadataFile.Metadata.GetTableRowSize(TableIndex.FieldMarshal) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int hasFieldMarshalRefSize = metadataFile.Metadata.ComputeCodedTokenSize(32768, TableMask.Field | TableMask.Param); + int blobHeapSize = metadataFile.Metadata.GetHeapSize(HeapIndex.Blob) < ushort.MaxValue ? 2 : 4; this.fieldMarshal = new FieldMarshal(ptr.Slice(rowOffset), blobHeapSize, hasFieldMarshalRefSize); this.parentTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs index dc34c5c23c..43f6e738fe 100644 --- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs @@ -23,22 +23,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class FieldRVATableTreeNode : MetadataTableTreeNode { - public FieldRVATableTreeNode(PEFile module) - : base((HandleKind)0x1D, module) + public FieldRVATableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x1D, metadataFile) { } - public override object Text => $"1D FieldRVA ({module.Metadata.GetTableRowCount(TableIndex.FieldRva)})"; - - public override object Icon => Images.Literal; + public override object Text => $"1D FieldRVA ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldRva)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -46,17 +42,17 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); FieldRVAEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldRva); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + int metadataOffset = metadataFile.MetadataOffset; for (int rid = 1; rid <= length; rid++) { - FieldRVAEntry entry = new FieldRVAEntry(module, ptr, metadataOffset, rid); + FieldRVAEntry entry = new FieldRVAEntry(metadataFile, metadataOffset, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -90,8 +86,7 @@ public FieldRVA(ReadOnlySpan ptr, int fieldDefSize) struct FieldRVAEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly FieldRVA fieldRVA; public int RID { get; } @@ -105,24 +100,23 @@ struct FieldRVAEntry public void OnFieldClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, fieldRVA.Field, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldRVA.Field, protocol: "metadata")); } string fieldTooltip; - public string FieldTooltip => GenerateTooltip(ref fieldTooltip, module, fieldRVA.Field); + public string FieldTooltip => GenerateTooltip(ref fieldTooltip, metadataFile, fieldRVA.Field); [ColumnInfo("X8", Kind = ColumnKind.Other)] public int FieldOffset => fieldRVA.Offset; - public FieldRVAEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public FieldRVAEntry(MetadataFile metadataFile, int metadataOffset, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.FieldRva) - + metadata.GetTableRowSize(TableIndex.FieldRva) * (row - 1); + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.FieldRva) + + metadataFile.Metadata.GetTableRowSize(TableIndex.FieldRva) * (row - 1); this.Offset = metadataOffset + rowOffset; - int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; + int fieldDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; this.fieldRVA = new FieldRVA(ptr.Slice(rowOffset), fieldDefSize); this.fieldTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs index f036661682..16c3ca9d2a 100644 --- a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs @@ -21,13 +21,8 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Threading; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -36,21 +31,19 @@ namespace ICSharpCode.ILSpy.Metadata { internal class FieldTableTreeNode : MetadataTableTreeNode { - public FieldTableTreeNode(PEFile module) - : base(HandleKind.FieldDefinition, module) + public FieldTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.FieldDefinition, metadataFile) { } - public override object Text => $"04 Field ({module.Metadata.GetTableRowCount(TableIndex.Field)})"; - - public override object Icon => Images.Literal; + public override object Text => $"04 Field ({metadataFile.Metadata.GetTableRowCount(TableIndex.Field)})"; public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); @@ -58,7 +51,7 @@ public override bool View(ViewModels.TabPageModel tabPage) foreach (var row in metadata.FieldDefinitions) { - var entry = new FieldDefEntry(module, row); + var entry = new FieldDefEntry(metadataFile, row); if (scrollTarget == entry.RID) { scrollTargetEntry = entry; @@ -80,9 +73,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct FieldDefEntry : IMemberTreeNode { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly FieldDefinitionHandle handle; readonly FieldDefinition fieldDef; @@ -90,9 +81,9 @@ struct FieldDefEntry : IMemberTreeNode public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Field) - + metadata.GetTableRowSize(TableIndex.Field) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Field) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Field) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public FieldAttributes Attributes => fieldDef.Attributes; @@ -104,25 +95,23 @@ struct FieldDefEntry : IMemberTreeNode FlagGroup.CreateMultipleChoiceGroup(typeof(FieldAttributes), "Flags:", (int)otherFlagsMask, (int)(fieldDef.Attributes & otherFlagsMask), includeAll: false), }; - public string Name => metadata.GetString(fieldDef.Name); + public string Name => metadataFile.Metadata.GetString(fieldDef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(fieldDef.Name):X} \"{Name}\""; - IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); + IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Signature => MetadataTokens.GetHeapOffset(fieldDef.Signature); string signatureTooltip; - public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle); + public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle); - public FieldDefEntry(PEFile module, FieldDefinitionHandle handle) + public FieldDefEntry(MetadataFile metadataFile, FieldDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.fieldDef = metadata.GetFieldDefinition(handle); + this.fieldDef = metadataFile.Metadata.GetFieldDefinition(handle); this.signatureTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs index ddf0e51895..183c2a75f5 100644 --- a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs @@ -27,14 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata { class FileTableTreeNode : MetadataTableTreeNode { - public FileTableTreeNode(PEFile module) - : base(HandleKind.AssemblyFile, module) + public FileTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.AssemblyFile, metadataFile) { } - public override object Text => $"26 File ({module.Metadata.GetTableRowCount(TableIndex.File)})"; - - public override object Icon => Images.Literal; + public override object Text => $"26 File ({metadataFile.Metadata.GetTableRowCount(TableIndex.File)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -42,14 +40,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); FileEntry scrollTargetEntry = default; foreach (var row in metadata.AssemblyFiles) { - FileEntry entry = new FileEntry(module, row); + FileEntry entry = new FileEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -71,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct FileEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly AssemblyFileHandle handle; readonly AssemblyFile assemblyFile; @@ -81,16 +77,16 @@ struct FileEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.File) - + metadata.GetTableRowSize(TableIndex.File) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.File) + + metadataFile.Metadata.GetTableRowSize(TableIndex.File) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public int Attributes => assemblyFile.ContainsMetadata ? 1 : 0; public string AttributesTooltip => assemblyFile.ContainsMetadata ? "ContainsMetaData" : "ContainsNoMetaData"; - public string Name => metadata.GetString(assemblyFile.Name); + public string Name => metadataFile.Metadata.GetString(assemblyFile.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(assemblyFile.Name):X} \"{Name}\""; @@ -101,18 +97,16 @@ public string HashValueTooltip { get { if (assemblyFile.HashValue.IsNil) return null; - System.Collections.Immutable.ImmutableArray token = metadata.GetBlobContent(assemblyFile.HashValue); + System.Collections.Immutable.ImmutableArray token = metadataFile.Metadata.GetBlobContent(assemblyFile.HashValue); return token.ToHexString(token.Length); } } - public FileEntry(PEFile module, AssemblyFileHandle handle) + public FileEntry(MetadataFile metadataFile, AssemblyFileHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.assemblyFile = metadata.GetAssemblyFile(handle); + this.assemblyFile = metadataFile.Metadata.GetAssemblyFile(handle); } } diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs index 1f97fdce6f..a65be0a872 100644 --- a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs @@ -21,7 +21,6 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; @@ -29,14 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class GenericParamConstraintTableTreeNode : MetadataTableTreeNode { - public GenericParamConstraintTableTreeNode(PEFile module) - : base(HandleKind.GenericParameterConstraint, module) + public GenericParamConstraintTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.GenericParameterConstraint, metadataFile) { } - public override object Text => $"2C GenericParamConstraint ({module.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})"; - - public override object Icon => Images.Literal; + public override object Text => $"2C GenericParamConstraint ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,14 +41,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); GenericParamConstraintEntry scrollTargetEntry = default; for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) { - GenericParamConstraintEntry entry = new GenericParamConstraintEntry(module, MetadataTokens.GenericParameterConstraintHandle(row)); + GenericParamConstraintEntry entry = new GenericParamConstraintEntry(metadataFile, MetadataTokens.GenericParameterConstraintHandle(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct GenericParamConstraintEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly GenericParameterConstraintHandle handle; readonly GenericParameterConstraint genericParamConstraint; @@ -82,16 +77,16 @@ struct GenericParamConstraintEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.GenericParamConstraint) - + metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.GenericParamConstraint) + + metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Owner => MetadataTokens.GetToken(genericParamConstraint.Parameter); public void OnOwnerClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, genericParamConstraint.Parameter, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Parameter, protocol: "metadata")); } string ownerTooltip; @@ -101,9 +96,9 @@ public string OwnerTooltip { if (ownerTooltip == null) { ITextOutput output = new PlainTextOutput(); - var p = metadata.GetGenericParameter(genericParamConstraint.Parameter); - output.Write("parameter " + p.Index + (p.Name.IsNil ? "" : " (" + metadata.GetString(p.Name) + ")") + " of "); - p.Parent.WriteTo(module, output, default); + var p = metadataFile.Metadata.GetGenericParameter(genericParamConstraint.Parameter); + output.Write("parameter " + p.Index + (p.Name.IsNil ? "" : " (" + metadataFile.Metadata.GetString(p.Name) + ")") + " of "); + p.Parent.WriteTo(metadataFile, output, default); ownerTooltip = output.ToString(); } return ownerTooltip; @@ -115,19 +110,17 @@ public string OwnerTooltip { public void OnTypeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, genericParamConstraint.Type, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Type, protocol: "metadata")); } string typeTooltip; - public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, genericParamConstraint.Type); + public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, genericParamConstraint.Type); - public GenericParamConstraintEntry(PEFile module, GenericParameterConstraintHandle handle) + public GenericParamConstraintEntry(MetadataFile metadataFile, GenericParameterConstraintHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.genericParamConstraint = metadata.GetGenericParameterConstraint(handle); + this.genericParamConstraint = metadataFile.Metadata.GetGenericParameterConstraint(handle); this.ownerTooltip = null; this.typeTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs index 789670a59f..6d8ce43e90 100644 --- a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class GenericParamTableTreeNode : MetadataTableTreeNode { - public GenericParamTableTreeNode(PEFile module) - : base(HandleKind.GenericParameter, module) + public GenericParamTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.GenericParameter, metadataFile) { } - public override object Text => $"2A GenericParam ({module.Metadata.GetTableRowCount(TableIndex.GenericParam)})"; - - public override object Icon => Images.Literal; + public override object Text => $"2A GenericParam ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -49,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); GenericParamEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) { - GenericParamEntry entry = new GenericParamEntry(module, MetadataTokens.GenericParameterHandle(row)); + GenericParamEntry entry = new GenericParamEntry(metadataFile, MetadataTokens.GenericParameterHandle(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct GenericParamEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly GenericParameterHandle handle; readonly GenericParameter genericParam; @@ -82,9 +76,9 @@ struct GenericParamEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.GenericParam) - + metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.GenericParam) + + metadataFile.Metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1); public int Number => genericParam.Index; @@ -101,23 +95,21 @@ struct GenericParamEntry public void OnOwnerClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, genericParam.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParam.Parent, protocol: "metadata")); } string ownerTooltip; - public string OwnerTooltip => GenerateTooltip(ref ownerTooltip, module, genericParam.Parent); + public string OwnerTooltip => GenerateTooltip(ref ownerTooltip, metadataFile, genericParam.Parent); - public string Name => metadata.GetString(genericParam.Name); + public string Name => metadataFile.Metadata.GetString(genericParam.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(genericParam.Name):X} \"{Name}\""; - public GenericParamEntry(PEFile module, GenericParameterHandle handle) + public GenericParamEntry(MetadataFile metadataFile, GenericParameterHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.genericParam = metadata.GetGenericParameter(handle); + this.genericParam = metadataFile.Metadata.GetGenericParameter(handle); this.ownerTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs index 9a7642b25e..2976597b08 100644 --- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs @@ -23,8 +23,6 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using Mono.Cecil; @@ -33,14 +31,12 @@ namespace ICSharpCode.ILSpy.Metadata { class ImplMapTableTreeNode : MetadataTableTreeNode { - public ImplMapTableTreeNode(PEFile module) - : base((HandleKind)0x1C, module) + public ImplMapTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x1C, metadataFile) { } - public override object Text => $"1C ImplMap ({module.Metadata.GetTableRowCount(TableIndex.ImplMap)})"; - - public override object Icon => Images.Literal; + public override object Text => $"1C ImplMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImplMap)})"; @@ -50,17 +46,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); ImplMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.ImplMap); var span = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - ImplMapEntry entry = new ImplMapEntry(module, span, metadataOffset, rid); + ImplMapEntry entry = new ImplMapEntry(metadataFile, span, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -98,8 +93,7 @@ public ImplMap(ReadOnlySpan span, int moduleRefSize, int memberForwardedTa struct ImplMapEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ImplMap implMap; public int RID { get; } @@ -124,38 +118,37 @@ struct ImplMapEntry public void OnMemberForwardedClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, implMap.MemberForwarded, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.MemberForwarded, protocol: "metadata")); } string memberForwardedTooltip; - public string MemberForwardedTooltip => GenerateTooltip(ref memberForwardedTooltip, module, implMap.MemberForwarded); + public string MemberForwardedTooltip => GenerateTooltip(ref memberForwardedTooltip, metadataFile, implMap.MemberForwarded); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int ImportScope => MetadataTokens.GetToken(implMap.ImportScope); public void OnImportScopeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, implMap.ImportScope, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.ImportScope, protocol: "metadata")); } string importScopeTooltip; - public string ImportScopeTooltip => GenerateTooltip(ref importScopeTooltip, module, implMap.ImportScope); + public string ImportScopeTooltip => GenerateTooltip(ref importScopeTooltip, metadataFile, implMap.ImportScope); - public string ImportName => metadata.GetString(implMap.ImportName); + public string ImportName => metadataFile.Metadata.GetString(implMap.ImportName); public string ImportNameTooltip => $"{MetadataTokens.GetHeapOffset(implMap.ImportName):X} \"{ImportName}\""; - public ImplMapEntry(PEFile module, ReadOnlySpan span, int metadataOffset, int row) + public ImplMapEntry(MetadataFile metadataFile, ReadOnlySpan span, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ImplMap) - + metadata.GetTableRowSize(TableIndex.ImplMap) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int moduleRefSize = metadata.GetTableRowCount(TableIndex.ModuleRef) < ushort.MaxValue ? 2 : 4; - int memberForwardedTagRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.MethodDef | TableMask.Field); - int stringHandleSize = metadata.GetHeapSize(HeapIndex.String) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ImplMap) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ImplMap) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int moduleRefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef) < ushort.MaxValue ? 2 : 4; + int memberForwardedTagRefSize = metadataFile.Metadata.ComputeCodedTokenSize(32768, TableMask.MethodDef | TableMask.Field); + int stringHandleSize = metadataFile.Metadata.GetHeapSize(HeapIndex.String) < ushort.MaxValue ? 2 : 4; this.implMap = new ImplMap(span.Slice(rowOffset), moduleRefSize, memberForwardedTagRefSize, stringHandleSize); this.importScopeTooltip = null; this.memberForwardedTooltip = null; diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs index e1ea243bfb..92cefd2c43 100644 --- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class InterfaceImplTableTreeNode : MetadataTableTreeNode { - public InterfaceImplTableTreeNode(PEFile module) - : base((HandleKind)0x09, module) + public InterfaceImplTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x09, metadataFile) { } - public override object Text => $"09 InterfaceImpl ({module.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})"; - - public override object Icon => Images.Literal; + public override object Text => $"09 InterfaceImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,17 +41,17 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); InterfaceImplEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; + int metadataOffset = metadataFile.MetadataOffset; for (int rid = 1; rid <= length; rid++) { - InterfaceImplEntry entry = new InterfaceImplEntry(module, ptr, metadataOffset, rid); + InterfaceImplEntry entry = new InterfaceImplEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -89,8 +85,7 @@ public InterfaceImpl(ReadOnlySpan ptr, int classSize, int interfaceSize) struct InterfaceImplEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly InterfaceImpl interfaceImpl; public int RID { get; } @@ -104,32 +99,31 @@ struct InterfaceImplEntry public void OnClassClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, interfaceImpl.Class, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Class, protocol: "metadata")); } string classTooltip; - public string ClassTooltip => GenerateTooltip(ref classTooltip, module, interfaceImpl.Class); + public string ClassTooltip => GenerateTooltip(ref classTooltip, metadataFile, interfaceImpl.Class); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Interface => MetadataTokens.GetToken(interfaceImpl.Interface); public void OnInterfaceClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, interfaceImpl.Interface, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Interface, protocol: "metadata")); } string interfaceTooltip; - public string InterfaceTooltip => GenerateTooltip(ref interfaceTooltip, module, interfaceImpl.Interface); + public string InterfaceTooltip => GenerateTooltip(ref interfaceTooltip, metadataFile, interfaceImpl.Interface); - public InterfaceImplEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public InterfaceImplEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl) - + metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1); - this.Offset = metadataOffset + rowOffset; - this.interfaceImpl = new InterfaceImpl(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec)); + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl) + + metadataFile.Metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + this.interfaceImpl = new InterfaceImpl(ptr.Slice(rowOffset), metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadataFile.Metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec)); this.interfaceTooltip = null; this.classTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs index 79fd5b76b0..1247899d7d 100644 --- a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class ManifestResourceTableTreeNode : MetadataTableTreeNode { - public ManifestResourceTableTreeNode(PEFile module) - : base(HandleKind.ManifestResource, module) + public ManifestResourceTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.ManifestResource, metadataFile) { } - public override object Text => $"28 ManifestResource ({module.Metadata.GetTableRowCount(TableIndex.ManifestResource)})"; - - public override object Icon => Images.Literal; + public override object Text => $"28 ManifestResource ({metadataFile.Metadata.GetTableRowCount(TableIndex.ManifestResource)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,14 +41,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); ManifestResourceEntry scrollTargetEntry = default; foreach (var row in metadata.ManifestResources) { - ManifestResourceEntry entry = new ManifestResourceEntry(module, row); + ManifestResourceEntry entry = new ManifestResourceEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -74,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct ManifestResourceEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ManifestResourceHandle handle; readonly ManifestResource manifestResource; @@ -84,16 +78,16 @@ struct ManifestResourceEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.ManifestResource) - + metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ManifestResource) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ManifestResource) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public ManifestResourceAttributes Attributes => manifestResource.Attributes; public object AttributesTooltip => manifestResource.Attributes.ToString(); - public string Name => metadata.GetString(manifestResource.Name); + public string Name => metadataFile.Metadata.GetString(manifestResource.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(manifestResource.Name):X} \"{Name}\""; @@ -102,19 +96,17 @@ struct ManifestResourceEntry public void OnImplementationClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, manifestResource.Implementation, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, manifestResource.Implementation, protocol: "metadata")); } string implementationTooltip; - public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, module, manifestResource.Implementation); + public string ImplementationTooltip => GenerateTooltip(ref implementationTooltip, metadataFile, manifestResource.Implementation); - public ManifestResourceEntry(PEFile module, ManifestResourceHandle handle) + public ManifestResourceEntry(MetadataFile metadataFile, ManifestResourceHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.manifestResource = metadata.GetManifestResource(handle); + this.manifestResource = metadataFile.Metadata.GetManifestResource(handle); this.implementationTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs index 01e7806dce..17d368a68a 100644 --- a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs @@ -21,22 +21,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class MemberRefTableTreeNode : MetadataTableTreeNode { - public MemberRefTableTreeNode(PEFile module) - : base(HandleKind.MemberReference, module) + public MemberRefTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.MemberReference, metadataFile) { } - public override object Text => $"0A MemberRef ({module.Metadata.GetTableRowCount(TableIndex.MemberRef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"0A MemberRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.MemberRef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,14 +40,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); MemberRefEntry scrollTargetEntry = default; foreach (var row in metadata.MemberReferences) { - MemberRefEntry entry = new MemberRefEntry(module, row); + MemberRefEntry entry = new MemberRefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -73,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MemberRefEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MemberReferenceHandle handle; readonly MemberReference memberRef; @@ -83,22 +77,22 @@ struct MemberRefEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.MemberRef) - + metadata.GetTableRowSize(TableIndex.MemberRef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MemberRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MemberRef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Parent => MetadataTokens.GetToken(memberRef.Parent); public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, memberRef.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, memberRef.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, memberRef.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, memberRef.Parent); - public string Name => metadata.GetString(memberRef.Name); + public string Name => metadataFile.Metadata.GetString(memberRef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(memberRef.Name):X} \"{Name}\""; @@ -106,15 +100,13 @@ public void OnParentClick() public int Signature => MetadataTokens.GetHeapOffset(memberRef.Signature); string signatureTooltip; - public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle); + public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle); - public MemberRefEntry(PEFile module, MemberReferenceHandle handle) + public MemberRefEntry(MetadataFile metadataFile, MemberReferenceHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.memberRef = metadata.GetMemberReference(handle); + this.memberRef = metadataFile.Metadata.GetMemberReference(handle); this.signatureTooltip = null; this.parentTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs index 24b93afd00..e694704803 100644 --- a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs @@ -21,22 +21,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class MethodImplTableTreeNode : MetadataTableTreeNode { - public MethodImplTableTreeNode(PEFile module) - : base((HandleKind)0x19, module) + public MethodImplTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x19, metadataFile) { } - public override object Text => $"19 MethodImpl ({module.Metadata.GetTableRowCount(TableIndex.MethodImpl)})"; - - public override object Icon => Images.Literal; + public override object Text => $"19 MethodImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -48,9 +44,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); MethodImplEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) { - MethodImplEntry entry = new MethodImplEntry(module, MetadataTokens.MethodImplementationHandle(row)); + MethodImplEntry entry = new MethodImplEntry(metadataFile, MetadataTokens.MethodImplementationHandle(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MethodImplEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MethodImplementationHandle handle; readonly MethodImplementation methodImpl; @@ -82,50 +76,48 @@ struct MethodImplEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.MethodDef) - + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int MethodDeclaration => MetadataTokens.GetToken(methodImpl.MethodDeclaration); public void OnMethodDeclarationClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.MethodDeclaration, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodDeclaration, protocol: "metadata")); } string methodDeclarationTooltip; - public string MethodDeclarationTooltip => GenerateTooltip(ref methodDeclarationTooltip, module, methodImpl.MethodDeclaration); + public string MethodDeclarationTooltip => GenerateTooltip(ref methodDeclarationTooltip, metadataFile, methodImpl.MethodDeclaration); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int MethodBody => MetadataTokens.GetToken(methodImpl.MethodBody); public void OnMethodBodyClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.MethodBody, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodBody, protocol: "metadata")); } string methodBodyTooltip; - public string MethodBodyTooltip => GenerateTooltip(ref methodBodyTooltip, module, methodImpl.MethodBody); + public string MethodBodyTooltip => GenerateTooltip(ref methodBodyTooltip, metadataFile, methodImpl.MethodBody); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Type => MetadataTokens.GetToken(methodImpl.Type); public void OnTypeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, methodImpl.Type, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.Type, protocol: "metadata")); } string typeTooltip; - public string TypeTooltip => GenerateTooltip(ref typeTooltip, module, methodImpl.Type); + public string TypeTooltip => GenerateTooltip(ref typeTooltip, metadataFile, methodImpl.Type); - public MethodImplEntry(PEFile module, MethodImplementationHandle handle) + public MethodImplEntry(MetadataFile metadataFile, MethodImplementationHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.methodImpl = metadata.GetMethodImplementation(handle); + this.methodImpl = metadataFile.Metadata.GetMethodImplementation(handle); this.typeTooltip = null; this.methodBodyTooltip = null; this.methodDeclarationTooltip = null; diff --git a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs index 3f3ab38dfc..4234733671 100644 --- a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class MethodSemanticsTableTreeNode : MetadataTableTreeNode { - public MethodSemanticsTableTreeNode(PEFile module) - : base((HandleKind)0x18, module) + public MethodSemanticsTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x18, metadataFile) { } - public override object Text => $"18 MethodSemantics ({module.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})"; - - public override object Icon => Images.Literal; + public override object Text => $"18 MethodSemantics ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,14 +41,13 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; var list = new List(); MethodSemanticsEntry scrollTargetEntry = default; - foreach (var row in metadata.GetMethodSemantics()) + foreach (var row in metadataFile.Metadata.GetMethodSemantics()) { - MethodSemanticsEntry entry = new MethodSemanticsEntry(module, row.Handle, row.Semantics, row.Method, row.Association); + MethodSemanticsEntry entry = new MethodSemanticsEntry(metadataFile, row.Handle, row.Semantics, row.Method, row.Association); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -74,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MethodSemanticsEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly Handle handle; readonly MethodSemanticsAttributes semantics; readonly MethodDefinitionHandle method; @@ -86,9 +79,9 @@ struct MethodSemanticsEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.MethodDef) - + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public MethodSemanticsAttributes Semantics => semantics; @@ -100,28 +93,26 @@ struct MethodSemanticsEntry public void OnMethodClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, method, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, method, protocol: "metadata")); } string methodTooltip; - public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, method); + public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, method); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Association => MetadataTokens.GetToken(association); public void OnAssociationClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, association, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, association, protocol: "metadata")); } string associationTooltip; - public string AssociationTooltip => GenerateTooltip(ref associationTooltip, module, association); + public string AssociationTooltip => GenerateTooltip(ref associationTooltip, metadataFile, association); - public MethodSemanticsEntry(PEFile module, Handle handle, MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association) + public MethodSemanticsEntry(MetadataFile metadataFile, Handle handle, MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; this.semantics = semantics; this.method = method; diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs index c050dbc58a..64b6b5ee5f 100644 --- a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs @@ -22,21 +22,18 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class MethodSpecTableTreeNode : MetadataTableTreeNode { - public MethodSpecTableTreeNode(PEFile module) - : base(HandleKind.MethodSpecification, module) + public MethodSpecTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.MethodSpecification, metadataFile) { } - public override object Text => $"2B MethodSpec ({module.Metadata.GetTableRowCount(TableIndex.MethodSpec)})"; - - public override object Icon => Images.Literal; + public override object Text => $"2B MethodSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSpec)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -44,14 +41,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); MethodSpecEntry scrollTargetEntry = default; foreach (var row in metadata.GetMethodSpecifications()) { - MethodSpecEntry entry = new MethodSpecEntry(module, row); + MethodSpecEntry entry = new MethodSpecEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -73,9 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MethodSpecEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MethodSpecificationHandle handle; readonly MethodSpecification methodSpec; @@ -83,20 +78,20 @@ struct MethodSpecEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.MethodSpec) - + metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodSpec) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Method => MetadataTokens.GetToken(methodSpec.Method); public void OnMethodClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, methodSpec.Method, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodSpec.Method, protocol: "metadata")); } string methodTooltip; - public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, methodSpec.Method); + public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, methodSpec.Method); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Signature => MetadataTokens.GetHeapOffset(methodSpec.Signature); @@ -104,7 +99,7 @@ public void OnMethodClick() public string SignatureTooltip { get { ITextOutput output = new PlainTextOutput(); - var signature = methodSpec.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), default); + var signature = methodSpec.DecodeSignature(new DisassemblerSignatureTypeProvider(metadataFile, output), default); bool first = true; foreach (var type in signature) { @@ -118,13 +113,11 @@ public string SignatureTooltip { } } - public MethodSpecEntry(PEFile module, MethodSpecificationHandle handle) + public MethodSpecEntry(MetadataFile metadataFile, MethodSpecificationHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.methodSpec = metadata.GetMethodSpecification(handle); + this.methodSpec = metadataFile.Metadata.GetMethodSpecification(handle); this.methodTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs index d2a55ae612..eaa49d1d6c 100644 --- a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs @@ -16,18 +16,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Windows.Controls; -using System.Windows.Threading; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -36,14 +31,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class MethodTableTreeNode : MetadataTableTreeNode { - public MethodTableTreeNode(PEFile module) - : base(HandleKind.MethodDefinition, module) + public MethodTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.MethodDefinition, metadataFile) { } - public override object Text => $"06 Method ({module.Metadata.GetTableRowCount(TableIndex.MethodDef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"06 Method ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -51,13 +44,13 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); MethodDefEntry scrollTargetEntry = default; foreach (var row in metadata.MethodDefinitions) { - MethodDefEntry entry = new MethodDefEntry(module, row); + MethodDefEntry entry = new MethodDefEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -79,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MethodDefEntry : IMemberTreeNode { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MethodDefinitionHandle handle; readonly MethodDefinition methodDef; @@ -89,9 +80,9 @@ struct MethodDefEntry : IMemberTreeNode public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.MethodDef) - + metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public MethodAttributes Attributes => methodDef.Attributes; @@ -114,7 +105,7 @@ struct MethodDefEntry : IMemberTreeNode public int RVA => methodDef.RelativeVirtualAddress; - public string Name => metadata.GetString(methodDef.Name); + public string Name => metadataFile.Metadata.GetString(methodDef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(methodDef.Name):X} \"{Name}\""; @@ -123,14 +114,14 @@ struct MethodDefEntry : IMemberTreeNode string signatureTooltip; - public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle); + public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int ParamList => MetadataTokens.GetToken(methodDef.GetParameters().FirstOrDefault()); public void OnParamListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata")); } string paramListTooltip; @@ -139,19 +130,17 @@ public string ParamListTooltip { var param = methodDef.GetParameters().FirstOrDefault(); if (param.IsNil) return null; - return GenerateTooltip(ref paramListTooltip, module, param); + return GenerateTooltip(ref paramListTooltip, metadataFile, param); } } - IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); + IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule)?.GetDefinition(handle); - public MethodDefEntry(PEFile module, MethodDefinitionHandle handle) + public MethodDefEntry(MetadataFile metadataFile, MethodDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.methodDef = metadata.GetMethodDefinition(handle); + this.methodDef = metadataFile.Metadata.GetMethodDefinition(handle); this.signatureTooltip = null; this.paramListTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs index 987471e855..8ef4ab4f6e 100644 --- a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs @@ -27,14 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class ModuleRefTableTreeNode : MetadataTableTreeNode { - public ModuleRefTableTreeNode(PEFile module) - : base(HandleKind.ModuleReference, module) + public ModuleRefTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.ModuleReference, metadataFile) { } - public override object Text => $"1A ModuleRef ({module.Metadata.GetTableRowCount(TableIndex.ModuleRef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"1A ModuleRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -42,14 +40,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); ModuleRefEntry scrollTargetEntry = default; foreach (var row in metadata.GetModuleReferences()) { - ModuleRefEntry entry = new ModuleRefEntry(module, row); + ModuleRefEntry entry = new ModuleRefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -71,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct ModuleRefEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ModuleReferenceHandle handle; readonly ModuleReference moduleRef; @@ -81,21 +77,19 @@ struct ModuleRefEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.ModuleRef) - + metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ModuleRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1); - public string Name => metadata.GetString(moduleRef.Name); + public string Name => metadataFile.Metadata.GetString(moduleRef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleRef.Name):X} \"{Name}\""; - public ModuleRefEntry(PEFile module, ModuleReferenceHandle handle) + public ModuleRefEntry(MetadataFile metadataFile, ModuleReferenceHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.moduleRef = metadata.GetModuleReference(handle); + this.moduleRef = metadataFile.Metadata.GetModuleReference(handle); } } diff --git a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs index ba65094264..6073d85bbf 100644 --- a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs @@ -27,14 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class ModuleTableTreeNode : MetadataTableTreeNode { - public ModuleTableTreeNode(PEFile module) - : base(HandleKind.ModuleDefinition, module) + public ModuleTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.ModuleDefinition, metadataFile) { } - public override object Text => $"00 Module ({module.Metadata.GetTableRowCount(TableIndex.Module)})"; - - public override object Icon => Images.Literal; + public override object Text => $"00 Module ({metadataFile.Metadata.GetTableRowCount(TableIndex.Module)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -46,7 +44,7 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); ModuleEntry scrollTargetEntry = default; - list.Add(new ModuleEntry(module, EntityHandle.ModuleDefinition)); + list.Add(new ModuleEntry(metadataFile, EntityHandle.ModuleDefinition)); view.ItemsSource = list; @@ -62,9 +60,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct ModuleEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ModuleDefinitionHandle handle; readonly ModuleDefinition moduleDef; @@ -72,38 +68,36 @@ struct ModuleEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Module) - + metadata.GetTableRowSize(TableIndex.Module) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Module) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Module) * (RID - 1); public int Generation => moduleDef.Generation; - public string Name => metadata.GetString(moduleDef.Name); + public string Name => metadataFile.Metadata.GetString(moduleDef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(moduleDef.Name):X} \"{Name}\""; [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Mvid => MetadataTokens.GetHeapOffset(moduleDef.Mvid); - public string MvidTooltip => metadata.GetGuid(moduleDef.Mvid).ToString(); + public string MvidTooltip => metadataFile.Metadata.GetGuid(moduleDef.Mvid).ToString(); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int GenerationId => MetadataTokens.GetHeapOffset(moduleDef.GenerationId); - public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadata.GetGuid(moduleDef.GenerationId).ToString(); + public string GenerationIdTooltip => moduleDef.GenerationId.IsNil ? null : metadataFile.Metadata.GetGuid(moduleDef.GenerationId).ToString(); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int BaseGenerationId => MetadataTokens.GetHeapOffset(moduleDef.BaseGenerationId); - public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadata.GetGuid(moduleDef.BaseGenerationId).ToString(); + public string BaseGenerationIdTooltip => moduleDef.BaseGenerationId.IsNil ? null : metadataFile.Metadata.GetGuid(moduleDef.BaseGenerationId).ToString(); - public ModuleEntry(PEFile module, ModuleDefinitionHandle handle) + public ModuleEntry(MetadataFile metadataFile, ModuleDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.moduleDef = metadata.GetModuleDefinition(); + this.moduleDef = metadataFile.Metadata.GetModuleDefinition(); } } diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs index acdcaad8f5..d75043bfa2 100644 --- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class NestedClassTableTreeNode : MetadataTableTreeNode { - public NestedClassTableTreeNode(PEFile module) - : base((HandleKind)0x29, module) + public NestedClassTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x29, metadataFile) { } - public override object Text => $"29 NestedClass ({module.Metadata.GetTableRowCount(TableIndex.NestedClass)})"; - - public override object Icon => Images.Literal; + public override object Text => $"29 NestedClass ({metadataFile.Metadata.GetTableRowCount(TableIndex.NestedClass)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,17 +41,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); NestedClassEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.NestedClass); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - NestedClassEntry entry = new NestedClassEntry(module, ptr, metadataOffset, rid); + NestedClassEntry entry = new NestedClassEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -89,8 +84,7 @@ public NestedClass(ReadOnlySpan ptr, int typeDefSize) struct NestedClassEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly NestedClass nestedClass; public int RID { get; } @@ -104,32 +98,31 @@ struct NestedClassEntry public void OnNestedClassClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, nestedClass.Nested, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Nested, protocol: "metadata")); } string nestedClassTooltip; - public string NestedClassTooltip => GenerateTooltip(ref nestedClassTooltip, module, nestedClass.Nested); + public string NestedClassTooltip => GenerateTooltip(ref nestedClassTooltip, metadataFile, nestedClass.Nested); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int EnclosingClass => MetadataTokens.GetToken(nestedClass.Enclosing); public void OnEnclosingClassClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, nestedClass.Enclosing, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Enclosing, protocol: "metadata")); } string enclosingClassTooltip; - public string EnclosingClassTooltip => GenerateTooltip(ref enclosingClassTooltip, module, nestedClass.Enclosing); + public string EnclosingClassTooltip => GenerateTooltip(ref enclosingClassTooltip, metadataFile, nestedClass.Enclosing); - public NestedClassEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public NestedClassEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.NestedClass) - + metadata.GetTableRowSize(TableIndex.NestedClass) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.NestedClass) + + metadataFile.Metadata.GetTableRowSize(TableIndex.NestedClass) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; this.nestedClass = new NestedClass(ptr.Slice(rowOffset), typeDefSize); this.nestedClassTooltip = null; this.enclosingClassTooltip = null; diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs index 5fee320ee6..0d69aa9d18 100644 --- a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs @@ -28,14 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class ParamTableTreeNode : MetadataTableTreeNode { - public ParamTableTreeNode(PEFile module) - : base(HandleKind.Parameter, module) + public ParamTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.Parameter, metadataFile) { } - public override object Text => $"08 Param ({module.Metadata.GetTableRowCount(TableIndex.Param)})"; - - public override object Icon => Images.Literal; + public override object Text => $"08 Param ({metadataFile.Metadata.GetTableRowCount(TableIndex.Param)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -47,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); ParamEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++) + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.Param); row++) { - ParamEntry entry = new ParamEntry(module, MetadataTokens.ParameterHandle(row)); + ParamEntry entry = new ParamEntry(metadataFile, MetadataTokens.ParameterHandle(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -71,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct ParamEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ParameterHandle handle; readonly Parameter param; @@ -81,9 +77,9 @@ struct ParamEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Param) - + metadata.GetTableRowSize(TableIndex.Param) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Param) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Param) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public ParameterAttributes Attributes => param.Attributes; @@ -92,19 +88,17 @@ struct ParamEntry FlagGroup.CreateMultipleChoiceGroup(typeof(ParameterAttributes), selectedValue: (int)param.Attributes, includeAll: false) }; - public string Name => metadata.GetString(param.Name); + public string Name => metadataFile.Metadata.GetString(param.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(param.Name):X} \"{Name}\""; public int Sequence => param.SequenceNumber; - public ParamEntry(PEFile module, ParameterHandle handle) + public ParamEntry(MetadataFile metadataFile, ParameterHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.param = metadata.GetParameter(handle); + this.param = metadataFile.Metadata.GetParameter(handle); } } diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs index d07b126c49..1a7897ae3a 100644 --- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs @@ -22,22 +22,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class PropertyMapTableTreeNode : MetadataTableTreeNode { - public PropertyMapTableTreeNode(PEFile module) - : base((HandleKind)0x15, module) + public PropertyMapTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x15, metadataFile) { } - public override object Text => $"15 PropertyMap ({module.Metadata.GetTableRowCount(TableIndex.PropertyMap)})"; - - public override object Icon => Images.Literal; + public override object Text => $"15 PropertyMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.PropertyMap)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -45,17 +41,16 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); PropertyMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.PropertyMap); ReadOnlySpan ptr = metadata.AsReadOnlySpan(); - int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - PropertyMapEntry entry = new PropertyMapEntry(module, ptr, metadataOffset, rid); + PropertyMapEntry entry = new PropertyMapEntry(metadataFile, ptr, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -89,8 +84,7 @@ public PropertyMap(ReadOnlySpan ptr, int typeDefSize, int propertyDefSize) struct PropertyMapEntry { - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly PropertyMap propertyMap; public int RID { get; } @@ -104,33 +98,32 @@ struct PropertyMapEntry public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, propertyMap.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, propertyMap.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, propertyMap.Parent); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int PropertyList => MetadataTokens.GetToken(propertyMap.PropertyList); public void OnPropertyListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, propertyMap.PropertyList, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.PropertyList, protocol: "metadata")); } string propertyListTooltip; - public string PropertyListTooltip => GenerateTooltip(ref propertyListTooltip, module, propertyMap.PropertyList); + public string PropertyListTooltip => GenerateTooltip(ref propertyListTooltip, metadataFile, propertyMap.PropertyList); - public PropertyMapEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) + public PropertyMapEntry(MetadataFile metadataFile, ReadOnlySpan ptr, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - var rowOffset = metadata.GetTableMetadataOffset(TableIndex.PropertyMap) - + metadata.GetTableRowSize(TableIndex.PropertyMap) * (row - 1); - this.Offset = metadataOffset + rowOffset; - int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; - int propertyDefSize = metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4; + var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.PropertyMap) + + metadataFile.Metadata.GetTableRowSize(TableIndex.PropertyMap) * (row - 1); + this.Offset = metadataFile.MetadataOffset + rowOffset; + int typeDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; + int propertyDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4; this.propertyMap = new PropertyMap(ptr.Slice(rowOffset), typeDefSize, propertyDefSize); this.propertyListTooltip = null; this.parentTooltip = null; diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs index 8240c2ac59..65209e85c0 100644 --- a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs @@ -22,8 +22,6 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -32,14 +30,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class PropertyTableTreeNode : MetadataTableTreeNode { - public PropertyTableTreeNode(PEFile module) - : base(HandleKind.PropertyDefinition, module) + public PropertyTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.PropertyDefinition, metadataFile) { } - public override object Text => $"17 Property ({module.Metadata.GetTableRowCount(TableIndex.Property)})"; - - public override object Icon => Images.Literal; + public override object Text => $"17 Property ({metadataFile.Metadata.GetTableRowCount(TableIndex.Property)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -47,14 +43,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); PropertyDefEntry scrollTargetEntry = default; foreach (var row in metadata.PropertyDefinitions) { - PropertyDefEntry entry = new PropertyDefEntry(module, row); + PropertyDefEntry entry = new PropertyDefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -76,9 +72,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct PropertyDefEntry : IMemberTreeNode { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly PropertyDefinitionHandle handle; readonly PropertyDefinition propertyDef; @@ -86,9 +80,9 @@ struct PropertyDefEntry : IMemberTreeNode public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.Property) - + metadata.GetTableRowSize(TableIndex.Property) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Property) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Property) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public PropertyAttributes Attributes => propertyDef.Attributes; @@ -97,25 +91,23 @@ struct PropertyDefEntry : IMemberTreeNode FlagGroup.CreateMultipleChoiceGroup(typeof(PropertyAttributes), selectedValue: (int)propertyDef.Attributes, includeAll: false), }; - public string Name => metadata.GetString(propertyDef.Name); + public string Name => metadataFile.Metadata.GetString(propertyDef.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(propertyDef.Name):X} \"{Name}\""; - IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); + IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Signature => MetadataTokens.GetHeapOffset(propertyDef.Signature); string signatureTooltip; - public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle); + public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle); - public PropertyDefEntry(PEFile module, PropertyDefinitionHandle handle) + public PropertyDefEntry(MetadataFile metadataFile, PropertyDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.propertyDef = metadata.GetPropertyDefinition(handle); + this.propertyDef = metadataFile.Metadata.GetPropertyDefinition(handle); this.signatureTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs index 0e618aad21..476ace7441 100644 --- a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs @@ -21,22 +21,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { class StandAloneSigTableTreeNode : MetadataTableTreeNode { - public StandAloneSigTableTreeNode(PEFile module) - : base(HandleKind.StandaloneSignature, module) + public StandAloneSigTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.StandaloneSignature, metadataFile) { } - public override object Text => $"11 StandAloneSig ({module.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})"; - - public override object Icon => Images.Literal; + public override object Text => $"11 StandAloneSig ({metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -48,9 +44,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); StandAloneSigEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) { - StandAloneSigEntry entry = new StandAloneSigEntry(module, MetadataTokens.StandaloneSignatureHandle(row)); + StandAloneSigEntry entry = new StandAloneSigEntry(metadataFile, MetadataTokens.StandaloneSignatureHandle(row)); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct StandAloneSigEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly StandaloneSignatureHandle handle; readonly StandaloneSignature standaloneSig; @@ -82,23 +76,21 @@ struct StandAloneSigEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.StandAloneSig) - + metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StandAloneSig) + + metadataFile.Metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Signature => MetadataTokens.GetHeapOffset(standaloneSig.Signature); string signatureTooltip; - public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, module, handle); + public string SignatureTooltip => GenerateTooltip(ref signatureTooltip, metadataFile, handle); - public StandAloneSigEntry(PEFile module, StandaloneSignatureHandle handle) + public StandAloneSigEntry(MetadataFile metadataFile, StandaloneSignatureHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.standaloneSig = metadata.GetStandaloneSignature(handle); + this.standaloneSig = metadataFile.Metadata.GetStandaloneSignature(handle); this.signatureTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs index 3388a244ae..0155d1e53a 100644 --- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs @@ -24,7 +24,6 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -33,14 +32,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class TypeDefTableTreeNode : MetadataTableTreeNode { - public TypeDefTableTreeNode(PEFile module) - : base(HandleKind.TypeDefinition, module) + public TypeDefTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.TypeDefinition, metadataFile) { } - public override object Text => $"02 TypeDef ({module.Metadata.GetTableRowCount(TableIndex.TypeDef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"02 TypeDef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -48,14 +45,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); TypeDefEntry scrollTargetEntry = default; foreach (var row in metadata.TypeDefinitions) { - TypeDefEntry entry = new TypeDefEntry(module, row); + TypeDefEntry entry = new TypeDefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -77,9 +74,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct TypeDefEntry : IMemberTreeNode { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly TypeDefinitionHandle handle; readonly TypeDefinition typeDef; @@ -87,9 +82,9 @@ struct TypeDefEntry : IMemberTreeNode public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.TypeDef) - + metadata.GetTableRowSize(TableIndex.TypeDef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.TypeDef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.TypeDef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Other)] public TypeAttributes Attributes => typeDef.Attributes; @@ -107,36 +102,36 @@ struct TypeDefEntry : IMemberTreeNode public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Name):X} \"{Name}\""; - public string Name => metadata.GetString(typeDef.Name); + public string Name => metadataFile.Metadata.GetString(typeDef.Name); public string NamespaceTooltip => $"{MetadataTokens.GetHeapOffset(typeDef.Namespace):X} \"{Namespace}\""; - public string Namespace => metadata.GetString(typeDef.Namespace); + public string Namespace => metadataFile.Metadata.GetString(typeDef.Namespace); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int BaseType => MetadataTokens.GetToken(typeDef.BaseType); public void OnBaseTypeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.BaseType, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.BaseType, protocol: "metadata")); } public string BaseTypeTooltip { get { var output = new PlainTextOutput(); - var provider = new DisassemblerSignatureTypeProvider(module, output); + var provider = new DisassemblerSignatureTypeProvider(metadataFile, output); if (typeDef.BaseType.IsNil) return null; switch (typeDef.BaseType.Kind) { case HandleKind.TypeDefinition: - provider.GetTypeFromDefinition(module.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); + provider.GetTypeFromDefinition(metadataFile.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); return output.ToString(); case HandleKind.TypeReference: - provider.GetTypeFromReference(module.Metadata, (TypeReferenceHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); + provider.GetTypeFromReference(metadataFile.Metadata, (TypeReferenceHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); return output.ToString(); case HandleKind.TypeSpecification: - provider.GetTypeFromSpecification(module.Metadata, new Decompiler.Metadata.MetadataGenericContext(default(TypeDefinitionHandle), module), (TypeSpecificationHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); + provider.GetTypeFromSpecification(metadataFile.Metadata, new Decompiler.Metadata.MetadataGenericContext(default(TypeDefinitionHandle), metadataFile.Metadata), (TypeSpecificationHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); return output.ToString(); default: return null; @@ -149,7 +144,7 @@ public string BaseTypeTooltip { public void OnFieldListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.GetFields().FirstOrDefault(), protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetFields().FirstOrDefault(), protocol: "metadata")); } string fieldListTooltip; @@ -158,7 +153,7 @@ public string FieldListTooltip { var field = typeDef.GetFields().FirstOrDefault(); if (field.IsNil) return null; - return GenerateTooltip(ref fieldListTooltip, module, field); + return GenerateTooltip(ref fieldListTooltip, metadataFile, field); } } @@ -167,7 +162,7 @@ public string FieldListTooltip { public void OnMethodListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata")); } string methodListTooltip; @@ -176,19 +171,17 @@ public string MethodListTooltip { var method = typeDef.GetMethods().FirstOrDefault(); if (method.IsNil) return null; - return GenerateTooltip(ref methodListTooltip, module, method); + return GenerateTooltip(ref methodListTooltip, metadataFile, method); } } - IEntity IMemberTreeNode.Member => ((MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); + IEntity IMemberTreeNode.Member => ((MetadataModule)metadataFile.GetTypeSystemWithCurrentOptionsOrNull()?.MainModule).GetDefinition(handle); - public TypeDefEntry(PEFile module, TypeDefinitionHandle handle) + public TypeDefEntry(MetadataFile metadataFile, TypeDefinitionHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.typeDef = metadata.GetTypeDefinition(handle); + this.typeDef = metadataFile.Metadata.GetTypeDefinition(handle); this.methodListTooltip = null; this.fieldListTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs index f0a773dc3d..0f9e98ce23 100644 --- a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs @@ -21,21 +21,18 @@ using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class TypeRefTableTreeNode : MetadataTableTreeNode { - public TypeRefTableTreeNode(PEFile module) - : base(HandleKind.TypeReference, module) + public TypeRefTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.TypeReference, metadataFile) { } - public override object Text => $"01 TypeRef ({module.Metadata.GetTableRowCount(TableIndex.TypeRef)})"; - - public override object Icon => Images.Literal; + public override object Text => $"01 TypeRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeRef)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -43,14 +40,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); TypeRefEntry scrollTargetEntry = default; foreach (var row in metadata.TypeReferences) { - TypeRefEntry entry = new TypeRefEntry(module, row); + TypeRefEntry entry = new TypeRefEntry(metadataFile, row); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -72,9 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct TypeRefEntry { - readonly int metadataOffset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly TypeReferenceHandle handle; readonly TypeReference typeRef; @@ -82,36 +77,34 @@ struct TypeRefEntry public int Token => MetadataTokens.GetToken(handle); - public int Offset => metadataOffset - + metadata.GetTableMetadataOffset(TableIndex.TypeRef) - + metadata.GetTableRowSize(TableIndex.TypeRef) * (RID - 1); + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.TypeRef) + + metadataFile.Metadata.GetTableRowSize(TableIndex.TypeRef) * (RID - 1); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int ResolutionScope => MetadataTokens.GetToken(typeRef.ResolutionScope); public void OnResolutionScopeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, typeRef.ResolutionScope, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeRef.ResolutionScope, protocol: "metadata")); } string resolutionScopeTooltip; - public string ResolutionScopeTooltip => GenerateTooltip(ref resolutionScopeTooltip, module, typeRef.ResolutionScope); + public string ResolutionScopeTooltip => GenerateTooltip(ref resolutionScopeTooltip, metadataFile, typeRef.ResolutionScope); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(typeRef.Name):X} \"{Name}\""; - public string Name => metadata.GetString(typeRef.Name); + public string Name => metadataFile.Metadata.GetString(typeRef.Name); public string NamespaceTooltip => $"{MetadataTokens.GetHeapOffset(typeRef.Namespace):X} \"{Namespace}\""; - public string Namespace => metadata.GetString(typeRef.Namespace); + public string Namespace => metadataFile.Metadata.GetString(typeRef.Namespace); - public TypeRefEntry(PEFile module, TypeReferenceHandle handle) + public TypeRefEntry(MetadataFile metadataFile, TypeReferenceHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.typeRef = metadata.GetTypeReference(handle); + this.typeRef = metadataFile.Metadata.GetTypeReference(handle); this.resolutionScopeTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs index 5b87adaa13..1f8fc2106b 100644 --- a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs @@ -28,14 +28,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class TypeSpecTableTreeNode : MetadataTableTreeNode { - public TypeSpecTableTreeNode(PEFile module) - : base(HandleKind.TypeSpecification, module) + public TypeSpecTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.TypeSpecification, metadataFile) { } - public override object Text => $"1B TypeSpec ({module.Metadata.GetTableRowCount(TableIndex.TypeSpec)})"; - - public override object Icon => Images.Literal; + public override object Text => $"1B TypeSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeSpec)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -43,14 +41,14 @@ public override bool View(ViewModels.TabPageModel tabPage) tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - var metadata = module.Metadata; + var metadata = metadataFile.Metadata; var list = new List(); TypeSpecEntry scrollTargetEntry = default; foreach (var row in metadata.GetTypeSpecifications()) { - TypeSpecEntry entry = new TypeSpecEntry(module, row); + TypeSpecEntry entry = new TypeSpecEntry(metadataFile, row); if (scrollTarget.Equals(row)) { scrollTargetEntry = entry; @@ -73,7 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct TypeSpecEntry { readonly int metadataOffset; - readonly PEFile module; + readonly MetadataFile module; readonly MetadataReader metadata; readonly TypeSpecificationHandle handle; readonly TypeSpecification typeSpec; @@ -97,11 +95,11 @@ public string SignatureTooltip { } } - public TypeSpecEntry(PEFile module, TypeSpecificationHandle handle) + public TypeSpecEntry(MetadataFile metadataFile, TypeSpecificationHandle handle) { - this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - this.module = module; - this.metadata = module.Metadata; + this.module = metadataFile; + this.metadataOffset = metadataFile.MetadataOffset; + this.metadata = metadataFile.Metadata; this.handle = handle; this.typeSpec = metadata.GetTypeSpecification(handle); } diff --git a/ILSpy/Metadata/DataDirectoriesTreeNode.cs b/ILSpy/Metadata/DataDirectoriesTreeNode.cs index 879389674b..4746ec1a09 100644 --- a/ILSpy/Metadata/DataDirectoriesTreeNode.cs +++ b/ILSpy/Metadata/DataDirectoriesTreeNode.cs @@ -17,12 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System.Reflection.PortableExecutable; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; namespace ICSharpCode.ILSpy.Metadata @@ -38,7 +35,8 @@ public DataDirectoriesTreeNode(PEFile module) public override object Text => "Data Directories"; - public override object Icon => Images.Literal; + public override object Icon => Images.ListFolder; + public override object ExpandedIcon => Images.ListFolderOpen; public override bool View(ViewModels.TabPageModel tabPage) { diff --git a/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs b/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs index 5fdf81a906..63037ec101 100644 --- a/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectory/CodeViewTreeNode.cs @@ -21,7 +21,6 @@ using System.Reflection.PortableExecutable; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -39,7 +38,7 @@ public CodeViewTreeNode(CodeViewDebugDirectoryData entry) public override object ToolTip => "Associated PDB file description."; - public override object Icon => Images.Literal; + public override object Icon => Images.MetadataTable; public override bool View(TabPageModel tabPage) { diff --git a/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs b/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs index 995cc8a173..dd19b0a7c0 100644 --- a/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectory/DebugDirectoryEntryTreeNode.cs @@ -23,7 +23,6 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy.Metadata { @@ -39,9 +38,9 @@ public DebugDirectoryEntryTreeNode(PEFile module, DebugDirectoryEntry entry) this.entry = entry; } - override public object Text => $"{entry.Type}"; + override public object Text => entry.Type.ToString(); - public override object Icon => Images.Literal; + public override object Icon => Images.MetadataTable; public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { diff --git a/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs b/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs index 13444518d9..40d16053bb 100644 --- a/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectory/PdbChecksumTreeNode.cs @@ -44,7 +44,7 @@ public override object ToolTip + "be present if multiple PDBs were produced during the build of the PE/COFF file\n" + "(for example, private and public symbols)."; - public override object Icon => Images.Literal; + public override object Icon => Images.MetadataTable; public override bool View(TabPageModel tabPage) { diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs index 78e3704c17..3acc164757 100644 --- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs @@ -18,15 +18,11 @@ #nullable enable -using System; using System.Collections.Generic; using System.Reflection.PortableExecutable; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; namespace ICSharpCode.ILSpy.Metadata @@ -43,7 +39,9 @@ public DebugDirectoryTreeNode(PEFile module) public override object Text => "Debug Directory"; - public override object Icon => Images.Literal; + public override object Icon => Images.ListFolder; + public override object ExpandedIcon => Images.ListFolderOpen; + public override bool View(ViewModels.TabPageModel tabPage) { @@ -78,8 +76,9 @@ protected override void LoadChildren() break; case DebugDirectoryEntryType.EmbeddedPortablePdb: - var embeddedPortablePdbReader = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry).GetMetadataReader(); - this.Children.Add(new DebugMetadataTreeNode(module, isEmbedded: true, provider: embeddedPortablePdbReader)); + var embeddedPortablePdbProvider = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry); + var embeddedPortablePdbMetadataFile = new MetadataFile(MetadataFile.MetadataFileKind.ProgramDebugDatabase, module.FileName, embeddedPortablePdbProvider, isEmbedded: true); + this.Children.Add(new MetadataTreeNode(embeddedPortablePdbMetadataFile, "Debug Metadata (Embedded)")); break; case DebugDirectoryEntryType.PdbChecksum: diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs index cc9f94c08f..af8dd974a0 100644 --- a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs +++ b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs @@ -16,13 +16,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Collections.Generic; -using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -30,42 +27,38 @@ namespace ICSharpCode.ILSpy.Metadata { class DebugMetadataTablesTreeNode : ILSpyTreeNode { - private PEFile module; - private bool isEmbedded; - private MetadataReader provider; + private MetadataFile metadataFile; - public DebugMetadataTablesTreeNode(PEFile module, bool isEmbedded, MetadataReader provider) + public DebugMetadataTablesTreeNode(MetadataFile metadataFile) { - this.module = module; - this.isEmbedded = isEmbedded; - this.provider = provider; + this.metadataFile = metadataFile; this.LazyLoading = true; } public override object Text => "Tables"; - public override object Icon => Images.Literal; + public override object Icon => Images.MetadataTableGroup; protected override void LoadChildren() { if (ShowTable(TableIndex.Document)) - this.Children.Add(new DocumentTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new DocumentTableTreeNode(metadataFile)); if (ShowTable(TableIndex.MethodDebugInformation)) - this.Children.Add(new MethodDebugInformationTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new MethodDebugInformationTableTreeNode(metadataFile)); if (ShowTable(TableIndex.LocalScope)) - this.Children.Add(new LocalScopeTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new LocalScopeTableTreeNode(metadataFile)); if (ShowTable(TableIndex.LocalVariable)) - this.Children.Add(new LocalVariableTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new LocalVariableTableTreeNode(metadataFile)); if (ShowTable(TableIndex.LocalConstant)) - this.Children.Add(new LocalConstantTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new LocalConstantTableTreeNode(metadataFile)); if (ShowTable(TableIndex.ImportScope)) - this.Children.Add(new ImportScopeTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new ImportScopeTableTreeNode(metadataFile)); if (ShowTable(TableIndex.StateMachineMethod)) - this.Children.Add(new StateMachineMethodTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new StateMachineMethodTableTreeNode(metadataFile)); if (ShowTable(TableIndex.CustomDebugInformation)) - this.Children.Add(new CustomDebugInformationTableTreeNode(this.module, this.provider, isEmbedded)); + this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile)); - bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || this.provider.GetTableRowCount(table) > 0; + bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0; } public override bool View(TabPageModel tabPage) diff --git a/ILSpy/Metadata/DebugMetadataTreeNode.cs b/ILSpy/Metadata/DebugMetadataTreeNode.cs deleted file mode 100644 index cd140aa573..0000000000 --- a/ILSpy/Metadata/DebugMetadataTreeNode.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System.Linq; -using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; - -using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.Options; -using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.ILSpy.ViewModels; - -namespace ICSharpCode.ILSpy.Metadata -{ - class DebugMetadataTreeNode : ILSpyTreeNode - { - private PEFile module; - private MetadataReader provider; - private bool isEmbedded; - - public DebugMetadataTreeNode(PEFile module, bool isEmbedded, MetadataReader provider) - { - this.module = module; - this.provider = provider; - this.isEmbedded = isEmbedded; - this.Text = "Debug Metadata (" + (isEmbedded ? "Embedded" : "From portable PDB") + ")"; - this.LazyLoading = true; - } - - public override object Text { get; } - - public override object Icon => Images.Library; - - public override bool View(TabPageModel tabPage) - { - tabPage.Title = Text.ToString(); - tabPage.SupportsLanguageSwitching = false; - - return false; - } - - public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) - { - language.WriteCommentLine(output, "Debug Metadata"); - } - - protected override void LoadChildren() - { - this.Children.Add(new DebugMetadataTablesTreeNode(module, this.isEmbedded, this.provider)); - this.Children.Add(new StringHeapTreeNode(module, this.provider)); - this.Children.Add(new UserStringHeapTreeNode(module, this.provider)); - this.Children.Add(new GuidHeapTreeNode(module, this.provider)); - this.Children.Add(new BlobHeapTreeNode(module, this.provider)); - } - - public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind) - { - return this.Children.OfType().SingleOrDefault(x => x.Kind == kind); - } - } -} diff --git a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs index 9e9d46c612..b7e19fa3d9 100644 --- a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software @@ -19,35 +19,25 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class CustomDebugInformationTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public CustomDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.CustomDebugInformation, module, metadata) + public CustomDebugInformationTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.CustomDebugInformation, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"37 CustomDebugInformation ({metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})"; - - public override object Icon => Images.Literal; + public override object Text => $"37 CustomDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -62,9 +52,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); CustomDebugInformationEntry scrollTargetEntry = default; - foreach (var row in metadata.CustomDebugInformation) + foreach (var row in metadataFile.Metadata.CustomDebugInformation) { - CustomDebugInformationEntry entry = new CustomDebugInformationEntry(module, metadata, isEmbedded, row); + CustomDebugInformationEntry entry = new CustomDebugInformationEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -105,8 +95,7 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai class CustomDebugInformationEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly CustomDebugInformationHandle handle; readonly CustomDebugInformation debugInfo; internal readonly CustomDebugInformationKind kind; @@ -141,11 +130,11 @@ static CustomDebugInformationKind GetKind(MetadataReader metadata, GuidHandle h) } if (KnownGuids.DynamicLocalVariables == guid) { - return CustomDebugInformationKind.StateMachineHoistedLocalScopes; + return CustomDebugInformationKind.DynamicLocalVariables; } if (KnownGuids.DefaultNamespaces == guid) { - return CustomDebugInformationKind.StateMachineHoistedLocalScopes; + return CustomDebugInformationKind.DefaultNamespaces; } if (KnownGuids.EditAndContinueLocalSlotMap == guid) { @@ -202,11 +191,11 @@ static CustomDebugInformationKind GetKind(MetadataReader metadata, GuidHandle h) public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Parent, protocol: "metadata")); } string parentTooltip; - public string ParentTooltip => GenerateTooltip(ref parentTooltip, module, debugInfo.Parent); + public string ParentTooltip => GenerateTooltip(ref parentTooltip, metadataFile, debugInfo.Parent); string kindString; public string Kind { @@ -217,7 +206,7 @@ public string Kind { Guid guid; if (kind != CustomDebugInformationKind.None) { - guid = metadata.GetGuid(debugInfo.Kind); + guid = metadataFile.Metadata.GetGuid(debugInfo.Kind); } else { @@ -251,7 +240,7 @@ public string ValueTooltip { get { if (debugInfo.Value.IsNil) return ""; - return metadata.GetBlobReader(debugInfo.Value).ToHexString(); + return metadataFile.Metadata.GetBlobReader(debugInfo.Value).ToHexString(); } } @@ -265,7 +254,7 @@ public object RowDetails { if (debugInfo.Value.IsNil) return null; - var reader = metadata.GetBlobReader(debugInfo.Value); + var reader = metadataFile.Metadata.GetBlobReader(debugInfo.Value); ArrayList list; switch (kind) @@ -324,15 +313,14 @@ public object RowDetails { } } - public CustomDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, CustomDebugInformationHandle handle) + public CustomDebugInformationEntry(MetadataFile metadataFile, CustomDebugInformationHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.CustomDebugInformation) - + metadata.GetTableRowSize(TableIndex.CustomDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.metadataFile = metadataFile; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.CustomDebugInformation) + + metadataFile.Metadata.GetTableRowSize(TableIndex.CustomDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1); this.handle = handle; - this.debugInfo = metadata.GetCustomDebugInformation(handle); - this.kind = GetKind(metadata, debugInfo.Kind); + this.debugInfo = metadataFile.Metadata.GetCustomDebugInformation(handle); + this.kind = GetKind(metadataFile.Metadata, debugInfo.Kind); } } @@ -341,4 +329,4 @@ public override void Decompile(Language language, ITextOutput output, Decompilat language.WriteCommentLine(output, "CustomDebugInformation"); } } -} \ No newline at end of file +} diff --git a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs index 2a7fdb8e4b..877dafbe9b 100644 --- a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs @@ -18,7 +18,6 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -30,17 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class DocumentTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public DocumentTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.Document, module, metadata) + public DocumentTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.Document, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"30 Document ({metadata.GetTableRowCount(TableIndex.Document)})"; - - public override object Icon => Images.Literal; + public override object Text => $"30 Document ({metadataFile.Metadata.GetTableRowCount(TableIndex.Document)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -51,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); DocumentEntry scrollTargetEntry = default; - foreach (var row in metadata.Documents) + foreach (var row in metadataFile.Metadata.Documents) { - DocumentEntry entry = new DocumentEntry(metadata, isEmbedded, row); + DocumentEntry entry = new DocumentEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -73,10 +67,10 @@ public override bool View(ViewModels.TabPageModel tabPage) return true; } - struct DocumentEntry + readonly struct DocumentEntry { readonly int? offset; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly DocumentHandle handle; readonly Document document; @@ -84,9 +78,9 @@ struct DocumentEntry public int Token => MetadataTokens.GetToken(handle); - public object Offset => offset == null ? "n/a" : (object)offset; + public object Offset => offset == null ? "n/a" : offset; - public string Name => metadata.GetString(document.Name); + public string Name => metadataFile.Metadata.GetString(document.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{Name}\""; @@ -97,7 +91,7 @@ public string HashAlgorithmTooltip { get { if (document.HashAlgorithm.IsNil) return null; - Guid guid = metadata.GetGuid(document.HashAlgorithm); + Guid guid = metadataFile.Metadata.GetGuid(document.HashAlgorithm); if (guid == KnownGuids.HashAlgorithmSHA1) return "SHA1 [ff1816ec-aa5e-4d10-87f7-6f4963833460]"; if (guid == KnownGuids.HashAlgorithmSHA256) @@ -113,7 +107,7 @@ public string HashTooltip { get { if (document.Hash.IsNil) return null; - System.Collections.Immutable.ImmutableArray token = metadata.GetBlobContent(document.Hash); + System.Collections.Immutable.ImmutableArray token = metadataFile.Metadata.GetBlobContent(document.Hash); return token.ToHexString(token.Length); } } @@ -125,7 +119,7 @@ public string LanguageTooltip { get { if (document.Language.IsNil) return null; - Guid guid = metadata.GetGuid(document.Language); + Guid guid = metadataFile.Metadata.GetGuid(document.Language); if (guid == KnownGuids.CSharpLanguageGuid) return "Visual C# [3f5162f8-07c6-11d3-9053-00c04fa302a1]"; if (guid == KnownGuids.VBLanguageGuid) @@ -136,13 +130,13 @@ public string LanguageTooltip { } } - public DocumentEntry(MetadataReader metadata, bool isEmbedded, DocumentHandle handle) + public DocumentEntry(MetadataFile metadataFile, DocumentHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.Document) - + metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1); - this.metadata = metadata; + this.metadataFile = metadataFile; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.Document) + + metadataFile.Metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1); this.handle = handle; - this.document = metadata.GetDocument(handle); + this.document = metadataFile.Metadata.GetDocument(handle); } } diff --git a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs index 0e6ee99d0a..b6b878aca2 100644 --- a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs @@ -16,34 +16,23 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.Linq; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class ImportScopeTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public ImportScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.ImportScope, module, metadata) + public ImportScopeTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.ImportScope, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"35 ImportScope ({metadata.GetTableRowCount(TableIndex.ImportScope)})"; - - public override object Icon => Images.Literal; + public override object Text => $"35 ImportScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImportScope)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -54,9 +43,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); ImportScopeEntry scrollTargetEntry = default; - foreach (var row in metadata.ImportScopes) + foreach (var row in metadataFile.Metadata.ImportScopes) { - ImportScopeEntry entry = new ImportScopeEntry(module, metadata, isEmbedded, row); + ImportScopeEntry entry = new ImportScopeEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -76,11 +65,10 @@ public override bool View(ViewModels.TabPageModel tabPage) return true; } - struct ImportScopeEntry + readonly struct ImportScopeEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly ImportScopeHandle handle; readonly ImportScope localScope; @@ -88,27 +76,26 @@ struct ImportScopeEntry public int Token => MetadataTokens.GetToken(handle); - public object Offset => offset == null ? "n/a" : (object)offset; + public object Offset => offset == null ? "n/a" : offset; [ColumnInfo("X8", Kind = ColumnKind.Token)] public int Parent => MetadataTokens.GetToken(localScope.Parent); public void OnParentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.Parent, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Parent, protocol: "metadata")); } [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Imports => MetadataTokens.GetHeapOffset(localScope.ImportsBlob); - public ImportScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, ImportScopeHandle handle) + public ImportScopeEntry(MetadataFile metadataFile, ImportScopeHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.ImportScope) - + metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.metadataFile = metadataFile; this.handle = handle; - this.localScope = metadata.GetImportScope(handle); + this.localScope = metadataFile.Metadata.GetImportScope(handle); + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.ImportScope) + + metadataFile.Metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1); } } diff --git a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs index 9eaf8be2af..6075499e55 100644 --- a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs @@ -16,32 +16,23 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class LocalConstantTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public LocalConstantTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.LocalConstant, module, metadata) + public LocalConstantTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.LocalConstant, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"34 LocalConstant ({metadata.GetTableRowCount(TableIndex.LocalConstant)})"; - - public override object Icon => Images.Literal; + public override object Text => $"34 LocalConstant ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalConstant)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -52,9 +43,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); LocalConstantEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalConstants) + foreach (var row in metadataFile.Metadata.LocalConstants) { - LocalConstantEntry entry = new LocalConstantEntry(module, metadata, isEmbedded, row); + LocalConstantEntry entry = new LocalConstantEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -77,8 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct LocalConstantEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly LocalConstantHandle handle; readonly LocalConstant localConst; @@ -88,21 +78,20 @@ struct LocalConstantEntry public object Offset => offset == null ? "n/a" : (object)offset; - public string Name => metadata.GetString(localConst.Name); + public string Name => metadataFile.Metadata.GetString(localConst.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localConst.Name):X} \"{Name}\""; [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int Signature => MetadataTokens.GetHeapOffset(localConst.Signature); - public LocalConstantEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalConstantHandle handle) + public LocalConstantEntry(MetadataFile metadataFile, LocalConstantHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalConstant) - + metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalConstant) + + metadataFile.Metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1); + this.metadataFile = metadataFile; this.handle = handle; - this.localConst = metadata.GetLocalConstant(handle); + this.localConst = metadataFile.Metadata.GetLocalConstant(handle); } } diff --git a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs index 8b8ac8b1ab..59b0d01e7e 100644 --- a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs @@ -16,34 +16,24 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class LocalScopeTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public LocalScopeTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.LocalScope, module, metadata) + public LocalScopeTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.LocalScope, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"32 LocalScope ({metadata.GetTableRowCount(TableIndex.LocalScope)})"; - - public override object Icon => Images.Literal; + public override object Text => $"32 LocalScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalScope)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -54,9 +44,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); LocalScopeEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalScopes) + foreach (var row in metadataFile.Metadata.LocalScopes) { - LocalScopeEntry entry = new LocalScopeEntry(module, metadata, isEmbedded, row); + LocalScopeEntry entry = new LocalScopeEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -79,8 +69,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct LocalScopeEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly LocalScopeHandle handle; readonly LocalScope localScope; @@ -95,18 +84,18 @@ struct LocalScopeEntry public void OnMethodClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.Method, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Method, protocol: "metadata")); } string methodTooltip; - public string MethodTooltip => GenerateTooltip(ref methodTooltip, module, localScope.Method); + public string MethodTooltip => GenerateTooltip(ref methodTooltip, metadataFile, localScope.Method); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int ImportScope => MetadataTokens.GetToken(localScope.ImportScope); public void OnImportScopeClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.ImportScope, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.ImportScope, protocol: "metadata")); } [ColumnInfo("X8", Kind = ColumnKind.Token)] @@ -114,7 +103,7 @@ public void OnImportScopeClick() public void OnVariableListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata")); } [ColumnInfo("X8", Kind = ColumnKind.Token)] @@ -122,21 +111,20 @@ public void OnVariableListClick() public void OnConstantListClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata")); } public int StartOffset => localScope.StartOffset; public int Length => localScope.Length; - public LocalScopeEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalScopeHandle handle) + public LocalScopeEntry(MetadataFile metadataFile, LocalScopeHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalScope) - + metadata.GetTableRowSize(TableIndex.LocalScope) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.metadataFile = metadataFile; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalScope) + + metadataFile.Metadata.GetTableRowSize(TableIndex.LocalScope) * (MetadataTokens.GetRowNumber(handle) - 1); this.handle = handle; - this.localScope = metadata.GetLocalScope(handle); + this.localScope = metadataFile.Metadata.GetLocalScope(handle); this.methodTooltip = null; } } diff --git a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs index 9913e1a6b5..978ecd499f 100644 --- a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs @@ -27,17 +27,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class LocalVariableTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public LocalVariableTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.LocalVariable, module, metadata) + public LocalVariableTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.LocalVariable, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"33 LocalVariable ({metadata.GetTableRowCount(TableIndex.LocalVariable)})"; - - public override object Icon => Images.Literal; + public override object Text => $"33 LocalVariable ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalVariable)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -48,9 +43,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); LocalVariableEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalVariables) + foreach (var row in metadataFile.Metadata.LocalVariables) { - LocalVariableEntry entry = new LocalVariableEntry(module, metadata, isEmbedded, row); + LocalVariableEntry entry = new LocalVariableEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -73,8 +68,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct LocalVariableEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly LocalVariableHandle handle; readonly LocalVariable localVar; @@ -93,18 +87,17 @@ struct LocalVariableEntry public int Index => localVar.Index; - public string Name => metadata.GetString(localVar.Name); + public string Name => metadataFile.Metadata.GetString(localVar.Name); public string NameTooltip => $"{MetadataTokens.GetHeapOffset(localVar.Name):X} \"{Name}\""; - public LocalVariableEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalVariableHandle handle) + public LocalVariableEntry(MetadataFile metadataFile, LocalVariableHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalVariable) - + metadata.GetTableRowSize(TableIndex.LocalVariable) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.metadataFile = metadataFile; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.LocalVariable) + + metadataFile.Metadata.GetTableRowSize(TableIndex.LocalVariable) * (MetadataTokens.GetRowNumber(handle) - 1); this.handle = handle; - this.localVar = metadata.GetLocalVariable(handle); + this.localVar = metadataFile.Metadata.GetLocalVariable(handle); } } diff --git a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs index d439308e44..591e388f64 100644 --- a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs @@ -16,9 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -31,17 +29,12 @@ namespace ICSharpCode.ILSpy.Metadata { internal class MethodDebugInformationTableTreeNode : DebugMetadataTableTreeNode { - private readonly bool isEmbedded; - - public MethodDebugInformationTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base(HandleKind.MethodDebugInformation, module, metadata) + public MethodDebugInformationTableTreeNode(MetadataFile metadataFile) + : base(HandleKind.MethodDebugInformation, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"31 MethodDebugInformation ({metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})"; - - public override object Icon => Images.Literal; + public override object Text => $"31 MethodDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -52,9 +45,9 @@ public override bool View(ViewModels.TabPageModel tabPage) var list = new List(); MethodDebugInformationEntry scrollTargetEntry = default; - foreach (var row in metadata.MethodDebugInformation) + foreach (var row in metadataFile.Metadata.MethodDebugInformation) { - MethodDebugInformationEntry entry = new MethodDebugInformationEntry(module, metadata, isEmbedded, row); + MethodDebugInformationEntry entry = new MethodDebugInformationEntry(metadataFile, row); if (entry.RID == scrollTarget) { scrollTargetEntry = entry; @@ -77,8 +70,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct MethodDebugInformationEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MethodDebugInformationHandle handle; readonly MethodDebugInformation debugInfo; @@ -93,15 +85,15 @@ struct MethodDebugInformationEntry public void OnDocumentClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.Document, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Document, protocol: "metadata")); } public string DocumentTooltip { get { if (debugInfo.Document.IsNil) return null; - var document = metadata.GetDocument(debugInfo.Document); - return $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{metadata.GetString(document.Name)}\""; + var document = metadataFile.Metadata.GetDocument(debugInfo.Document); + return $"{MetadataTokens.GetHeapOffset(document.Name):X} \"{metadataFile.Metadata.GetString(document.Name)}\""; } } @@ -126,7 +118,7 @@ public string SequencePointsTooltip { public void OnLocalSignatureClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, debugInfo.LocalSignature, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.LocalSignature, protocol: "metadata")); } public string LocalSignatureTooltip { @@ -134,9 +126,9 @@ public string LocalSignatureTooltip { if (debugInfo.LocalSignature.IsNil) return null; ITextOutput output = new PlainTextOutput(); - var context = new MetadataGenericContext(default(TypeDefinitionHandle), metadata); - StandaloneSignature localSignature = module.Metadata.GetStandaloneSignature(debugInfo.LocalSignature); - var signatureDecoder = new DisassemblerSignatureTypeProvider(module, output); + var context = new MetadataGenericContext(default(TypeDefinitionHandle), metadataFile.Metadata); + StandaloneSignature localSignature = metadataFile.Metadata.GetStandaloneSignature(debugInfo.LocalSignature); + var signatureDecoder = new DisassemblerSignatureTypeProvider(metadataFile, output); int index = 0; foreach (var item in localSignature.DecodeLocalSignature(signatureDecoder, context)) { @@ -150,14 +142,13 @@ public string LocalSignatureTooltip { } } - public MethodDebugInformationEntry(PEFile module, MetadataReader metadata, bool isEmbedded, MethodDebugInformationHandle handle) + public MethodDebugInformationEntry(MetadataFile metadataFile, MethodDebugInformationHandle handle) { - this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.MethodDebugInformation) - + metadata.GetTableRowSize(TableIndex.MethodDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1); - this.module = module; - this.metadata = metadata; + this.metadataFile = metadataFile; + this.offset = metadataFile.IsEmbedded ? null : (int?)metadataFile.Metadata.GetTableMetadataOffset(TableIndex.MethodDebugInformation) + + metadataFile.Metadata.GetTableRowSize(TableIndex.MethodDebugInformation) * (MetadataTokens.GetRowNumber(handle) - 1); this.handle = handle; - this.debugInfo = metadata.GetMethodDebugInformation(handle); + this.debugInfo = metadataFile.Metadata.GetMethodDebugInformation(handle); } } diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs index f4a463e78d..8882adbdd6 100644 --- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs @@ -16,33 +16,23 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata { internal class StateMachineMethodTableTreeNode : DebugMetadataTableTreeNode { - readonly bool isEmbedded; - - public StateMachineMethodTableTreeNode(PEFile module, MetadataReader metadata, bool isEmbedded) - : base((HandleKind)0x36, module, metadata) + public StateMachineMethodTableTreeNode(MetadataFile metadataFile) + : base((HandleKind)0x36, metadataFile) { - this.isEmbedded = isEmbedded; } - public override object Text => $"36 StateMachineMethod ({metadata.GetTableRowCount(TableIndex.StateMachineMethod)})"; - - public override object Icon => Images.Literal; + public override object Text => $"36 StateMachineMethod ({metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod)})"; public override bool View(ViewModels.TabPageModel tabPage) { @@ -52,13 +42,13 @@ public override bool View(ViewModels.TabPageModel tabPage) var view = Helpers.PrepareDataGrid(tabPage, this); var list = new List(); StateMachineMethodEntry scrollTargetEntry = default; - var length = metadata.GetTableRowCount(TableIndex.StateMachineMethod); - var reader = metadata.AsBlobReader(); - reader.Offset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod); + var length = metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod); + var reader = metadataFile.Metadata.AsBlobReader(); + reader.Offset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod); for (int rid = 1; rid <= length; rid++) { - StateMachineMethodEntry entry = new StateMachineMethodEntry(module, ref reader, isEmbedded, rid); + StateMachineMethodEntry entry = new StateMachineMethodEntry(metadataFile, ref reader, rid); if (scrollTarget == rid) { scrollTargetEntry = entry; @@ -81,8 +71,7 @@ public override bool View(ViewModels.TabPageModel tabPage) struct StateMachineMethodEntry { readonly int? offset; - readonly PEFile module; - readonly MetadataReader metadata; + readonly MetadataFile metadataFile; readonly MethodDefinitionHandle moveNextMethod; readonly MethodDefinitionHandle kickoffMethod; @@ -97,33 +86,32 @@ struct StateMachineMethodEntry public void OnMoveNextMethodClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, moveNextMethod, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, moveNextMethod, protocol: "metadata")); } string moveNextMethodTooltip; - public string MoveNextMethodTooltip => GenerateTooltip(ref moveNextMethodTooltip, module, moveNextMethod); + public string MoveNextMethodTooltip => GenerateTooltip(ref moveNextMethodTooltip, metadataFile, moveNextMethod); [ColumnInfo("X8", Kind = ColumnKind.Token)] public int KickoffMethod => MetadataTokens.GetToken(kickoffMethod); public void OnKickofMethodClick() { - MainWindow.Instance.JumpToReference(new EntityReference(module, kickoffMethod, protocol: "metadata")); + MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, kickoffMethod, protocol: "metadata")); } string kickoffMethodTooltip; - public string KickoffMethodTooltip => GenerateTooltip(ref kickoffMethodTooltip, module, kickoffMethod); + public string KickoffMethodTooltip => GenerateTooltip(ref kickoffMethodTooltip, metadataFile, kickoffMethod); - public StateMachineMethodEntry(PEFile module, ref BlobReader reader, bool isEmbedded, int row) + public StateMachineMethodEntry(MetadataFile metadataFile, ref BlobReader reader, int row) { - this.module = module; - this.metadata = module.Metadata; + this.metadataFile = metadataFile; this.RID = row; - int rowOffset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod) - + metadata.GetTableRowSize(TableIndex.StateMachineMethod) * (row - 1); - this.offset = isEmbedded ? null : (int?)rowOffset; + int rowOffset = metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod) + + metadataFile.Metadata.GetTableRowSize(TableIndex.StateMachineMethod) * (row - 1); + this.offset = metadataFile.IsEmbedded ? null : (int?)rowOffset; - int methodDefSize = metadata.GetTableRowCount(TableIndex.MethodDef) < ushort.MaxValue ? 2 : 4; + int methodDefSize = metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef) < ushort.MaxValue ? 2 : 4; this.moveNextMethod = MetadataTokens.MethodDefinitionHandle(methodDefSize == 2 ? reader.ReadInt16() : reader.ReadInt32()); this.kickoffMethod = MetadataTokens.MethodDefinitionHandle(methodDefSize == 2 ? reader.ReadInt16() : reader.ReadInt32()); this.kickoffMethodTooltip = null; diff --git a/ILSpy/Metadata/DosHeaderTreeNode.cs b/ILSpy/Metadata/DosHeaderTreeNode.cs index ad62e6fff9..29cb3833b4 100644 --- a/ILSpy/Metadata/DosHeaderTreeNode.cs +++ b/ILSpy/Metadata/DosHeaderTreeNode.cs @@ -17,8 +17,6 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; @@ -38,7 +36,7 @@ public DosHeaderTreeNode(PEFile module) public override object Text => "DOS Header"; - public override object Icon => Images.Literal; + public override object Icon => Images.Header; public override bool View(TabPageModel tabPage) { diff --git a/ILSpy/Metadata/GoToTokenCommand.cs b/ILSpy/Metadata/GoToTokenCommand.cs index d8963ce603..ae0fa1657e 100644 --- a/ILSpy/Metadata/GoToTokenCommand.cs +++ b/ILSpy/Metadata/GoToTokenCommand.cs @@ -35,7 +35,7 @@ class GoToTokenCommand : IContextMenuEntry { public void Execute(TextViewContext context) { - int token = GetSelectedToken(context.DataGrid, out PEFile module).Value; + int token = GetSelectedToken(context.DataGrid, out MetadataFile module).Value; MainWindow.Instance.JumpToReference(new EntityReference(module, MetadataTokens.Handle(token), protocol: "metadata")); } @@ -49,7 +49,7 @@ public bool IsVisible(TextViewContext context) return context.DataGrid?.Name == "MetadataView" && GetSelectedToken(context.DataGrid, out _) != null; } - private int? GetSelectedToken(DataGrid grid, out PEFile module) + private int? GetSelectedToken(DataGrid grid, out MetadataFile module) { module = null; if (grid == null) @@ -62,7 +62,7 @@ public bool IsVisible(TextViewContext context) var moduleField = type.GetField("module", BindingFlags.NonPublic | BindingFlags.Instance); if (property == null || property.PropertyType != typeof(int) || !property.GetCustomAttributes(false).Any(a => a is ColumnInfoAttribute { Kind: ColumnKind.Token } c)) return null; - module = (PEFile)moduleField.GetValue(cell.Item); + module = (MetadataFile)moduleField.GetValue(cell.Item); return (int)property.GetValue(cell.Item); } } diff --git a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs index f439e9acda..7dc0c62b19 100644 --- a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs +++ b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs @@ -16,21 +16,11 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata @@ -39,11 +29,12 @@ internal class BlobHeapTreeNode : MetadataHeapTreeNode { readonly List list; - public BlobHeapTreeNode(PEFile module, MetadataReader metadata) - : base(HandleKind.Blob, module, metadata) + public BlobHeapTreeNode(MetadataFile metadataFile) + : base(HandleKind.Blob, metadataFile) { list = new List(); + var metadata = metadataFile.Metadata; BlobHandle handle = MetadataTokens.BlobHandle(0); do { @@ -55,8 +46,6 @@ public BlobHeapTreeNode(PEFile module, MetadataReader metadata) public override object Text => $"Blob Heap ({list.Count})"; - public override object Icon => Images.Literal; - public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); diff --git a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs index f3f742619e..17de531ab1 100644 --- a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs +++ b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs @@ -16,7 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -30,10 +29,11 @@ internal class GuidHeapTreeNode : MetadataHeapTreeNode { readonly List list; - public GuidHeapTreeNode(PEFile module, MetadataReader metadata) - : base(HandleKind.Guid, module, metadata) + public GuidHeapTreeNode(MetadataFile metadataFile) + : base(HandleKind.Guid, metadataFile) { list = new List(); + var metadata = metadataFile.Metadata; int count = metadata.GetHeapSize(HeapIndex.Guid) >> 4; for (int i = 1; i <= count; i++) { @@ -44,8 +44,6 @@ public GuidHeapTreeNode(PEFile module, MetadataReader metadata) public override object Text => $"Guid Heap ({list.Count})"; - public override object Icon => Images.Literal; - public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); diff --git a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs index 2e2ca4370a..91f679de9c 100644 --- a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs +++ b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs @@ -16,21 +16,11 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata @@ -39,10 +29,11 @@ internal class StringHeapTreeNode : MetadataHeapTreeNode { readonly List list; - public StringHeapTreeNode(PEFile module, MetadataReader metadata) - : base(HandleKind.String, module, metadata) + public StringHeapTreeNode(MetadataFile metadataFile) + : base(HandleKind.String, metadataFile) { list = new List(); + var metadata = metadataFile.Metadata; StringHandle handle = MetadataTokens.StringHandle(0); do { @@ -54,8 +45,6 @@ public StringHeapTreeNode(PEFile module, MetadataReader metadata) public override object Text => $"String Heap ({list.Count})"; - public override object Icon => Images.Literal; - public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); diff --git a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs index 882a1c3a61..f2a7fd00d2 100644 --- a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs +++ b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs @@ -16,21 +16,11 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections; using System.Collections.Generic; -using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata @@ -39,11 +29,11 @@ internal class UserStringHeapTreeNode : MetadataHeapTreeNode { readonly List list; - public UserStringHeapTreeNode(PEFile module, MetadataReader metadata) - : base(HandleKind.UserString, module, metadata) + public UserStringHeapTreeNode(MetadataFile metadataFile) + : base(HandleKind.UserString, metadataFile) { list = new List(); - + var metadata = metadataFile.Metadata; UserStringHandle handle = MetadataTokens.UserStringHandle(0); do { @@ -55,8 +45,6 @@ public UserStringHeapTreeNode(PEFile module, MetadataReader metadata) public override object Text => $"UserString Heap ({list.Count})"; - public override object Icon => Images.Literal; - public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); diff --git a/ILSpy/Metadata/MetadataHeapTreeNode.cs b/ILSpy/Metadata/MetadataHeapTreeNode.cs index 3be811d3df..67a12036ad 100644 --- a/ILSpy/Metadata/MetadataHeapTreeNode.cs +++ b/ILSpy/Metadata/MetadataHeapTreeNode.cs @@ -16,44 +16,34 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; using System.Windows.Controls; using System.Windows.Threading; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.ILSpy.ViewModels; -using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.Metadata { internal abstract class MetadataHeapTreeNode : ILSpyTreeNode { - protected PEFile module; - protected MetadataReader metadata; + protected MetadataFile metadataFile; protected int scrollTarget; public HandleKind Kind { get; } - public MetadataHeapTreeNode(HandleKind kind, PEFile module, MetadataReader metadata) - { - this.module = module; - this.Kind = kind; - this.metadata = metadata; - } + public override object Icon => Images.Heap; - internal void ScrollTo(Handle handle) + public MetadataHeapTreeNode(HandleKind kind, MetadataFile metadataFile) { - //this.scrollTarget = MetadataTokens.GetHeapOffset((EntityHandle)handle); + this.Kind = kind; + this.metadataFile = metadataFile; } protected void ScrollItemIntoView(DataGrid view, object item) { view.Loaded += View_Loaded; - view.Dispatcher.BeginInvoke((Action)(() => view.SelectItem(item)), DispatcherPriority.Background); + view.Dispatcher.BeginInvoke(() => view.SelectItem(item), DispatcherPriority.Background); } private void View_Loaded(object sender, System.Windows.RoutedEventArgs e) diff --git a/ILSpy/Metadata/MetadataProtocolHandler.cs b/ILSpy/Metadata/MetadataProtocolHandler.cs index 3fb5219d94..e4fc4bbec3 100644 --- a/ILSpy/Metadata/MetadataProtocolHandler.cs +++ b/ILSpy/Metadata/MetadataProtocolHandler.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Metadata [Export(typeof(IProtocolHandler))] class MetadataProtocolHandler : IProtocolHandler { - public ILSpyTreeNode Resolve(string protocol, PEFile module, Handle handle, out bool newTabPage) + public ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage) { newTabPage = true; if (protocol != "metadata") diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs index 204270dc3e..54f2d47ae2 100644 --- a/ILSpy/Metadata/MetadataTableTreeNode.cs +++ b/ILSpy/Metadata/MetadataTableTreeNode.cs @@ -23,28 +23,30 @@ using System.Windows.Threading; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.IL; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; namespace ICSharpCode.ILSpy.Metadata { internal abstract class MetadataTableTreeNode : ILSpyTreeNode { - protected PEFile module; + protected readonly MetadataFile metadataFile; protected int scrollTarget; public HandleKind Kind { get; } - public MetadataTableTreeNode(HandleKind kind, PEFile module) + public override object Icon => Images.MetadataTable; + + public MetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile) { - this.module = module; this.Kind = kind; + this.metadataFile = metadataFile; } internal void ScrollTo(Handle handle) { - this.scrollTarget = module.Metadata.GetRowNumber((EntityHandle)handle); + this.scrollTarget = metadataFile.Metadata.GetRowNumber((EntityHandle)handle); } protected void ScrollItemIntoView(DataGrid view, object item) @@ -62,7 +64,7 @@ private void View_Loaded(object sender, System.Windows.RoutedEventArgs e) this.scrollTarget = default; } - protected static string GenerateTooltip(ref string tooltip, PEFile module, EntityHandle handle) + protected static string GenerateTooltip(ref string tooltip, MetadataFile module, EntityHandle handle) { if (tooltip == null) { @@ -71,7 +73,7 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit return null; } ITextOutput output = new PlainTextOutput(); - var context = new MetadataGenericContext(default(TypeDefinitionHandle), module); + var context = new MetadataGenericContext(default(TypeDefinitionHandle), module.Metadata); var metadata = module.Metadata; switch (handle.Kind) { @@ -84,7 +86,7 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit output.Write(metadata.GetString(moduleReference.Name)); break; case HandleKind.AssemblyReference: - var asmRef = new Decompiler.Metadata.AssemblyReference(module, (AssemblyReferenceHandle)handle); + var asmRef = new Decompiler.Metadata.AssemblyReference(metadata, (AssemblyReferenceHandle)handle); output.Write(asmRef.ToString()); break; case HandleKind.Parameter: @@ -132,12 +134,9 @@ protected static string GenerateTooltip(ref string tooltip, PEFile module, Entit internal abstract class DebugMetadataTableTreeNode : MetadataTableTreeNode { - protected MetadataReader metadata; - - public DebugMetadataTableTreeNode(HandleKind kind, PEFile module, MetadataReader metadata) - : base(kind, module) + public DebugMetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile) + : base(kind, metadataFile) { - this.metadata = metadata; } } } \ No newline at end of file diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs index 0a05fcf654..26bb59b211 100644 --- a/ILSpy/Metadata/MetadataTablesTreeNode.cs +++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs @@ -16,12 +16,12 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Collections.Generic; +using System; +using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -29,91 +29,120 @@ namespace ICSharpCode.ILSpy.Metadata { class MetadataTablesTreeNode : ILSpyTreeNode { - private PEFile module; + readonly MetadataFile metadataFile; - public MetadataTablesTreeNode(PEFile module) + public MetadataTablesTreeNode(MetadataFile metadataFile) { - this.module = module; + this.metadataFile = metadataFile; this.LazyLoading = true; } public override object Text => "Tables"; - public override object Icon => Images.Literal; + public override object Icon => Images.MetadataTableGroup; protected override void LoadChildren() { - if (ShowTable(TableIndex.Module)) - this.Children.Add(new ModuleTableTreeNode(module)); - if (ShowTable(TableIndex.TypeRef)) - this.Children.Add(new TypeRefTableTreeNode(module)); - if (ShowTable(TableIndex.TypeDef)) - this.Children.Add(new TypeDefTableTreeNode(module)); - if (ShowTable(TableIndex.Field)) - this.Children.Add(new FieldTableTreeNode(module)); - if (ShowTable(TableIndex.MethodDef)) - this.Children.Add(new MethodTableTreeNode(module)); - if (ShowTable(TableIndex.Param)) - this.Children.Add(new ParamTableTreeNode(module)); - if (ShowTable(TableIndex.InterfaceImpl)) - this.Children.Add(new InterfaceImplTableTreeNode(module)); - if (ShowTable(TableIndex.MemberRef)) - this.Children.Add(new MemberRefTableTreeNode(module)); - if (ShowTable(TableIndex.Constant)) - this.Children.Add(new ConstantTableTreeNode(module)); - if (ShowTable(TableIndex.CustomAttribute)) - this.Children.Add(new CustomAttributeTableTreeNode(module)); - if (ShowTable(TableIndex.FieldMarshal)) - this.Children.Add(new FieldMarshalTableTreeNode(module)); - if (ShowTable(TableIndex.DeclSecurity)) - this.Children.Add(new DeclSecurityTableTreeNode(module)); - if (ShowTable(TableIndex.ClassLayout)) - this.Children.Add(new ClassLayoutTableTreeNode(module)); - if (ShowTable(TableIndex.FieldLayout)) - this.Children.Add(new FieldLayoutTableTreeNode(module)); - if (ShowTable(TableIndex.StandAloneSig)) - this.Children.Add(new StandAloneSigTableTreeNode(module)); - if (ShowTable(TableIndex.EventMap)) - this.Children.Add(new EventMapTableTreeNode(module)); - if (ShowTable(TableIndex.Event)) - this.Children.Add(new EventTableTreeNode(module)); - if (ShowTable(TableIndex.PropertyMap)) - this.Children.Add(new PropertyMapTableTreeNode(module)); - if (ShowTable(TableIndex.Property)) - this.Children.Add(new PropertyTableTreeNode(module)); - if (ShowTable(TableIndex.MethodSemantics)) - this.Children.Add(new MethodSemanticsTableTreeNode(module)); - if (ShowTable(TableIndex.MethodImpl)) - this.Children.Add(new MethodImplTableTreeNode(module)); - if (ShowTable(TableIndex.ModuleRef)) - this.Children.Add(new ModuleRefTableTreeNode(module)); - if (ShowTable(TableIndex.TypeSpec)) - this.Children.Add(new TypeSpecTableTreeNode(module)); - if (ShowTable(TableIndex.ImplMap)) - this.Children.Add(new ImplMapTableTreeNode(module)); - if (ShowTable(TableIndex.FieldRva)) - this.Children.Add(new FieldRVATableTreeNode(module)); - if (ShowTable(TableIndex.Assembly)) - this.Children.Add(new AssemblyTableTreeNode(module)); - if (ShowTable(TableIndex.AssemblyRef)) - this.Children.Add(new AssemblyRefTableTreeNode(module)); - if (ShowTable(TableIndex.File)) - this.Children.Add(new FileTableTreeNode(module)); - if (ShowTable(TableIndex.ExportedType)) - this.Children.Add(new ExportedTypeTableTreeNode(module)); - if (ShowTable(TableIndex.ManifestResource)) - this.Children.Add(new ManifestResourceTableTreeNode(module)); - if (ShowTable(TableIndex.NestedClass)) - this.Children.Add(new NestedClassTableTreeNode(module)); - if (ShowTable(TableIndex.GenericParam)) - this.Children.Add(new GenericParamTableTreeNode(module)); - if (ShowTable(TableIndex.MethodSpec)) - this.Children.Add(new MethodSpecTableTreeNode(module)); - if (ShowTable(TableIndex.GenericParamConstraint)) - this.Children.Add(new GenericParamConstraintTableTreeNode(module)); + foreach (var table in Enum.GetValues()) + { + if (ShowTable(table, metadataFile.Metadata)) + this.Children.Add(CreateTableTreeNode(table, metadataFile)); + } + } - bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || module.Metadata.GetTableRowCount(table) > 0; + internal static bool ShowTable(TableIndex table, MetadataReader metadata) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadata.GetTableRowCount(table) > 0; + internal static MetadataTableTreeNode CreateTableTreeNode(TableIndex table, MetadataFile metadataFile) + { + switch (table) + { + case TableIndex.Module: + return new ModuleTableTreeNode(metadataFile); + case TableIndex.TypeRef: + return new TypeRefTableTreeNode(metadataFile); + case TableIndex.TypeDef: + return new TypeDefTableTreeNode(metadataFile); + case TableIndex.Field: + return new FieldTableTreeNode(metadataFile); + case TableIndex.MethodDef: + return new MethodTableTreeNode(metadataFile); + case TableIndex.Param: + return new ParamTableTreeNode(metadataFile); + case TableIndex.InterfaceImpl: + return new InterfaceImplTableTreeNode(metadataFile); + case TableIndex.MemberRef: + return new MemberRefTableTreeNode(metadataFile); + case TableIndex.Constant: + return new ConstantTableTreeNode(metadataFile); + case TableIndex.CustomAttribute: + return new CustomAttributeTableTreeNode(metadataFile); + case TableIndex.FieldMarshal: + return new FieldMarshalTableTreeNode(metadataFile); + case TableIndex.DeclSecurity: + return new DeclSecurityTableTreeNode(metadataFile); + case TableIndex.ClassLayout: + return new ClassLayoutTableTreeNode(metadataFile); + case TableIndex.FieldLayout: + return new FieldLayoutTableTreeNode(metadataFile); + case TableIndex.StandAloneSig: + return new StandAloneSigTableTreeNode(metadataFile); + case TableIndex.EventMap: + return new EventMapTableTreeNode(metadataFile); + case TableIndex.Event: + return new EventTableTreeNode(metadataFile); + case TableIndex.PropertyMap: + return new PropertyMapTableTreeNode(metadataFile); + case TableIndex.Property: + return new PropertyTableTreeNode(metadataFile); + case TableIndex.MethodSemantics: + return new MethodSemanticsTableTreeNode(metadataFile); + case TableIndex.MethodImpl: + return new MethodImplTableTreeNode(metadataFile); + case TableIndex.ModuleRef: + return new ModuleRefTableTreeNode(metadataFile); + case TableIndex.TypeSpec: + return new TypeSpecTableTreeNode(metadataFile); + case TableIndex.ImplMap: + return new ImplMapTableTreeNode(metadataFile); + case TableIndex.FieldRva: + return new FieldRVATableTreeNode(metadataFile); + case TableIndex.Assembly: + return new AssemblyTableTreeNode(metadataFile); + case TableIndex.AssemblyRef: + return new AssemblyRefTableTreeNode(metadataFile); + case TableIndex.File: + return new FileTableTreeNode(metadataFile); + case TableIndex.ExportedType: + return new ExportedTypeTableTreeNode(metadataFile); + case TableIndex.ManifestResource: + return new ManifestResourceTableTreeNode(metadataFile); + case TableIndex.NestedClass: + return new NestedClassTableTreeNode(metadataFile); + case TableIndex.GenericParam: + return new GenericParamTableTreeNode(metadataFile); + case TableIndex.MethodSpec: + return new MethodSpecTableTreeNode(metadataFile); + case TableIndex.GenericParamConstraint: + return new GenericParamConstraintTableTreeNode(metadataFile); + case TableIndex.Document: + return new DocumentTableTreeNode(metadataFile); + case TableIndex.MethodDebugInformation: + return new MethodDebugInformationTableTreeNode(metadataFile); + case TableIndex.LocalScope: + return new LocalScopeTableTreeNode(metadataFile); + case TableIndex.LocalVariable: + return new LocalVariableTableTreeNode(metadataFile); + case TableIndex.LocalConstant: + return new LocalConstantTableTreeNode(metadataFile); + case TableIndex.ImportScope: + return new ImportScopeTableTreeNode(metadataFile); + case TableIndex.StateMachineMethod: + return new StateMachineMethodTableTreeNode(metadataFile); + case TableIndex.CustomDebugInformation: + return new CustomDebugInformationTableTreeNode(metadataFile); + default: + throw new ArgumentException($"Unsupported table index: {table}"); + } } public override bool View(TabPageModel tabPage) diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs index 5511d5ad58..4aedf30a78 100644 --- a/ILSpy/Metadata/MetadataTreeNode.cs +++ b/ILSpy/Metadata/MetadataTreeNode.cs @@ -21,11 +21,11 @@ using System.Globalization; using System.Linq; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; @@ -33,19 +33,19 @@ namespace ICSharpCode.ILSpy.Metadata { class MetadataTreeNode : ILSpyTreeNode { - private readonly PEFile module; - private AssemblyTreeNode assemblyTreeNode; + private readonly MetadataFile metadataFile; + private readonly string title; - public MetadataTreeNode(PEFile module, AssemblyTreeNode assemblyTreeNode) + public MetadataTreeNode(MetadataFile module, string title) { - this.module = module; - this.assemblyTreeNode = assemblyTreeNode; + this.metadataFile = module; + this.title = title; this.LazyLoading = true; } - public override object Text => Resources.Metadata; + public override object Text => title; - public override object Icon => Images.Library; + public override object Icon => Images.Metadata; public override bool View(TabPageModel tabPage) { @@ -57,21 +57,52 @@ public override bool View(TabPageModel tabPage) public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { - language.WriteCommentLine(output, "Metadata"); + language.WriteCommentLine(output, title); + + DumpMetadataInfo(language, output, this.metadataFile.Metadata); + } + + internal static void DumpMetadataInfo(Language language, ITextOutput output, MetadataReader metadata) + { + language.WriteCommentLine(output, "MetadataKind: " + metadata.MetadataKind); + language.WriteCommentLine(output, "MetadataVersion: " + metadata.MetadataVersion); + + if (metadata.DebugMetadataHeader is { } header) + { + output.WriteLine(); + language.WriteCommentLine(output, "Header:"); + language.WriteCommentLine(output, "Id: " + header.Id.ToHexString(header.Id.Length)); + language.WriteCommentLine(output, "EntryPoint: " + MetadataTokens.GetToken(header.EntryPoint).ToString("X8")); + } + + output.WriteLine(); + language.WriteCommentLine(output, "Tables:"); + + foreach (var table in Enum.GetValues()) + { + int count = metadata.GetTableRowCount(table); + if (count > 0) + { + language.WriteCommentLine(output, $"{(byte)table:X2} {table}: {count} rows"); + } + } } protected override void LoadChildren() { - this.Children.Add(new DosHeaderTreeNode(module)); - this.Children.Add(new CoffHeaderTreeNode(module)); - this.Children.Add(new OptionalHeaderTreeNode(module)); - this.Children.Add(new DataDirectoriesTreeNode(module)); - this.Children.Add(new DebugDirectoryTreeNode(module)); - this.Children.Add(new MetadataTablesTreeNode(module)); - this.Children.Add(new StringHeapTreeNode(module, module.Metadata)); - this.Children.Add(new UserStringHeapTreeNode(module, module.Metadata)); - this.Children.Add(new GuidHeapTreeNode(module, module.Metadata)); - this.Children.Add(new BlobHeapTreeNode(module, module.Metadata)); + if (metadataFile is PEFile module) + { + this.Children.Add(new DosHeaderTreeNode(module)); + this.Children.Add(new CoffHeaderTreeNode(module)); + this.Children.Add(new OptionalHeaderTreeNode(module)); + this.Children.Add(new DataDirectoriesTreeNode(module)); + this.Children.Add(new DebugDirectoryTreeNode(module)); + } + this.Children.Add(new MetadataTablesTreeNode(metadataFile)); + this.Children.Add(new StringHeapTreeNode(metadataFile)); + this.Children.Add(new UserStringHeapTreeNode(metadataFile)); + this.Children.Add(new GuidHeapTreeNode(metadataFile)); + this.Children.Add(new BlobHeapTreeNode(metadataFile)); } public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind) diff --git a/ILSpy/Metadata/OptionalHeaderTreeNode.cs b/ILSpy/Metadata/OptionalHeaderTreeNode.cs index cbd67a2924..dc1be30ec7 100644 --- a/ILSpy/Metadata/OptionalHeaderTreeNode.cs +++ b/ILSpy/Metadata/OptionalHeaderTreeNode.cs @@ -40,7 +40,7 @@ public OptionalHeaderTreeNode(PEFile module) public override object Text => "Optional Header"; - public override object Icon => Images.Literal; + public override object Icon => Images.Header; public override bool View(ViewModels.TabPageModel tabPage) { diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 397e5da3a7..1866a7b293 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -495,6 +495,15 @@ public static string CheckUpdates { } } + /// + /// Looks up a localized string similar to Clear assembly list. + /// + public static string ClearAssemblyList { + get { + return ResourceManager.GetString("ClearAssemblyList", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close. /// @@ -765,6 +774,15 @@ public static string DecompilerSettings_AsyncEnumerator { } } + /// + /// Looks up a localized string similar to Automatically load assembly references. + /// + public static string DecompilerSettings_AutoLoadAssemblyReferences { + get { + return ResourceManager.GetString("DecompilerSettings.AutoLoadAssemblyReferences", resourceCulture); + } + } + /// /// Looks up a localized string similar to User-defined checked operators. /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 6623f03530..cc08fca35e 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -186,6 +186,9 @@ Are you sure you want to continue? Checking... + + Clear assembly list + Close @@ -279,6 +282,9 @@ Are you sure you want to continue? Decompile async IAsyncEnumerator methods + + Automatically load assembly references + User-defined checked operators diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index 0bd418539c..0eb3fe8d05 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -21,7 +21,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; @@ -34,7 +33,6 @@ using System.Windows.Threading; using ICSharpCode.ILSpy.Docking; -using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX.Extensions; @@ -220,7 +218,14 @@ void UpdateResults(object sender, EventArgs e) if (resultsAdded > 0 && Results.Count == MAX_RESULTS) { - Results.Add(new SearchResult { Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound }); + Results.Add(new SearchResult { + Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound, + Location = null!, + Assembly = null!, + Image = null!, + LocationImage = null!, + AssemblyImage = null!, + }); currentSearch.Cancel(); } } @@ -467,7 +472,7 @@ await Task.Factory.StartNew(() => { { foreach (var loadedAssembly in assemblies) { - var module = loadedAssembly.GetPEFileOrNull(); + var module = loadedAssembly.GetMetadataFileOrNull(); if (module == null) continue; searcher.Search(module, cts.Token); diff --git a/ILSpy/Search/SearchResultFactory.cs b/ILSpy/Search/SearchResultFactory.cs index 63db8e9091..f466436c7a 100644 --- a/ILSpy/Search/SearchResultFactory.cs +++ b/ILSpy/Search/SearchResultFactory.cs @@ -105,14 +105,14 @@ public MemberSearchResult Create(IEntity entity) Name = GetLanguageSpecificName(entity), Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : entity.Namespace, Assembly = entity.ParentModule.FullAssemblyName, - ToolTip = entity.ParentModule.PEFile?.FileName, + ToolTip = entity.ParentModule.MetadataFile?.FileName, Image = GetIcon(entity), LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace, AssemblyImage = Images.Assembly, }; } - public ResourceSearchResult Create(PEFile module, Resource resource, ITreeNode node, ITreeNode parent) + public ResourceSearchResult Create(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent) { return new ResourceSearchResult { Resource = resource, @@ -127,7 +127,7 @@ public ResourceSearchResult Create(PEFile module, Resource resource, ITreeNode n }; } - public AssemblySearchResult Create(PEFile module) + public AssemblySearchResult Create(MetadataFile module) { return new AssemblySearchResult { Module = module, @@ -142,7 +142,7 @@ public AssemblySearchResult Create(PEFile module) }; } - public NamespaceSearchResult Create(PEFile module, INamespace ns) + public NamespaceSearchResult Create(MetadataFile module, INamespace ns) { var name = ns.FullName.Length == 0 ? "-" : ns.FullName; return new NamespaceSearchResult { @@ -165,7 +165,7 @@ public ITreeNode Create(Resource resource) return ResourceTreeNode.Create(resource); } - public ITreeNode CreateResourcesList(PEFile module) + public ITreeNode CreateResourcesList(MetadataFile module) { return new ResourceListTreeNode(module); } diff --git a/ILSpy/SessionSettings.cs b/ILSpy/SessionSettings.cs index ad53d408cd..4004513c59 100644 --- a/ILSpy/SessionSettings.cs +++ b/ILSpy/SessionSettings.cs @@ -60,9 +60,6 @@ public SessionSettings(ILSpySettings spySettings) this.WindowState = FromString((string)doc.Element("WindowState"), WindowState.Normal); this.WindowBounds = FromString((string)doc.Element("WindowBounds"), DefaultWindowBounds); - this.SplitterPosition = FromString((string)doc.Element("SplitterPosition"), 0.4); - this.TopPaneSplitterPosition = FromString((string)doc.Element("TopPaneSplitterPosition"), 0.3); - this.BottomPaneSplitterPosition = FromString((string)doc.Element("BottomPaneSplitterPosition"), 0.3); this.SelectedSearchMode = FromString((string)doc.Element("SelectedSearchMode"), SearchMode.TypeAndMember); this.Theme = FromString((string)doc.Element(nameof(Theme)), ThemeManager.Current.DefaultTheme); string currentCulture = (string)doc.Element(nameof(CurrentCulture)); @@ -119,11 +116,6 @@ public string ActiveAssemblyList { public WindowState WindowState = WindowState.Normal; public Rect WindowBounds; internal static Rect DefaultWindowBounds = new Rect(10, 10, 750, 550); - /// - /// position of the left/right splitter - /// - public double SplitterPosition; - public double TopPaneSplitterPosition, BottomPaneSplitterPosition; public DockLayoutSettings DockLayout { get; private set; } @@ -145,9 +137,6 @@ public XElement ToXml() } doc.Add(new XElement("WindowState", ToString(this.WindowState))); doc.Add(new XElement("WindowBounds", ToString(this.WindowBounds))); - doc.Add(new XElement("SplitterPosition", ToString(this.SplitterPosition))); - doc.Add(new XElement("TopPaneSplitterPosition", ToString(this.TopPaneSplitterPosition))); - doc.Add(new XElement("BottomPaneSplitterPosition", ToString(this.BottomPaneSplitterPosition))); doc.Add(new XElement("SelectedSearchMode", ToString(this.SelectedSearchMode))); doc.Add(new XElement(nameof(Theme), ToString(this.Theme))); if (this.CurrentCulture != null) diff --git a/ILSpy/TextView/AvalonEditTextOutput.cs b/ILSpy/TextView/AvalonEditTextOutput.cs index dca58e1026..da62890a0f 100644 --- a/ILSpy/TextView/AvalonEditTextOutput.cs +++ b/ILSpy/TextView/AvalonEditTextOutput.cs @@ -260,7 +260,7 @@ public void WriteReference(Decompiler.Disassembler.OpCodeInfo opCode, bool omitS references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = opCode }); } - public void WriteReference(PEFile module, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) + public void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) { WriteIndent(); int start = this.TextLength; @@ -268,9 +268,9 @@ public void WriteReference(PEFile module, Handle handle, string text, string pro int end = this.TextLength; if (isDefinition) { - this.DefinitionLookup.AddDefinition((module, handle), this.TextLength); + this.DefinitionLookup.AddDefinition((metadata, handle), this.TextLength); } - references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = new EntityReference(module, handle, protocol), IsDefinition = isDefinition }); + references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = new EntityReference(metadata, handle, protocol), IsDefinition = isDefinition }); } public void WriteReference(IType type, string text, bool isDefinition = false) diff --git a/ILSpy/TextView/DecompilerTextEditor.cs b/ILSpy/TextView/DecompilerTextEditor.cs new file mode 100644 index 0000000000..f258794496 --- /dev/null +++ b/ILSpy/TextView/DecompilerTextEditor.cs @@ -0,0 +1,13 @@ +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Rendering; + +namespace ICSharpCode.ILSpy.TextView; + +public class DecompilerTextEditor : TextEditor +{ + protected override IVisualLineTransformer CreateColorizer(IHighlightingDefinition highlightingDefinition) + { + return new ThemeAwareHighlightingColorizer(highlightingDefinition); + } +} diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index c01e7ceb40..00ce4204b2 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -450,9 +450,9 @@ void ToolTipClosed(object? sender, EventArgs e) renderer.AddSignatureBlock(richText.Text, richText.ToRichTextModel()); try { - if (resolved.ParentModule == null || resolved.ParentModule.PEFile == null) + if (resolved.ParentModule == null || resolved.ParentModule.MetadataFile == null) return null; - var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentModule.PEFile); + var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentModule.MetadataFile); if (docProvider != null) { string documentation = docProvider.GetDocumentation(resolved.GetIdString()); diff --git a/ILSpy/TextView/DecompilerTextView.xaml b/ILSpy/TextView/DecompilerTextView.xaml index 42786e3968..2230cae602 100644 --- a/ILSpy/TextView/DecompilerTextView.xaml +++ b/ILSpy/TextView/DecompilerTextView.xaml @@ -1,17 +1,16 @@  + xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" + xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" + xmlns:local="clr-namespace:ICSharpCode.ILSpy.TextView" + xmlns:editing="clr-namespace:ICSharpCode.AvalonEdit.Editing;assembly=ICSharpCode.AvalonEdit" + xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit" + xmlns:styles="urn:TomsToolbox.Wpf.Styles" + xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"> - + - - - + + + + Value="True"> + Property="HorizontalScrollBarVisibility" + Value="Disabled" /> - - + + @@ -102,10 +101,10 @@ - + - public sealed class AssemblyReferenceTreeNode : ILSpyTreeNode { + readonly MetadataModule module; readonly AssemblyReference r; readonly AssemblyTreeNode parentAssembly; - public AssemblyReferenceTreeNode(AssemblyReference r, AssemblyTreeNode parentAssembly) + public AssemblyReferenceTreeNode(MetadataModule module, AssemblyReference r, AssemblyTreeNode parentAssembly) { + this.module = module ?? throw new ArgumentNullException(nameof(module)); this.r = r ?? throw new ArgumentNullException(nameof(r)); this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly)); this.LazyLoading = true; } - public IAssemblyReference AssemblyNameReference => r; + public AssemblyReference AssemblyReference => r; public override object Text { get { return Language.EscapeName(r.Name) + GetSuffixString(r.Handle); } @@ -75,12 +78,15 @@ public override void ActivateItem(System.Windows.RoutedEventArgs e) protected override void LoadChildren() { - var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(); - var module = resolver.Resolve(r); - if (module != null) + this.Children.Add(new AssemblyReferenceReferencedTypesTreeNode(module, r)); + + var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(MainWindow.Instance.CurrentDecompilerSettings.AutoLoadAssemblyReferences); + var referencedModule = resolver.Resolve(r); + if (referencedModule != null) { - foreach (var childRef in module.AssemblyReferences) - this.Children.Add(new AssemblyReferenceTreeNode(childRef, parentAssembly)); + var module = (MetadataModule)referencedModule.GetTypeSystemWithCurrentOptionsOrNull().MainModule; + foreach (var childRef in referencedModule.AssemblyReferences) + this.Children.Add(new AssemblyReferenceTreeNode(module, childRef, parentAssembly)); } } diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index 2cc3744232..aec26fcc08 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -29,10 +29,11 @@ using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpy.Options; +using ICSharpCode.ILSpy.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.FileLoaders; using ICSharpCode.ILSpyX.PdbProvider; using ICSharpCode.TreeView; @@ -98,7 +99,19 @@ public override object Icon { _ => Images.Library, }; } - return Images.Assembly; + if (loadResult.MetadataFile != null) + { + return loadResult.MetadataFile.Kind switch { + MetadataFile.MetadataFileKind.PortableExecutable => Images.Assembly, + MetadataFile.MetadataFileKind.ProgramDebugDatabase => Images.ProgramDebugDatabase, + MetadataFile.MetadataFileKind.WebCIL => Images.WebAssemblyFile, + _ => Images.MetadataFile, + }; + } + else + { + return Images.Assembly; + } } else { @@ -117,7 +130,7 @@ public override object ToolTip { if (tooltip == null && LoadedAssembly.IsLoaded) { tooltip = new TextBlock(); - var module = LoadedAssembly.GetPEFileOrNull(); + var module = LoadedAssembly.GetMetadataFileOrNull(); var metadata = module?.Metadata; if (metadata?.IsAssembly == true && metadata.TryGetFullAssemblyName(out var assemblyName)) { @@ -129,9 +142,12 @@ public override object ToolTip { tooltip.Inlines.Add(new Run(LoadedAssembly.FileName)); if (module != null) { - tooltip.Inlines.Add(new LineBreak()); - tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); - tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(module))); + if (module is PEFile peFile) + { + tooltip.Inlines.Add(new LineBreak()); + tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); + tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(peFile))); + } string runtimeName = Language.GetRuntimeDisplayName(module); if (runtimeName != null) { @@ -173,7 +189,7 @@ async void Init() protected override void LoadChildren() { - LoadedAssembly.LoadResult loadResult; + LoadResult loadResult; try { loadResult = LoadedAssembly.GetLoadResultAsync().GetAwaiter().GetResult(); @@ -185,9 +201,25 @@ protected override void LoadChildren() } try { - if (loadResult.PEFile != null) + if (loadResult.MetadataFile != null) { - LoadChildrenForPEFile(loadResult.PEFile); + switch (loadResult.MetadataFile.Kind) + { + case MetadataFile.MetadataFileKind.PortableExecutable: + LoadChildrenForPEFile(loadResult.MetadataFile); + break; + case MetadataFile.MetadataFileKind.WebCIL: + LoadChildrenForWebCilFile((WebCilFile)loadResult.MetadataFile); + break; + default: + var metadata = loadResult.MetadataFile; + this.Children.Add(new MetadataTablesTreeNode(metadata)); + this.Children.Add(new StringHeapTreeNode(metadata)); + this.Children.Add(new UserStringHeapTreeNode(metadata)); + this.Children.Add(new GuidHeapTreeNode(metadata)); + this.Children.Add(new BlobHeapTreeNode(metadata)); + break; + } } else if (loadResult.Package != null) { @@ -201,16 +233,82 @@ protected override void LoadChildren() } } - void LoadChildrenForPEFile(PEFile module) + void LoadChildrenForPEFile(MetadataFile module) { typeSystem = LoadedAssembly.GetTypeSystemOrNull(); var assembly = (MetadataModule)typeSystem.MainModule; - this.Children.Add(new Metadata.MetadataTreeNode(module, this)); + this.Children.Add(new MetadataTreeNode(module, Resources.Metadata)); Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull(); if (debugInfo is PortableDebugInfoProvider ppdb && ppdb.GetMetadataReader() is System.Reflection.Metadata.MetadataReader reader) { - this.Children.Add(new Metadata.DebugMetadataTreeNode(module, ppdb.IsEmbedded, reader)); + this.Children.Add(new MetadataTreeNode(ppdb.ToMetadataFile(), $"Debug Metadata ({(ppdb.IsEmbedded ? "Embedded" : "From portable PDB")})")); + } + this.Children.Add(new ReferenceFolderTreeNode(module, this)); + if (module.Resources.Any()) + this.Children.Add(new ResourceListTreeNode(module)); + foreach (NamespaceTreeNode ns in namespaces.Values) + { + ns.Children.Clear(); + } + namespaces.Clear(); + bool useNestedStructure = MainWindow.Instance.CurrentDisplaySettings.UseNestedNamespaceNodes; + foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) + { + var ns = GetOrCreateNamespaceTreeNode(type.Namespace); + TypeTreeNode node = new TypeTreeNode(type, this); + typeDict[(TypeDefinitionHandle)type.MetadataToken] = node; + ns.Children.Add(node); + } + foreach (NamespaceTreeNode ns in namespaces.Values + .Where(ns => ns.Children.Count > 0 && ns.Parent == null) + .OrderBy(n => n.Name, NaturalStringComparer.Instance)) + { + this.Children.Add(ns); + SetPublicAPI(ns); + } + + NamespaceTreeNode GetOrCreateNamespaceTreeNode(string @namespace) + { + if (!namespaces.TryGetValue(@namespace, out NamespaceTreeNode ns)) + { + if (useNestedStructure) + { + int decimalIndex = @namespace.LastIndexOf('.'); + if (decimalIndex < 0) + { + var escapedNamespace = Language.EscapeName(@namespace); + ns = new NamespaceTreeNode(escapedNamespace); + } + else + { + var parentNamespaceTreeNode = GetOrCreateNamespaceTreeNode(@namespace.Substring(0, decimalIndex)); + var escapedInnerNamespace = Language.EscapeName(@namespace.Substring(decimalIndex + 1)); + ns = new NamespaceTreeNode(escapedInnerNamespace); + parentNamespaceTreeNode.Children.Add(ns); + } + } + else + { + var escapedNamespace = Language.EscapeName(@namespace); + ns = new NamespaceTreeNode(escapedNamespace); + } + namespaces.Add(@namespace, ns); + } + return ns; + } + } + + void LoadChildrenForWebCilFile(WebCilFile module) + { + typeSystem = LoadedAssembly.GetTypeSystemOrNull(); + var assembly = (MetadataModule)typeSystem.MainModule; + this.Children.Add(new MetadataTreeNode(module, Resources.Metadata)); + Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull(); + if (debugInfo is PortableDebugInfoProvider ppdb + && ppdb.GetMetadataReader() is System.Reflection.Metadata.MetadataReader reader) + { + this.Children.Add(new MetadataTreeNode(ppdb.ToMetadataFile(), $"Debug Metadata ({(ppdb.IsEmbedded ? "Embedded" : "From portable PDB")})")); } this.Children.Add(new ReferenceFolderTreeNode(module, this)); if (module.Resources.Any()) @@ -365,7 +463,7 @@ void HandleException(Exception ex, string message) try { var loadResult = LoadedAssembly.GetLoadResultAsync().GetAwaiter().GetResult(); - if (loadResult.PEFile != null) + if (loadResult.MetadataFile != null) { language.DecompileAssembly(LoadedAssembly, output, options); } @@ -374,9 +472,9 @@ void HandleException(Exception ex, string message) output.WriteLine("// " + LoadedAssembly.FileName); DecompilePackage(loadResult.Package, output); } - else + else if (loadResult.FileLoadException != null) { - LoadedAssembly.GetPEFileOrNullAsync().GetAwaiter().GetResult(); + HandleException(loadResult.FileLoadException, loadResult.FileLoadException.Message); } } catch (BadImageFormatException badImage) @@ -391,7 +489,7 @@ void HandleException(Exception ex, string message) { HandleException(dirNotFound, "The directory was not found."); } - catch (PEFileNotSupportedException notSupported) + catch (MetadataFileNotSupportedException notSupported) { HandleException(notSupported, notSupported.Message); } @@ -545,7 +643,7 @@ public async void Execute(TextViewContext context) { var la = ((AssemblyTreeNode)node).LoadedAssembly; var resolver = la.GetAssemblyResolver(); - var module = la.GetPEFileOrNull(); + var module = la.GetMetadataFileOrNull(); if (module != null) { var metadata = module.Metadata; diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs index d2d79650c5..4b8100747d 100644 --- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs +++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs @@ -34,10 +34,10 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class BaseTypesTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; readonly ITypeDefinition type; - public BaseTypesTreeNode(PEFile module, ITypeDefinition type) + public BaseTypesTreeNode(MetadataFile module, ITypeDefinition type) { this.module = module; this.type = type; @@ -53,7 +53,7 @@ protected override void LoadChildren() AddBaseTypes(this.Children, module, type); } - internal static void AddBaseTypes(SharpTreeNodeCollection children, PEFile module, ITypeDefinition typeDefinition) + internal static void AddBaseTypes(SharpTreeNodeCollection children, MetadataFile module, ITypeDefinition typeDefinition) { TypeDefinitionHandle handle = (TypeDefinitionHandle)typeDefinition.MetadataToken; DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver(), diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs index 46dcbf6d70..7a0b7accd9 100644 --- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs @@ -64,10 +64,10 @@ IEnumerable FetchChildren(CancellationToken cancellationToken) internal static IEnumerable FindDerivedTypes(AssemblyList list, ITypeDefinition type, CancellationToken cancellationToken) { - var definitionMetadata = type.ParentModule.PEFile.Metadata; + var definitionMetadata = type.ParentModule.MetadataFile.Metadata; var metadataToken = (SRM.TypeDefinitionHandle)type.MetadataToken; var assemblies = list.GetAllAssemblies().GetAwaiter().GetResult() - .Select(node => node.GetPEFileOrNull()).Where(asm => asm != null).ToArray(); + .Select(node => node.GetMetadataFileOrNull()).Where(asm => asm != null).ToArray(); foreach (var module in assemblies) { var metadata = module.Metadata; diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs index 9f73940f97..0499f5dff6 100644 --- a/ILSpy/TreeNodes/EventTreeNode.cs +++ b/ILSpy/TreeNodes/EventTreeNode.cs @@ -51,7 +51,7 @@ public EventTreeNode(IEvent @event) private IEvent GetEventDefinition() { - return ((MetadataModule)EventDefinition.ParentModule.PEFile + return ((MetadataModule)EventDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((EventDefinitionHandle)EventDefinition.MetadataToken) ?? EventDefinition; } diff --git a/ILSpy/TreeNodes/ExportedTypeTreeNode.cs b/ILSpy/TreeNodes/ExportedTypeTreeNode.cs new file mode 100644 index 0000000000..262d4c7a99 --- /dev/null +++ b/ILSpy/TreeNodes/ExportedTypeTreeNode.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; + +namespace ICSharpCode.ILSpy.TreeNodes +{ + /// + /// exported type within assembly reference list. + /// + public sealed class ExportedTypeTreeNode : ILSpyTreeNode + { + readonly MetadataModule module; + readonly ExportedTypeMetadata r; + readonly IType resolvedType; + + public ExportedTypeTreeNode(MetadataModule module, ExportedTypeMetadata r) + { + this.module = module ?? throw new ArgumentNullException(nameof(module)); + this.r = r ?? throw new ArgumentNullException(nameof(r)); + this.resolvedType = module.ResolveType(r.Handle, default); + + this.LazyLoading = true; + } + + public override object Text + => Language.TypeToString(resolvedType, includeNamespace: true) + GetSuffixString(r.Handle); + + public override object Icon => Images.ExportedType; + + protected override void LoadChildren() + { + foreach (var exportedType in r.ExportedTypes) + this.Children.Add(new ExportedTypeTreeNode(module, exportedType)); + } + + public override bool ShowExpander => !r.ExportedTypes.IsEmpty; + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, $"{Language.TypeToString(resolvedType, includeNamespace: true)} (Exported, IsForwarder: {r.IsForwarder}, Attributes: {(int)r.Attributes:X8})"); + } + } +} diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index 3219abcd55..4df85b89fa 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -43,7 +43,7 @@ public FieldTreeNode(IField field) private IField GetFieldDefinition() { - return ((MetadataModule)FieldDefinition.ParentModule.PEFile + return ((MetadataModule)FieldDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((FieldDefinitionHandle)FieldDefinition.MetadataToken) ?? FieldDefinition; } diff --git a/ILSpy/TreeNodes/MemberReferenceTreeNode.cs b/ILSpy/TreeNodes/MemberReferenceTreeNode.cs new file mode 100644 index 0000000000..33ae47cffc --- /dev/null +++ b/ILSpy/TreeNodes/MemberReferenceTreeNode.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Reflection.Metadata; + +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; + +namespace ICSharpCode.ILSpy.TreeNodes +{ + /// + /// Reference to member from assembly reference list. + /// + public sealed class MemberReferenceTreeNode : ILSpyTreeNode + { + readonly MetadataModule module; + readonly MemberReferenceMetadata r; + readonly IMember resolvedMember; + + public MemberReferenceTreeNode(MetadataModule module, MemberReferenceMetadata r) + { + this.module = module ?? throw new ArgumentNullException(nameof(module)); + this.r = r; + this.resolvedMember = r.MemberReferenceKind switch { + MemberReferenceKind.Method => module.ResolveMethod(r.Handle, default), + MemberReferenceKind.Field => (IMember)module.ResolveEntity(r.Handle), + _ => throw new NotSupportedException(), + }; + } + + public override object Text => Signature + GetSuffixString(r.Handle); + + public override object Icon => r.MemberReferenceKind switch { + MemberReferenceKind.Method => Images.MethodReference, + MemberReferenceKind.Field => Images.FieldReference, + _ => throw new NotSupportedException(), + }; + + public string Signature => resolvedMember is IMethod m ? Language.MethodToString(m, false, false, false) : Language.FieldToString((IField)resolvedMember, false, false, false); + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, Signature); + } + + public override object ToolTip => Language.GetRichTextTooltip(resolvedMember); + } +} diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index 03bd8bd1ef..c805d5a83b 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -43,7 +43,7 @@ public MethodTreeNode(IMethod method) private IMethod GetMethodDefinition() { - return ((MetadataModule)MethodDefinition.ParentModule.PEFile + return ((MetadataModule)MethodDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((MethodDefinitionHandle)MethodDefinition.MetadataToken) ?? MethodDefinition; } diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs index b800e55911..e3c2481311 100644 --- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs @@ -20,6 +20,7 @@ using System.Reflection.Metadata; using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.TreeNodes { @@ -28,6 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ModuleReferenceTreeNode : ILSpyTreeNode { + readonly MetadataFile module; readonly AssemblyTreeNode parentAssembly; readonly MetadataReader metadata; readonly ModuleReferenceHandle handle; @@ -37,20 +39,21 @@ sealed class ModuleReferenceTreeNode : ILSpyTreeNode readonly string moduleName; readonly bool containsMetadata; - public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataReader module) + public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataFile module) { this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly)); if (r.IsNil) throw new ArgumentNullException(nameof(r)); - this.metadata = module; this.handle = r; - this.reference = module.GetModuleReference(r); + this.module = module ?? throw new ArgumentNullException(nameof(module)); + this.metadata = module.Metadata; + this.reference = module.Metadata.GetModuleReference(r); this.moduleName = Language.EscapeName(metadata.GetString(reference.Name)); - foreach (var h in module.AssemblyFiles) + foreach (var h in metadata.AssemblyFiles) { - var file = module.GetAssemblyFile(h); - if (module.StringComparer.Equals(file.Name, moduleName)) + var file = metadata.GetAssemblyFile(h); + if (metadata.StringComparer.Equals(file.Name, moduleName)) { this.file = file; this.fileHandle = h; @@ -72,7 +75,7 @@ public override void ActivateItem(System.Windows.RoutedEventArgs e) if (assemblyListNode != null && containsMetadata) { var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(); - var mainModule = parentAssembly.LoadedAssembly.GetPEFileOrNull(); + var mainModule = parentAssembly.LoadedAssembly.GetMetadataFileOrNull(); if (mainModule != null) { assemblyListNode.Select(assemblyListNode.FindAssemblyNode(resolver.ResolveModule(mainModule, metadata.GetString(reference.Name)))); diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs index a495c6e794..ab437f8d4f 100644 --- a/ILSpy/TreeNodes/PropertyTreeNode.cs +++ b/ILSpy/TreeNodes/PropertyTreeNode.cs @@ -53,7 +53,7 @@ public PropertyTreeNode(IProperty property) private IProperty GetPropertyDefinition() { - return ((MetadataModule)PropertyDefinition.ParentModule.PEFile + return ((MetadataModule)PropertyDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((PropertyDefinitionHandle)PropertyDefinition.MetadataToken) ?? PropertyDefinition; } diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs index 347e07d670..2f3942083d 100644 --- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs +++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs @@ -22,6 +22,7 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy.TreeNodes @@ -31,10 +32,10 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ReferenceFolderTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; readonly AssemblyTreeNode parentAssembly; - public ReferenceFolderTreeNode(PEFile module, AssemblyTreeNode parentAssembly) + public ReferenceFolderTreeNode(MetadataFile module, AssemblyTreeNode parentAssembly) { this.module = module; this.parentAssembly = parentAssembly; @@ -48,10 +49,11 @@ public ReferenceFolderTreeNode(PEFile module, AssemblyTreeNode parentAssembly) protected override void LoadChildren() { var metadata = module.Metadata; + var metadataModule = (MetadataModule)module.GetTypeSystemWithCurrentOptionsOrNull().MainModule; foreach (var r in module.AssemblyReferences.OrderBy(r => r.Name)) - this.Children.Add(new AssemblyReferenceTreeNode(r, parentAssembly)); + this.Children.Add(new AssemblyReferenceTreeNode(metadataModule, r, parentAssembly)); foreach (var r in metadata.GetModuleReferences().OrderBy(r => metadata.GetString(metadata.GetModuleReference(r).Name))) - this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, metadata)); + this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, module)); } public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs index 5b5b80b33e..d812b79666 100644 --- a/ILSpy/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs @@ -23,7 +23,6 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; -using ICSharpCode.ILSpyX.Abstractions; namespace ICSharpCode.ILSpy.TreeNodes { @@ -32,9 +31,9 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ResourceListTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; - public ResourceListTreeNode(PEFile module) + public ResourceListTreeNode(MetadataFile module) { this.LazyLoading = true; this.module = module; diff --git a/ILSpy/TreeNodes/TypeReferenceTreeNode.cs b/ILSpy/TreeNodes/TypeReferenceTreeNode.cs new file mode 100644 index 0000000000..d8039181cf --- /dev/null +++ b/ILSpy/TreeNodes/TypeReferenceTreeNode.cs @@ -0,0 +1,73 @@ +// Copyright (c) 2023 James May +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; + +namespace ICSharpCode.ILSpy.TreeNodes +{ + /// + /// referenced type within assembly reference list. + /// + public sealed class TypeReferenceTreeNode : ILSpyTreeNode + { + readonly MetadataModule module; + readonly TypeReferenceMetadata r; + readonly IType resolvedType; + + public TypeReferenceTreeNode(MetadataModule module, TypeReferenceMetadata r) + { + this.module = module ?? throw new ArgumentNullException(nameof(module)); + this.r = r ?? throw new ArgumentNullException(nameof(r)); + this.resolvedType = module.ResolveType(r.Handle, default); + + this.LazyLoading = true; + } + + public override object Text + => Language.TypeToString(resolvedType, includeNamespace: false) + GetSuffixString(r.Handle); + + public override object Icon => Images.TypeReference; + + protected override void LoadChildren() + { + foreach (var typeRef in r.TypeReferences) + this.Children.Add(new TypeReferenceTreeNode(module, typeRef)); + + foreach (var memberRef in r.MemberReferences) + this.Children.Add(new MemberReferenceTreeNode(module, memberRef)); + } + + public override bool ShowExpander => !r.TypeReferences.IsEmpty || !r.MemberReferences.IsEmpty; + + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) + { + language.WriteCommentLine(output, Language.TypeToString(resolvedType, includeNamespace: true)); + EnsureLazyChildren(); + foreach (ILSpyTreeNode child in Children) + { + output.Indent(); + child.Decompile(language, output, options); + output.Unindent(); + } + } + } +} diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 83126d88c3..5917f35e0a 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -48,7 +48,7 @@ public TypeTreeNode(ITypeDefinition typeDefinition, AssemblyTreeNode parentAssem private ITypeDefinition GetTypeDefinition() { return ((MetadataModule)ParentAssemblyNode.LoadedAssembly - .GetPEFileOrNull() + .GetMetadataFileOrNull() ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule).GetDefinition((SRM.TypeDefinitionHandle)TypeDefinition.MetadataToken); } @@ -87,7 +87,7 @@ public override FilterResult Filter(FilterSettings settings) protected override void LoadChildren() { if (TypeDefinition.DirectBaseTypes.Any()) - this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetPEFileOrNull(), TypeDefinition)); + this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetMetadataFileOrNull(), TypeDefinition)); if (!TypeDefinition.IsSealed) this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition)); foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) diff --git a/NuGet.config b/NuGet.config index 40b60b1652..5209a02bfd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,23 @@  - + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 9db6276d51..adb3b2c8e7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Decompiler Frontends Aside from the WPF UI ILSpy (downloadable via Releases, see also [plugins](https://github.com/icsharpcode/ILSpy/wiki/Plugins)), the following other frontends are available: -* Visual Studio 2022 ships with decompilation support for F12 enabled by default (using our engine v7.1). +* Visual Studio 2022 ships with decompilation support for F12 enabled by default (using our engine v8.1). * In Visual Studio 2019, you have to manually enable F12 support. Go to Tools / Options / Text Editor / C# / Advanced and check "Enable navigation to decompiled source" * [C# for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) ships with decompilation support as well. To enable, activate the setting "Enable Decompilation Support". * Our Visual Studio 2022 extension [marketplace](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.ILSpy2022) @@ -48,11 +48,11 @@ How to build - Make sure PowerShell (at least version) 5.0 is installed. - Clone the ILSpy repository using git. - Execute `git submodule update --init --recursive` to download the ILSpy-Tests submodule (used by some test cases). -- Install Visual Studio (documented version: 17.1). You can install the necessary components in one of 3 ways: +- Install Visual Studio (documented version: 17.8). You can install the necessary components in one of 3 ways: - Follow Microsoft's instructions for [importing a configuration](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022#import-a-configuration), and import the .vsconfig file located at the root of the solution. - Alternatively, you can open the ILSpy solution (ILSpy.sln) and Visual Studio will [prompt you to install the missing components](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022#automatically-install-missing-components). - Finally, you can manually install the necessary components via the Visual Studio Installer. The workloads/components are as follows: - - Workload ".NET Desktop Development". This workload includes the .NET Framework 4.8 SDK and the .NET Framework 4.7.2 targeting pack, as well as the [.NET 6.0 SDK](https://dotnet.microsoft.com/download/dotnet/6.0) and [.NET 7.0 SDK](https://dotnet.microsoft.com/download/dotnet/7.0) (ILSpy.csproj targets .NET 6.0, but we have net472+net70 projects too). _Note: The optional components of this workload are not required for ILSpy_ + - Workload ".NET Desktop Development". This workload includes the .NET Framework 4.8 SDK and the .NET Framework 4.7.2 targeting pack, as well as the [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) (ILSpy.csproj targets .NET 6.0, but we have net472 projects too). _Note: The optional components of this workload are not required for ILSpy_ - Workload "Visual Studio extension development" (ILSpy.sln contains a VS extension project) _Note: The optional components of this workload are not required for ILSpy_ - Individual Component "MSVC v143 - VS 2022 C++ x64/x86 build tools" (or similar) - _The VC++ toolset is optional_; if present it is used for `editbin.exe` to modify the stack size used by ILSpy.exe from 1MB to 16MB, because the decompiler makes heavy use of recursion, where small stack sizes lead to problems in very complex methods. @@ -71,7 +71,7 @@ If this problem occurs, please manually install the .NET 6.0 SDK from [here](htt #### Unix / Mac: -- Make sure [.NET 7.0 SDK](https://dotnet.microsoft.com/download/dotnet/7.0) is installed. +- Make sure [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) is installed. - Make sure [PowerShell](https://github.com/PowerShell/PowerShell) is installed (formerly known as PowerShell Core) - Clone the repository using git. - Execute `git submodule update --init --recursive` to download the ILSpy-Tests submodule (used by some test cases). diff --git a/SharpTreeView/ICSharpCode.TreeView.csproj b/SharpTreeView/ICSharpCode.TreeView.csproj index 2929c0b301..a0b1c2b99e 100644 --- a/SharpTreeView/ICSharpCode.TreeView.csproj +++ b/SharpTreeView/ICSharpCode.TreeView.csproj @@ -5,7 +5,7 @@ true False True - net6.0-windows + net8.0-windows ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk true @@ -20,10 +20,8 @@ true - - - + diff --git a/TestPlugin/ContextMenuCommand.cs b/TestPlugin/ContextMenuCommand.cs index 6bbf3475b3..9dc672fe5f 100644 --- a/TestPlugin/ContextMenuCommand.cs +++ b/TestPlugin/ContextMenuCommand.cs @@ -6,8 +6,6 @@ using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TreeNodes; -using Microsoft.Win32; - namespace TestPlugin { [ExportContextMenuEntryAttribute(Header = "_Save Assembly")] @@ -28,7 +26,7 @@ public void Execute(TextViewContext context) if (context.SelectedTreeNodes == null) return; AssemblyTreeNode node = (AssemblyTreeNode)context.SelectedTreeNodes[0]; - var asm = node.LoadedAssembly.GetPEFileOrNull(); + var asm = node.LoadedAssembly.GetMetadataFileOrNull(); if (asm != null) { /*SaveFileDialog dlg = new SaveFileDialog(); diff --git a/TestPlugin/CustomLanguage.cs b/TestPlugin/CustomLanguage.cs index 4914edc261..e41ea015eb 100644 --- a/TestPlugin/CustomLanguage.cs +++ b/TestPlugin/CustomLanguage.cs @@ -6,7 +6,6 @@ using System.Windows.Controls; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy; @@ -34,11 +33,11 @@ public override string FileExtension { // There are several methods available to override; in this sample, we deal with methods only public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - var module = ((MetadataModule)method.ParentModule).PEFile; + var module = ((MetadataModule)method.ParentModule).MetadataFile; var methodDef = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); if (methodDef.HasBody()) { - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); output.WriteLine("Size of method: {0} bytes", methodBody.GetCodeSize()); ISmartTextOutput smartOutput = output as ISmartTextOutput; diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj index 5ff29f0b23..50d7dadba6 100644 --- a/TestPlugin/TestPlugin.csproj +++ b/TestPlugin/TestPlugin.csproj @@ -1,7 +1,7 @@  - net6.0-windows + net8.0-windows Test.Plugin true true diff --git a/global.json b/global.json index 1fcfe4feea..6a5d4badd3 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.100", + "version": "8.0.100", "rollForward": "major", "allowPrerelease": true } diff --git a/packages.props b/packages.props deleted file mode 100644 index 236f7b6617..0000000000 --- a/packages.props +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - 7.0.0 - 7.0.0 - 6.0.0 - 6.0.0 - - 1.1.0-beta2-22171-02 - 0.11.4 - 6.3.0.90 - 2.8.7 - - - - 3.13.3 - 4.4.2 - 3.0.124 - 3.2.0 - 17.5.0 - 2017.7.26.1241 - - 4.6.0 - - 7.0.0 - - 7.0.0 - - diff --git a/publish.ps1 b/publish.ps1 index c2be01b3dc..6854d2f93a 100644 --- a/publish.ps1 +++ b/publish.ps1 @@ -1,6 +1,6 @@ -$output_arm64 = "./ILSpy/bin/Release/net6.0-windows/win-arm64/publish/fwdependent" -$output_x64 = "./ILSpy/bin/Release/net6.0-windows/win-x64/publish/fwdependent" -$output_x64_selfcontained = "./ILSpy/bin/Release/net6.0-windows/win-x64/publish/selfcontained" +$output_arm64 = "./ILSpy/bin/Release/net8.0-windows/win-arm64/publish/fwdependent" +$output_x64 = "./ILSpy/bin/Release/net8.0-windows/win-x64/publish/fwdependent" +$output_x64_selfcontained = "./ILSpy/bin/Release/net8.0-windows/win-x64/publish/selfcontained" dotnet publish ./ILSpy/ILSpy.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64 dotnet publish ./ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64