Browse Source

Merge branch 'master' into dependabot/github_actions/dessant/lock-threads-4.0.0

pull/3027/head^2
Charlie Lin 2 years ago committed by GitHub
parent
commit
6aeee57358
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/build-frontends.yml
  2. 58
      .github/workflows/build-ilspy.yml
  3. 2
      .github/workflows/codeql-analysis.yml
  4. 3
      .github/workflows/lock.yml
  5. 2
      .gitignore
  6. 10
      BuildTools/pre-commit
  7. 4
      ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs
  8. 4
      ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
  9. 11
      ICSharpCode.Decompiler.PowerShell/README.md
  10. 129
      ICSharpCode.Decompiler.PowerShell/manifest.psd1
  11. 2
      ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
  12. 13
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  13. 23
      ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs
  14. 31
      ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs
  15. 12
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  16. 91
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  17. 27
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  18. 6
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  19. 58
      ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs
  20. 74
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  21. 6
      ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs
  22. 26
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs
  23. 31
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs
  24. 32
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il
  25. 2
      ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/.gitignore
  26. 75
      ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/InterfaceImplAttributes.il
  27. 395
      ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/SortMembers.expected.il
  28. 381
      ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/SortMembers.il
  29. 14
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.cs
  30. 45
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.il
  31. 39
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/GuessAccessors.cs
  32. 22
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/GuessAccessors.il
  33. 4
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs
  34. 26
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il
  35. 4
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/CustomPdbId.xml
  36. 44
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ProgressReporting.xml
  37. 17
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs
  38. 1117
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  39. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
  40. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs
  41. 44
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  42. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs
  43. 14
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs
  44. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs
  45. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  46. 41
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
  47. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs
  48. 225
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Operators.cs
  49. 58
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
  50. 29
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs
  51. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs
  52. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  53. 15
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs
  54. 87
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs
  55. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/StaticAbstractInterfaceMembers.cs
  56. 26
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Structs.cs
  57. 30
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  58. 61
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  59. 13
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs
  60. 4
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/.gitignore
  61. 262
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs
  62. 226
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.vb
  63. 14
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.cs
  64. 9
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.vb
  65. 20
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBNonGenericForEach.cs
  66. 11
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBNonGenericForEach.vb
  67. 419
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/YieldReturn.cs
  68. 300
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/YieldReturn.vb
  69. 10
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  70. 5
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
  71. 4
      ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs
  72. 189
      ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs
  73. BIN
      ICSharpCode.Decompiler.Tests/Util/Test.resources
  74. 26
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
  75. 130
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  76. 39
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  77. 75
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  78. 5
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  79. 11
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  80. 3
      ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs
  81. 1
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  82. 5
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs
  83. 6
      ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs
  84. 5
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs
  85. 14
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs
  86. 31
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs
  87. 187
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  88. 26
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  89. 2
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  90. 21
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  91. 18
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs
  92. 6
      ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolutionErrors.cs
  93. 53
      ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs
  94. 9
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs
  95. 6
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs
  96. 1
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs
  97. 1
      ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs
  98. 5
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs
  99. 28
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs
  100. 16
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  101. Some files were not shown because too many files have changed in this diff Show More

2
.github/workflows/build-frontends.yml

@ -15,7 +15,7 @@ jobs: @@ -15,7 +15,7 @@ jobs:
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v2
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x

58
.github/workflows/build-ilspy.yml

@ -27,7 +27,7 @@ jobs: @@ -27,7 +27,7 @@ jobs:
fetch-depth: 0
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v1.3
- 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
@ -37,7 +37,7 @@ jobs: @@ -37,7 +37,7 @@ jobs:
shell: pwsh
run: |
.\BuildTools\ghactions-install.ps1
Get-ChildItem Env: | Where-Object {$_.Name -Match "^ILSPY_"} | %{ echo "::set-output name=$($_.Name)::$($_.Value)" }
Get-ChildItem Env: | Where-Object {$_.Name -Match "^ILSPY_"} | %{ echo "$($_.Name)=$($_.Value)" } | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf8 -Append
- name: Restore the application
run: msbuild ILSpy.sln /t:Restore /p:Configuration=${{ matrix.configuration }} /p:Platform=$env:BuildPlatform
@ -60,7 +60,7 @@ jobs: @@ -60,7 +60,7 @@ jobs:
path: 'test-results/${{ matrix.configuration }}.xml'
- name: Create Test Report
uses: test-summary/action@v1
uses: test-summary/action@v2
if: always()
with:
paths: "test-results/${{ matrix.configuration }}.xml"
@ -78,14 +78,30 @@ jobs: @@ -78,14 +78,30 @@ jobs:
- 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
- name: Zip ILSpy Release (self-contained win-x64)
if: matrix.configuration == 'release'
- name: Publish x64/arm64 framework-dependent/self-contained
shell: pwsh
run: .\publish.ps1
- 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\*
- 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\*
- name: Build Installer (x64 and arm64, framework-dependent)
if: matrix.configuration == 'release'
run: |
msbuild ILSpy.Installer.sln /t:Restore /p:Configuration="Release" /p:Platform="Any CPU"
msbuild ILSpy.Installer.sln /p:Configuration="Release" /p:Platform="Any CPU"
msbuild ILSpy.Installer.sln /p:Configuration="Release" /p:Platform="Any CPU" /p:DefineConstants="ARM64"
- name: Build VS Extensions (for 2017-2019 and 2022)
if: matrix.configuration == 'release'
run: |
dotnet publish ./ILSpy/ILSpy.csproj -c Release --no-restore --self-contained -r win-x64
dotnet publish ./ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj -c Release --no-restore --self-contained -r win-x64
dotnet publish ./ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj -c Release --no-restore --self-contained -r win-x64
7z a -tzip $env:StagingDirectory\ILSpy_selfcontained_x64.zip .\ILSpy\bin\Release\net6.0-windows\win-x64\publish\*
msbuild ILSpy.VSExtensions.sln /t:Restore /p:Configuration="Release" /p:Platform="Any CPU"
msbuild ILSpy.VSExtensions.sln /p:Configuration="Release" /p:Platform="Any CPU"
# https://github.com/actions/upload-artifact
- name: Upload VSIX (VS 2019) release build artifacts
@ -137,7 +153,7 @@ jobs: @@ -137,7 +153,7 @@ jobs:
path: ${{ env.StagingDirectory }}\ILSpy_binaries.zip
if-no-files-found: error
- name: Upload self-contained zip build artifacts (Release-only)
- name: Upload x64 self-contained zip (Release-only)
if: matrix.configuration == 'release'
uses: actions/upload-artifact@v3
with:
@ -145,12 +161,28 @@ jobs: @@ -145,12 +161,28 @@ jobs:
path: ${{ env.StagingDirectory }}\ILSpy_selfcontained_x64.zip
if-no-files-found: error
- name: Upload installer artifact
- name: Upload arm64 framework-dependent zip (Release-only)
if: matrix.configuration == 'release'
uses: actions/upload-artifact@v3
with:
name: ILSpy arm64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }})
path: ${{ env.StagingDirectory }}\ILSpy_binaries_arm64.zip
if-no-files-found: error
- name: Upload x64 installer artifact
if: matrix.configuration == 'release'
uses: actions/upload-artifact@v3
with:
name: ILSpy Installer x64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }})
path: ILSpy.Installer\wix\*-x64.msi
if-no-files-found: error
- name: Upload arm64 installer artifact
if: matrix.configuration == 'release'
uses: actions/upload-artifact@v3
with:
name: ILSpy Installer ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }})
path: ILSpy.Installer\wix\*.msi
name: ILSpy Installer arm64 ${{ steps.version.outputs.ILSPY_VERSION_NUMBER }} (${{ matrix.configuration }})
path: ILSpy.Installer\wix\*-arm64.msi
if-no-files-found: error
- name: Upload ilspycmd release build artifacts

2
.github/workflows/codeql-analysis.yml

@ -28,7 +28,7 @@ jobs: @@ -28,7 +28,7 @@ jobs:
languages: ${{ matrix.language }}
- name: Setup .NET
uses: actions/setup-dotnet@v2
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x

3
.github/workflows/lock.yml

@ -8,7 +8,8 @@ jobs: @@ -8,7 +8,8 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v4.0.0
- uses: dessant/lock-threads@v4.0.1
with:
github-token: ${{ github.token }}
issue-inactive-days: '90'

2
.gitignore vendored

@ -8,6 +8,7 @@ _ReSharper*/ @@ -8,6 +8,7 @@ _ReSharper*/
*.ReSharper
*.patch
.vs/
.idea/
/ILSpy.AddIn*/Packages/*
/ILSpy.AddIn*/source.extension.vsixmanifest
/ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/*.dll
@ -18,3 +19,4 @@ multitargeting.props @@ -18,3 +19,4 @@ multitargeting.props
ILSpy.Installer/wix/
/VERSION
/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.cs
*/.vscode/

10
BuildTools/pre-commit

@ -12,9 +12,9 @@ if [ ! -d "$DOTNET_PATH" ]; then @@ -12,9 +12,9 @@ if [ ! -d "$DOTNET_PATH" ]; then
fi
"$DOTNET_PATH/dotnet-format.exe" --version
#if git diff --quiet --ignore-submodules; then
# "$DOTNET_PATH/dotnet-format.exe" whitespace --no-restore --verbosity detailed ILSpy.sln
# git add -u -- \*\*.cs
#else
if git diff --quiet --ignore-submodules; then
"$DOTNET_PATH/dotnet-format.exe" whitespace --no-restore --verbosity detailed ILSpy.sln
git add -u -- \*\*.cs
else
exec "$DOTNET_PATH/dotnet-format.exe" whitespace --verify-no-changes --no-restore --verbosity detailed ILSpy.sln
#fi
fi

4
ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs

@ -33,8 +33,8 @@ namespace ICSharpCode.Decompiler.PowerShell @@ -33,8 +33,8 @@ namespace ICSharpCode.Decompiler.PowerShell
lock (syncObject)
{
completed++;
progress = new ProgressRecord(1, "Decompiling " + fileName, $"Completed {completed} of {value.TotalNumberOfFiles}: {value.Status}") {
PercentComplete = (int)(completed * 100.0 / value.TotalNumberOfFiles)
progress = new ProgressRecord(1, "Decompiling " + fileName, $"Completed {completed} of {value.TotalUnits}: {value.Status}") {
PercentComplete = (int)(completed * 100.0 / value.TotalUnits)
};
}
}

4
ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj

@ -25,4 +25,8 @@ @@ -25,4 +25,8 @@
<Compile Include="..\ICSharpCode.ILSpyX\PdbProvider\DebugInfoUtils.cs" Link="DebugInfoUtils.cs" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Condition=" '$(OS)' == 'Windows_NT' " Command="powershell -Command &quot;Copy-Item $(ProjectDir)manifest.psd1 $(TargetDir)$(TargetName).psd1&quot;" />
<Exec Condition=" '$(OS)' != 'Windows_NT' " Command="pwsh -Command &quot;Copy-Item $(ProjectDir)manifest.psd1 $(TargetDir)$(TargetName).psd1&quot;" />
</Target>
</Project>

11
ICSharpCode.Decompiler.PowerShell/README.md

@ -4,20 +4,21 @@ Built using https://github.com/PowerShell/PowerShell/blob/master/docs/cmdlet-exa @@ -4,20 +4,21 @@ Built using https://github.com/PowerShell/PowerShell/blob/master/docs/cmdlet-exa
Sample usage: Demo.ps1
Tested with: PowerShell 5.1 on Windows, PowerShell Core on Windows and Mac (Beta9)
Tested with: PowerShell 5.1 on Windows, PowerShell 7+ on Windows and Mac
## Missing
.psd1 for deploying to https://www.powershellgallery.com/
Publishing to https://www.powershellgallery.com/
* https://learn.microsoft.com/en-us/powershell/gallery/how-to/publishing-packages/publishing-a-package
* https://learn.microsoft.com/en-us/powershell/gallery/concepts/publishing-guidelines
## Links for developing PS cmdlets
* https://docs.microsoft.com/en-us/powershell/gallery/psgallery/creating-and-publishing-an-item
* https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/how-to-write-a-simple-cmdlet
* https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands
* https://github.com/mmaitre314/PowerShellGet-Test-Binary-Module
* https://www.red-gate.com/simple-talk/dotnet/net-development/using-c-to-create-powershell-cmdlets-beyond-the-basics/
* https://msdn.microsoft.com/en-us/library/dd878294(v=VS.85).aspx Writing a Windows PowerShell Cmdlet
* https://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx Approved verbs
* https://www.google.com/search?q=write+a+module+for+powershell+core

129
ICSharpCode.Decompiler.PowerShell/manifest.psd1

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
@{
# Script module or binary module file associated with this manifest.
RootModule = 'ICSharpCode.Decompiler.PowerShell.dll'
# Version number of this module.
ModuleVersion = '8.0.0.0'
# Supported PSEditions
# CompatiblePSEditions = @()
# ID used to uniquely identify this module
GUID = '198b4312-cbe7-417e-81a7-1aaff467ef06'
# Author of this module
Author = 'ILSpy Contributors'
# Company or vendor of this module
CompanyName = 'ic#code'
# Copyright statement for this module
Copyright = 'Copyright 2011-2023 AlphaSierraPapa'
# Description of the functionality provided by this module
Description = 'PowerShell front-end for ILSpy'
# Minimum version of the PowerShell engine required by this module
# PowerShellVersion = ''
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @()
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @(
'Get-DecompiledProject',
'Get-DecompiledSource',
'Get-DecompiledTypes',
'Get-Decompiler',
'Get-DecompilerVersion'
)
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
ProjectUri = 'https://github.com/icsharpcode/ILSpy'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}

2
ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

13
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 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
@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.Tests
public async Task StackTests()
{
// IL contains .corflags = 32BITREQUIRED
await RunIL("StackTests.il", asmOptions: AssemblerOptions.Force32Bit);
await RunIL("StackTests.il", CompilerOptions.Force32Bit, AssemblerOptions.Force32Bit);
}
[Test]
@ -398,10 +398,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -398,10 +398,6 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task MiniJSON([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
if (options.HasFlag(CompilerOptions.UseMcs2_6_4))
{
Assert.Ignore("Decompiler bug with mono!");
}
await RunCS(options: options);
}
@ -487,6 +483,11 @@ namespace ICSharpCode.Decompiler.Tests @@ -487,6 +483,11 @@ namespace ICSharpCode.Decompiler.Tests
string outputFile = null;
CompilerResults decompiledOutputFile = null;
bool optionsForce32Bit = options.HasFlag(CompilerOptions.Force32Bit);
bool asmOptionsForce32Bit = asmOptions.HasFlag(AssemblerOptions.Force32Bit);
Assert.AreEqual(optionsForce32Bit, asmOptionsForce32Bit, "Inconsistent architecture.");
try
{
options |= CompilerOptions.UseTestRunner;

23
ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs

@ -58,15 +58,28 @@ namespace ICSharpCode.Decompiler.Tests @@ -58,15 +58,28 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
async Task Run([CallerMemberName] string testName = null)
[Test]
public async Task SortMembers()
{
await Run(ilExpectedFile: Path.Combine(TestCasePath, "SortMembers.expected.il"), asmOptions: AssemblerOptions.SortedOutput);
}
[Test]
public async Task InterfaceImplAttributes()
{
await Run();
}
async Task Run([CallerMemberName] string testName = null, string ilExpectedFile = null, AssemblerOptions asmOptions = AssemblerOptions.None)
{
var ilExpectedFile = Path.Combine(TestCasePath, testName + ".il");
var ilInputFile = Path.Combine(TestCasePath, testName + ".il");
ilExpectedFile ??= ilInputFile;
var ilResultFile = Path.Combine(TestCasePath, testName + ".result.il");
var executable = await Tester.AssembleIL(ilExpectedFile, AssemblerOptions.Library).ConfigureAwait(false);
var disassembled = await Tester.Disassemble(executable, ilResultFile, AssemblerOptions.UseOwnDisassembler).ConfigureAwait(false);
var executable = await Tester.AssembleIL(ilInputFile, AssemblerOptions.Library).ConfigureAwait(false);
var disassembled = await Tester.Disassemble(executable, ilResultFile, AssemblerOptions.UseOwnDisassembler | asmOptions).ConfigureAwait(false);
CodeAssert.FilesAreEqual(ilExpectedFile, ilResultFile);
CodeAssert.FilesAreEqual(ilExpectedFile, disassembled);
}
}
}

31
ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
if (section.Attributes.Count == 0)
section.Remove();
}
if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode")
if (section.AttributeTarget == "module" && type.Identifier is "UnverifiableCode" or "RefSafetyRules")
{
attribute.Remove();
if (section.Attributes.Count == 0)
@ -34,35 +34,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -34,35 +34,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
}
public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform
{
HashSet<string> attributeNames = new HashSet<string>() {
"System.Runtime.CompilerServices.IsReadOnlyAttribute",
"System.Runtime.CompilerServices.IsByRefLikeAttribute",
"System.Runtime.CompilerServices.IsUnmanagedAttribute",
"System.Runtime.CompilerServices.NullableAttribute",
"System.Runtime.CompilerServices.NullableContextAttribute",
"System.Runtime.CompilerServices.NativeIntegerAttribute",
"Microsoft.CodeAnalysis.EmbeddedAttribute",
};
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
var typeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition;
if (typeDefinition == null || !attributeNames.Contains(typeDefinition.FullName))
return;
if (typeDeclaration.Parent is NamespaceDeclaration ns && ns.Members.Count == 1)
ns.Remove();
else
typeDeclaration.Remove();
}
public void Run(AstNode rootNode, TransformContext context)
{
rootNode.AcceptVisitor(this);
}
}
public class RemoveNamespaceMy : DepthFirstAstVisitor, IAstTransform
{
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)

12
ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs

@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
string otherOptions = $"-noconfig " +
string otherOptions = $"-nologo -noconfig " +
"-optioninfer+ -optionexplicit+ " +
$"-langversion:{languageVersion} " +
$"/optimize{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";
@ -122,8 +122,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -122,8 +122,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
Assert.AreEqual(0, result.ExitCode, "vbc failed");
return results;

91
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -69,6 +69,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -69,6 +69,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
UseMcs5_23 = 0x2000,
UseTestRunner = 0x4000,
NullableEnable = 0x8000,
ReferenceUnsafe = 0x10000,
UseMcsMask = UseMcs2_6_4 | UseMcs5_23,
UseRoslynMask = UseRoslyn1_3_2 | UseRoslyn2_10_0 | UseRoslyn3_11_0 | UseRoslynLatest
}
@ -84,6 +85,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -84,6 +85,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
UseOwnDisassembler = 0x8,
/// Work around bug in .NET 5 ilasm (https://github.com/dotnet/runtime/issues/32400)
UseLegacyAssembler = 0x10,
/// UseSortByNameFilter, implies UseOwnDisassembler
SortedOutput = 0x20,
}
public static partial class Tester
@ -102,9 +105,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -102,9 +105,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
TesterPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
TestCasePath = Path.Combine(TesterPath, "../../../../TestCases");
#if DEBUG
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net6.0-windows");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net7.0");
#else
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net6.0-windows");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net7.0");
#endif
packagesPropsFile = Path.Combine(TesterPath, "../../../../../packages.props");
roslynLatestVersion = XDocument.Load(packagesPropsFile).XPathSelectElement("//RoslynVersion").Value;
@ -175,13 +178,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -175,13 +178,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
var command = Cli.Wrap(ilasmPath)
.WithArguments($"/nologo {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"")
.WithArguments($"/quiet {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"")
.WithValidation(CommandResultValidation.None);
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
Assert.AreEqual(0, result.ExitCode, "ilasm failed");
return outputFile;
@ -189,7 +198,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -189,7 +198,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static async Task<string> Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
{
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler))
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler) || asmOptions.HasFlag(AssemblerOptions.SortedOutput))
{
using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read))
using (var peFile = new PEFile(sourceFileName, peFileStream))
@ -198,7 +207,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -198,7 +207,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var metadata = peFile.Metadata;
var output = new PlainTextOutput(writer);
ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
rd.AssemblyResolver = new UniversalAssemblyResolver(sourceFileName, true, null);
if (asmOptions.HasFlag(AssemblerOptions.SortedOutput))
{
rd.EntityProcessor = new SortByNameProcessor();
}
rd.AssemblyResolver = new UniversalAssemblyResolver(sourceFileName, throwOnError: true, null);
rd.DetectControlStructure = false;
rd.WriteAssemblyReferences(metadata);
if (metadata.IsAssembly)
@ -223,8 +236,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -223,8 +236,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
Assert.AreEqual(0, result.ExitCode, "ildasm failed");
// Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic),
@ -251,8 +270,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -251,8 +270,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NET,
new Version(6, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v6.0");
new Version(7, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v7.0");
public static readonly string RefAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
@ -289,7 +308,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -289,7 +308,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
const string targetFrameworkAttributeSnippet = @"
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v6.0"", FrameworkDisplayName = """")]
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v7.0"", FrameworkDisplayName = """")]
";
@ -324,6 +343,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -324,6 +343,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
preprocessorSymbols.Add("NETCORE");
preprocessorSymbols.Add("NET60");
preprocessorSymbols.Add("NET70");
}
preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60");
@ -352,10 +372,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -352,10 +372,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
preprocessorSymbols.Add("ROSLYN4");
preprocessorSymbols.Add("CS100");
if (flags.HasFlag(CompilerOptions.Preview))
{
preprocessorSymbols.Add("CS110");
}
preprocessorSymbols.Add("CS110");
}
}
else if ((flags & CompilerOptions.UseMcsMask) != 0)
@ -425,7 +442,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -425,7 +442,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
string otherOptions = $"-noconfig " +
if (useRoslyn && !targetNet40 && flags.HasFlag(CompilerOptions.ReferenceUnsafe))
{
references = references.Concat(new[] { "-r:\"System.Runtime.CompilerServices.Unsafe.dll\"" });
}
string otherOptions = $"-nologo -noconfig " +
$"-langversion:{languageVersion} " +
$"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";
@ -477,12 +498,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -477,12 +498,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var command = Cli.Wrap(cscPath)
.WithArguments($"{otherOptions} -lib:{libPath} {string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
.WithValidation(CommandResultValidation.None);
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
//Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
Assert.AreEqual(0, result.ExitCode, "csc failed");
return results;
@ -533,12 +560,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -533,12 +560,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var command = Cli.Wrap(mcsPath)
.WithArguments($"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
.WithValidation(CommandResultValidation.None);
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
//Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
Assert.AreEqual(0, result.ExitCode, "mcs failed");
return results;
@ -553,7 +586,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -553,7 +586,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
CompilerOptions.UseRoslyn1_3_2 => CSharp.LanguageVersion.CSharp6,
CompilerOptions.UseRoslyn2_10_0 => CSharp.LanguageVersion.CSharp7_3,
CompilerOptions.UseRoslyn3_11_0 => CSharp.LanguageVersion.CSharp9_0,
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp10_0,
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp11_0,
};
DecompilerSettings settings = new(langVersion) {
// Never use file-scoped namespaces
@ -810,8 +843,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -810,8 +843,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);
Assert.AreEqual(0, result.ExitCode, "sn failed");
Console.WriteLine("output: " + result.StandardOutput);
Console.WriteLine("errors: " + result.StandardError);
if (!string.IsNullOrWhiteSpace(result.StandardOutput))
{
Console.WriteLine("output:" + Environment.NewLine + result.StandardOutput);
}
if (!string.IsNullOrWhiteSpace(result.StandardError))
{
Console.WriteLine("errors:" + Environment.NewLine + result.StandardError);
}
}
public static async Task<string> FindMSBuild()

27
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162</NoWarn>
<NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632;626;8618;8714;8602</NoWarn>
<GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
<EnableDefaultItems>false</EnableDefaultItems>
<AutoGenerateBindingRedirects>True</AutoGenerateBindingRedirects>
<EnableUnsafeBinaryFormatterSerialization>True</EnableUnsafeBinaryFormatterSerialization>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
@ -33,11 +34,11 @@ @@ -33,11 +34,11 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;ROSLYN;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
<DefineConstants>TRACE;DEBUG;ROSLYN;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;ROSLYN;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
<DefineConstants>TRACE;ROSLYN;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100</DefineConstants>
</PropertyGroup>
<Import Project="..\packages.props" />
@ -45,7 +46,7 @@ @@ -45,7 +46,7 @@
<ItemGroup>
<PackageReference Include="DiffLib" Version="$(DiffLibVersion)" />
<PackageReference Include="CliWrap" Version="3.4.4" />
<PackageReference Include="NuGet.Protocol" Version="6.2.1" />
<PackageReference Include="NuGet.Protocol" Version="6.2.4" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(RoslynVersion)" />
@ -57,10 +58,11 @@ @@ -57,10 +58,11 @@
<!-- used for xml test result files -->
<PackageReference Include="JunitXml.TestLogger" Version="$(JUnitXmlTestLoggerVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="Mono.Cecil" Version="$(MonoCecilVersion)" />
<PackageReference Include="Microsoft.NETCore.ILAsm" Version="$(ILAsmVersion)" />
<PackageReference Include="Microsoft.NETCore.ILDAsm" Version="$(ILDAsmVersion)" />
<PackageReference Include="System.Resources.Extensions" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
@ -73,6 +75,9 @@ @@ -73,6 +75,9 @@
<None Include="TestCases\Correctness\StackTests.il" />
<None Include="TestCases\Correctness\StackTypes.il" />
<None Include="TestCases\Correctness\Uninit.vb" />
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
<None Include="TestCases\Disassembler\Pretty\SortMembers.expected.il" />
<None Include="TestCases\Disassembler\Pretty\SortMembers.il" />
<None Include="TestCases\ILPretty\GuessAccessors.cs" />
<None Include="TestCases\ILPretty\GuessAccessors.il" />
<None Include="TestCases\ILPretty\Issue2260SwitchString.il" />
@ -110,6 +115,13 @@ @@ -110,6 +115,13 @@
<Compile Include="Output\InsertParenthesesVisitorTests.cs" />
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
<Compile Include="TestAssemblyResolver.cs" />
<Compile Include="Util\ResourceReaderWriterTests.cs" />
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
<Compile Include="TestCases\VBPretty\VBAutomaticEvents.cs" />
<Compile Include="TestCases\VBPretty\VBNonGenericForEach.cs" />
<None Include="TestCases\VBPretty\VBNonGenericForEach.vb" />
<Compile Include="TestCases\VBPretty\YieldReturn.cs" />
<None Include="TestCases\VBPretty\YieldReturn.vb" />
<Compile Include="TypeSystem\ReflectionHelperTests.cs" />
<None Include="TestCases\Pretty\MetadataAttributes.cs" />
<None Include="TestCases\Correctness\ComInterop.cs" />
@ -211,6 +223,7 @@ @@ -211,6 +223,7 @@
<None Include="TestCases\Pretty\MemberTests.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" />
<None Include="TestCases\Pretty\RefFields.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\TupleTests.cs" />
<Compile Include="TestCases\Pretty\WellKnownConstants.cs" />
@ -312,6 +325,7 @@ @@ -312,6 +325,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="TestCases\PdbGen\ProgressReporting.xml" />
<Content Include="TestCases\PdbGen\ForLoopTests.xml" />
<Content Include="TestCases\PdbGen\CustomPdbId.xml" />
<Content Include="TestCases\PdbGen\HelloWorld.xml" />
@ -326,6 +340,7 @@ @@ -326,6 +340,7 @@
<None Include="TestCases\VBPretty\VBCompoundAssign.vb" />
<None Include="TestCases\VBPretty\Async.vb" />
<None Include="TestCases\VBPretty\VBPropertiesTest.vb" />
<EmbeddedResource Include="Util\Test.resources" />
</ItemGroup>
</Project>

6
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -263,6 +263,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -263,6 +263,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
[Test]
public async Task EmptyBodies()
{
await Run();
}
async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
{

58
ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
@ -9,13 +8,10 @@ using System.Text; @@ -9,13 +8,10 @@ using System.Text;
using System.Xml.Linq;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.Decompiler.TypeSystem;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.DiaSymReader.Tools;
using NUnit.Framework;
@ -72,6 +68,60 @@ namespace ICSharpCode.Decompiler.Tests @@ -72,6 +68,60 @@ namespace ICSharpCode.Decompiler.Tests
}
}
[Test]
public void ProgressReporting()
{
// Generate a PDB for an assembly and validate that the progress reporter is called with reasonable values
(string peFileName, string pdbFileName) = CompileTestCase(nameof(ProgressReporting));
var moduleDefinition = new PEFile(peFileName);
var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Metadata.DetectTargetFrameworkId(), null, PEStreamOptions.PrefetchEntireImage);
var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings());
var lastFilesWritten = 0;
var totalFiles = -1;
Action<DecompilationProgress> reportFunc = progress => {
if (totalFiles == -1)
{
// Initialize value on first call
totalFiles = progress.TotalUnits;
}
Assert.AreEqual(progress.TotalUnits, totalFiles);
Assert.AreEqual(progress.UnitsCompleted, lastFilesWritten + 1);
lastFilesWritten = progress.UnitsCompleted;
};
using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, nameof(ProgressReporting) + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
pdbStream.SetLength(0);
PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true, progress: new TestProgressReporter(reportFunc));
pdbStream.Position = 0;
var metadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader();
var generatedPdbId = new BlobContentId(metadataReader.DebugMetadataHeader.Id);
}
Assert.AreEqual(totalFiles, lastFilesWritten);
}
private class TestProgressReporter : IProgress<DecompilationProgress>
{
private Action<DecompilationProgress> reportFunc;
public TestProgressReporter(Action<DecompilationProgress> reportFunc)
{
this.reportFunc = reportFunc;
}
public void Report(DecompilationProgress value)
{
reportFunc(value);
}
}
private void TestGeneratePdb([CallerMemberName] string testName = null)
{
const PdbToXmlOptions options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.ThrowOnError | PdbToXmlOptions.IncludeTokens | PdbToXmlOptions.ResolveTokens | PdbToXmlOptions.IncludeMethodSpans;

74
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 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
@ -135,15 +135,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -135,15 +135,7 @@ namespace ICSharpCode.Decompiler.Tests
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslynLatestOnlyWithNet40Options =
{
CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] roslynLatestOnlyOptions =
static readonly CompilerOptions[] roslyn4OrNewerOptions =
{
CompilerOptions.UseRoslynLatest,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
@ -261,7 +253,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -261,7 +253,7 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public async Task SwitchExpressions([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task SwitchExpressions([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
@ -275,7 +267,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -275,7 +267,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task DelegateConstruction([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
@ -320,6 +312,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -320,6 +312,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task Operators([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task Generics([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
@ -329,18 +327,17 @@ namespace ICSharpCode.Decompiler.Tests @@ -329,18 +327,17 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task Loops([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
RemoveDeadStores = (cscOptions == CompilerOptions.None),
UseExpressionBodyForCalculatedGetterOnlyProperties = false,
FileScopedNamespaces = false,
});
DecompilerSettings settings = Tester.GetSettings(cscOptions);
// legacy csc generates a dead store in debug builds
settings.RemoveDeadStores = (cscOptions == CompilerOptions.None);
settings.UseExpressionBodyForCalculatedGetterOnlyProperties = false;
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: settings);
}
[Test]
public async Task LocalFunctions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
@ -376,7 +373,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -376,7 +373,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.ReferenceUnsafe);
}
[Test]
@ -494,13 +491,13 @@ namespace ICSharpCode.Decompiler.Tests @@ -494,13 +491,13 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public async Task NativeInts([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task NativeInts([ValueSource(nameof(roslyn3OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task FileScopedNamespaces([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task FileScopedNamespaces([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings());
}
@ -512,13 +509,13 @@ namespace ICSharpCode.Decompiler.Tests @@ -512,13 +509,13 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public async Task FunctionPointers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task FunctionPointers([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task Records([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task Records([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable);
}
@ -547,6 +544,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -547,6 +544,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task RefFields([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
@ -568,12 +571,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -568,12 +571,6 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task TupleTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
{
Assert.Ignore("DefaultInterpolatedStringHandler is not yet supported!");
return;
}
await RunForLibrary(cscOptions: cscOptions);
}
@ -586,7 +583,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -586,7 +583,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
@ -610,11 +607,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -610,11 +607,6 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task CustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
{
// Test C# 11 generic attributes
cscOptions |= CompilerOptions.Preview;
}
await RunForLibrary(cscOptions: cscOptions);
}
@ -669,7 +661,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -669,7 +661,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public async Task YieldReturn([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
@ -703,9 +695,9 @@ namespace ICSharpCode.Decompiler.Tests @@ -703,9 +695,9 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public async Task StaticAbstractInterfaceMembers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task StaticAbstractInterfaceMembers([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]

6
ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2010-2013 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
@ -104,7 +104,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -104,7 +104,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
Assert.AreSame(c1, r.BestCandidate);
}
[Test, Ignore("Broken after migration to ICS.Decompiler")]
[Test]
public void NullableIntAndNullableUIntIsAmbiguous()
{
OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(ushort?)));
@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors);
}
[Test, Ignore("Broken on SRM branch???")]
[Test]
public void Lambda_DelegateAndExpressionTreeOverloadsAreAmbiguous()
{
var m1 = MakeMethod(typeof(Func<int>));

26
ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2014 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
@ -36,7 +36,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -36,7 +36,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(field2);
Console.WriteLine(field3);
Console.WriteLine(field4);
Console.WriteLine(IntToDecimal());
Console.WriteLine(UIntToDecimal());
Console.WriteLine(LongToDecimal());
Console.WriteLine(ULongToDecimal());
return 0;
}
public static decimal IntToDecimal()
{
return (decimal)int.MaxValue;
}
public static decimal UIntToDecimal()
{
return (decimal)uint.MaxValue;
}
public static decimal LongToDecimal()
{
return (decimal)long.MaxValue;
}
public static decimal ULongToDecimal()
{
return (decimal)ulong.MaxValue;
}
}
}

31
ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs

@ -36,6 +36,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -36,6 +36,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Issue1747();
CallAmbiguousOutParam();
CallWithInParam();
#if CS90
NativeIntTests(new IntPtr(1), 2);
#endif
Issue2444.M2();
Issue2741.B.Test(new Issue2741.C());
}
@ -337,6 +340,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -337,6 +340,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
#endif
#endregion
#if CS90
static void NativeIntTests(IntPtr i1, nint i2)
{
Console.WriteLine("NativeIntTests(i1):");
ObjectOrLong((object)i1);
ObjectOrLong((long)i1);
Console.WriteLine("NativeIntTests(i2):");
ObjectOrLong((object)i2);
ObjectOrLong((long)i2);
Console.WriteLine("NativeIntTests(new IntPtr):");
ObjectOrLong((object)new IntPtr(3));
ObjectOrLong((long)new IntPtr(3));
Console.WriteLine("NativeIntTests(IntPtr.Zero):");
ObjectOrLong((object)IntPtr.Zero);
ObjectOrLong((long)IntPtr.Zero);
}
static void ObjectOrLong(object o)
{
Console.WriteLine("object " + o);
}
static void ObjectOrLong(long l)
{
Console.WriteLine("long " + l);
}
#endif
#region #2444
public struct Issue2444
{

32
ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il

@ -79,7 +79,34 @@ pointless: @@ -79,7 +79,34 @@ pointless:
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
/*
ldstr "Int32OrNativeReordered(0x7fffffff, false) = {0}"
ldc.i4 0x7fffffff
ldc.i4 0
call native int Program::Int32OrNativeReordered(int32, bool)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "Int32OrNativeReordered(0x7fffffff, true) = {0}"
ldc.i4 0x7fffffff
ldc.i4 1
call native int Program::Int32OrNativeReordered(int32, bool)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "Int32OrNativeReordered(-1, false) = {0}"
ldc.i4.m1
ldc.i4 0
call native int Program::Int32OrNativeReordered(int32, bool)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "Int32OrNativeReordered(-1, true) = {0}"
ldc.i4.m1
ldc.i4 1
call native int Program::Int32OrNativeReordered(int32, bool)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "Int32OrNativeLoopStyle(0x7fffffff):"
call void [mscorlib]System.Console::WriteLine(string)
ldc.i4 0x7fffffff
@ -101,7 +128,6 @@ pointless: @@ -101,7 +128,6 @@ pointless:
call native int Program::Int32OrNativeDeadCode(int32)
box native int
call void [mscorlib]System.Console::WriteLine(string, object)
*/
ldc.i4 0x7fffffff
call void Program::RunInt32OrNativeMultiUse(int32)
@ -127,7 +153,6 @@ pointless: @@ -127,7 +153,6 @@ pointless:
ret
}
/*
.method public static native int Int32OrNativeReordered(int32 val, bool use_native)
{
// The spec is ambiguous whether the addition will be in 32-bits or native size.
@ -187,7 +212,6 @@ pointless: @@ -187,7 +212,6 @@ pointless:
conv.u
br after_if
}
*/
.method public static void RunInt32OrNativeMultiUse(int32 val)
{

2
ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/.gitignore vendored

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
*.result.il
*.dll

75
ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/InterfaceImplAttributes.il

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly InterfaceImplAttributes
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module InterfaceImplAttributes.dll
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WindowsCui
.corflags 0x00000001 // ILOnly
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit TestType
extends [mscorlib]System.Object
implements ITestInterfaceA
{
.interfaceimpl type ITestInterfaceA
.custom instance void TestAttributeA::.ctor() = (
01 00 00 00
)
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method TestType::.ctor
} // end of class TestType
.class interface public auto ansi abstract ITestInterfaceA
{
} // end of class ITestInterfaceA
.class public auto ansi beforefieldinit TestAttributeA
extends [mscorlib]System.Attribute
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2058
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
IL_0006: ret
} // end of method TestAttributeA::.ctor
} // end of class TestAttributeA

395
ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/SortMembers.expected.il

@ -0,0 +1,395 @@ @@ -0,0 +1,395 @@
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly SecurityDeclarations
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module SecurityDeclarations.dll
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WindowsCui
.corflags 0x00000001 // ILOnly
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class private auto ansi beforefieldinit SecurityDeclarations.NestedArrays
extends [mscorlib]System.Object
{
.permissionset assert = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field object TestBoxed2 = object(object[4](int32(1) int32(2) int32(3) object[3](int32(4) int32(5) int32(6))))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20d4
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method NestedArrays::.ctor
} // end of class SecurityDeclarations.NestedArrays
.class private auto ansi beforefieldinit SecurityDeclarations.SecurityAttrTest
extends [mscorlib]System.Security.Permissions.SecurityAttribute
{
// Fields
.field private valuetype SecurityDeclarations.TestEnum[] _testEnumArray
.field private int32[] _testInt32Array
.field private string[] _testStringArray
.field private class [mscorlib]System.Type[] _testTypeArray
.field public object TestBoxed
.field public object TestBoxed2
.field public object TestBoxedArray
.field public object TestBoxedString
.field public object TestBoxedType
.field public valuetype SecurityDeclarations.TestEnum TestEnumType
.field public int32 TestInt32
.field public string TestString
.field public class [mscorlib]System.Type TestType
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
valuetype [mscorlib]System.Security.Permissions.SecurityAction action
) cil managed
{
// Method begins at RVA 0x2059
// Header size: 1
// Code size: 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance void [mscorlib]System.Security.Permissions.SecurityAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction)
IL_0007: nop
IL_0008: nop
IL_0009: ret
} // end of method SecurityAttrTest::.ctor
.method public hidebysig virtual
instance class [mscorlib]System.Security.IPermission CreatePermission () cil managed
{
// Method begins at RVA 0x2064
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.NotImplementedException::.ctor()
IL_0006: throw
} // end of method SecurityAttrTest::CreatePermission
.method public hidebysig specialname
instance valuetype SecurityDeclarations.TestEnum[] get_TestEnumArray () cil managed
{
// Method begins at RVA 0x208e
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::_testEnumArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestEnumArray
.method public hidebysig specialname
instance int32[] get_TestInt32Array () cil managed
{
// Method begins at RVA 0x207d
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32[] SecurityDeclarations.SecurityAttrTest::_testInt32Array
IL_0006: ret
} // end of method SecurityAttrTest::get_TestInt32Array
.method public hidebysig specialname
instance string[] get_TestStringArray () cil managed
{
// Method begins at RVA 0x206c
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld string[] SecurityDeclarations.SecurityAttrTest::_testStringArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestStringArray
.method public hidebysig specialname
instance class [mscorlib]System.Type[] get_TestTypeArray () cil managed
{
// Method begins at RVA 0x209f
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::_testTypeArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestTypeArray
.method public hidebysig specialname
instance void set_TestEnumArray (
valuetype SecurityDeclarations.TestEnum[] 'value'
) cil managed
{
// Method begins at RVA 0x2096
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::_testEnumArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestEnumArray
.method public hidebysig specialname
instance void set_TestInt32Array (
int32[] 'value'
) cil managed
{
// Method begins at RVA 0x2085
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32[] SecurityDeclarations.SecurityAttrTest::_testInt32Array
IL_0007: ret
} // end of method SecurityAttrTest::set_TestInt32Array
.method public hidebysig specialname
instance void set_TestStringArray (
string[] 'value'
) cil managed
{
// Method begins at RVA 0x2074
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld string[] SecurityDeclarations.SecurityAttrTest::_testStringArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestStringArray
.method public hidebysig specialname
instance void set_TestTypeArray (
class [mscorlib]System.Type[] 'value'
) cil managed
{
// Method begins at RVA 0x20a7
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::_testTypeArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestTypeArray
// Properties
.property instance valuetype SecurityDeclarations.TestEnum[] TestEnumArray()
{
.get instance valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::get_TestEnumArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestEnumArray(valuetype SecurityDeclarations.TestEnum[])
}
.property instance int32[] TestInt32Array()
{
.get instance int32[] SecurityDeclarations.SecurityAttrTest::get_TestInt32Array()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestInt32Array(int32[])
}
.property instance string[] TestStringArray()
{
.get instance string[] SecurityDeclarations.SecurityAttrTest::get_TestStringArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestStringArray(string[])
}
.property instance class [mscorlib]System.Type[] TestTypeArray()
{
.get instance class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::get_TestTypeArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestTypeArray(class [mscorlib]System.Type[])
}
} // end of class SecurityDeclarations.SecurityAttrTest
.class private auto ansi beforefieldinit SecurityDeclarations.SimpleType
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method SimpleType::.ctor
} // end of class SecurityDeclarations.SimpleType
.class private auto ansi sealed SecurityDeclarations.TestEnum
extends [mscorlib]System.Enum
{
// Fields
.field public static literal valuetype SecurityDeclarations.TestEnum A = int32(0)
.field public static literal valuetype SecurityDeclarations.TestEnum B = int32(1)
.field public static literal valuetype SecurityDeclarations.TestEnum C = int32(2)
.field public specialname rtspecialname int32 value__
} // end of class SecurityDeclarations.TestEnum
.class private auto ansi beforefieldinit SecurityDeclarations.TestEnumTypes
extends [mscorlib]System.Object
{
.permissionset inheritcheck = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field enum SecurityDeclarations.TestEnum TestEnumType = int32(0)
field object TestBoxed = object(int32(1))
property enum SecurityDeclarations.TestEnum[] TestEnumArray = int32[3](0 1 2)
field object TestBoxed2 = object(object[4](int32(0) int32(1) int32(2) object[1](int32(3))))
field object TestBoxedArray = object(int32[3](0 1 2))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20c2
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestEnumTypes::.ctor
} // end of class SecurityDeclarations.TestEnumTypes
.class private auto ansi beforefieldinit SecurityDeclarations.TestInt32Types
extends [mscorlib]System.Object
{
.permissionset permitonly = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field int32 TestInt32 = int32(5)
field object TestBoxed = object(int32(10))
property int32[] TestInt32Array = int32[3](1 2 3)
field object TestBoxedArray = object(int32[3](4 5 6))
field object TestBoxed2 = object(object[3](int32(7) int32(8) int32(9)))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20cb
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestInt32Types::.ctor
} // end of class SecurityDeclarations.TestInt32Types
.class private auto ansi beforefieldinit SecurityDeclarations.TestStringTypes
extends [mscorlib]System.Object
{
.permissionset assert = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field string TestString = string('Hello World!')
field object TestBoxedString = object(string('Boxed String'))
property string[] TestStringArray = string[2]('a' 'b')
field object TestBoxedArray = object(string[2]('c' 'd'))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20b0
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestStringTypes::.ctor
} // end of class SecurityDeclarations.TestStringTypes
.class private sequential ansi sealed beforefieldinit SecurityDeclarations.TestStruct
extends [mscorlib]System.ValueType
{
.pack 0
.size 1
} // end of class SecurityDeclarations.TestStruct
.class private auto ansi beforefieldinit SecurityDeclarations.TestTypeTypes
extends [mscorlib]System.Object
{
.permissionset demand = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field type TestType = type(SecurityDeclarations.SimpleType)
field object TestBoxed = object(type(SecurityDeclarations.TestEnum))
property type[] TestTypeArray = type[2](SecurityDeclarations.TestStruct SecurityDeclarations.SimpleType)
field object TestBoxedArray = object(type[2](SecurityDeclarations.TestStringTypes SecurityDeclarations.TestTypeTypes))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20b9
// Header size: 1
// Code size: 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestTypeTypes::.ctor
} // end of class SecurityDeclarations.TestTypeTypes

381
ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/SortMembers.il

@ -0,0 +1,381 @@ @@ -0,0 +1,381 @@
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly SecurityDeclarations
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module SecurityDeclarations.dll
// MVID: {761F919A-2373-48EB-9282-9DAB26913D43}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WindowsCui
.corflags 0x00000001 // ILOnly
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class private sequential ansi sealed beforefieldinit SecurityDeclarations.TestStruct
extends [mscorlib]System.ValueType
{
.pack 0
.size 1
} // end of class SecurityDeclarations.TestStruct
.class private auto ansi beforefieldinit SecurityDeclarations.SimpleType
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method SimpleType::.ctor
} // end of class SecurityDeclarations.SimpleType
.class private auto ansi sealed SecurityDeclarations.TestEnum
extends [mscorlib]System.Enum
{
// Fields
.field public specialname rtspecialname int32 value__
.field public static literal valuetype SecurityDeclarations.TestEnum A = int32(0)
.field public static literal valuetype SecurityDeclarations.TestEnum B = int32(1)
.field public static literal valuetype SecurityDeclarations.TestEnum C = int32(2)
} // end of class SecurityDeclarations.TestEnum
.class private auto ansi beforefieldinit SecurityDeclarations.SecurityAttrTest
extends [mscorlib]System.Security.Permissions.SecurityAttribute
{
// Fields
.field private string[] _testStringArray
.field private int32[] _testInt32Array
.field private valuetype SecurityDeclarations.TestEnum[] _testEnumArray
.field private class [mscorlib]System.Type[] _testTypeArray
.field public int32 TestInt32
.field public class [mscorlib]System.Type TestType
.field public valuetype SecurityDeclarations.TestEnum TestEnumType
.field public object TestBoxed
.field public object TestBoxed2
.field public string TestString
.field public object TestBoxedString
.field public object TestBoxedArray
.field public object TestBoxedType
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
valuetype [mscorlib]System.Security.Permissions.SecurityAction action
) cil managed
{
// Method begins at RVA 0x2059
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance void [mscorlib]System.Security.Permissions.SecurityAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction)
IL_0007: nop
IL_0008: nop
IL_0009: ret
} // end of method SecurityAttrTest::.ctor
.method public hidebysig virtual
instance class [mscorlib]System.Security.IPermission CreatePermission () cil managed
{
// Method begins at RVA 0x2064
// Code size 7 (0x7)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.NotImplementedException::.ctor()
IL_0006: throw
} // end of method SecurityAttrTest::CreatePermission
.method public hidebysig specialname
instance string[] get_TestStringArray () cil managed
{
// Method begins at RVA 0x206c
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld string[] SecurityDeclarations.SecurityAttrTest::_testStringArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestStringArray
.method public hidebysig specialname
instance void set_TestStringArray (
string[] 'value'
) cil managed
{
// Method begins at RVA 0x2074
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld string[] SecurityDeclarations.SecurityAttrTest::_testStringArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestStringArray
.method public hidebysig specialname
instance int32[] get_TestInt32Array () cil managed
{
// Method begins at RVA 0x207d
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32[] SecurityDeclarations.SecurityAttrTest::_testInt32Array
IL_0006: ret
} // end of method SecurityAttrTest::get_TestInt32Array
.method public hidebysig specialname
instance void set_TestInt32Array (
int32[] 'value'
) cil managed
{
// Method begins at RVA 0x2085
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32[] SecurityDeclarations.SecurityAttrTest::_testInt32Array
IL_0007: ret
} // end of method SecurityAttrTest::set_TestInt32Array
.method public hidebysig specialname
instance valuetype SecurityDeclarations.TestEnum[] get_TestEnumArray () cil managed
{
// Method begins at RVA 0x208e
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::_testEnumArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestEnumArray
.method public hidebysig specialname
instance void set_TestEnumArray (
valuetype SecurityDeclarations.TestEnum[] 'value'
) cil managed
{
// Method begins at RVA 0x2096
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::_testEnumArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestEnumArray
.method public hidebysig specialname
instance class [mscorlib]System.Type[] get_TestTypeArray () cil managed
{
// Method begins at RVA 0x209f
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::_testTypeArray
IL_0006: ret
} // end of method SecurityAttrTest::get_TestTypeArray
.method public hidebysig specialname
instance void set_TestTypeArray (
class [mscorlib]System.Type[] 'value'
) cil managed
{
// Method begins at RVA 0x20a7
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::_testTypeArray
IL_0007: ret
} // end of method SecurityAttrTest::set_TestTypeArray
// Properties
.property instance string[] TestStringArray()
{
.get instance string[] SecurityDeclarations.SecurityAttrTest::get_TestStringArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestStringArray(string[])
}
.property instance int32[] TestInt32Array()
{
.get instance int32[] SecurityDeclarations.SecurityAttrTest::get_TestInt32Array()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestInt32Array(int32[])
}
.property instance valuetype SecurityDeclarations.TestEnum[] TestEnumArray()
{
.get instance valuetype SecurityDeclarations.TestEnum[] SecurityDeclarations.SecurityAttrTest::get_TestEnumArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestEnumArray(valuetype SecurityDeclarations.TestEnum[])
}
.property instance class [mscorlib]System.Type[] TestTypeArray()
{
.get instance class [mscorlib]System.Type[] SecurityDeclarations.SecurityAttrTest::get_TestTypeArray()
.set instance void SecurityDeclarations.SecurityAttrTest::set_TestTypeArray(class [mscorlib]System.Type[])
}
} // end of class SecurityDeclarations.SecurityAttrTest
.class private auto ansi beforefieldinit SecurityDeclarations.TestStringTypes
extends [mscorlib]System.Object
{
.permissionset assert = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field string TestString = string('Hello World!')
field object TestBoxedString = object(string('Boxed String'))
property string[] TestStringArray = string[2]('a' 'b')
field object TestBoxedArray = object(string[2]('c' 'd'))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestStringTypes::.ctor
} // end of class SecurityDeclarations.TestStringTypes
.class private auto ansi beforefieldinit SecurityDeclarations.TestTypeTypes
extends [mscorlib]System.Object
{
.permissionset demand = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field type TestType = type(SecurityDeclarations.SimpleType)
field object TestBoxed = object(type(SecurityDeclarations.TestEnum))
property type[] TestTypeArray = type[2](SecurityDeclarations.TestStruct SecurityDeclarations.SimpleType)
field object TestBoxedArray = object(type[2](SecurityDeclarations.TestStringTypes SecurityDeclarations.TestTypeTypes))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestTypeTypes::.ctor
} // end of class SecurityDeclarations.TestTypeTypes
.class private auto ansi beforefieldinit SecurityDeclarations.TestEnumTypes
extends [mscorlib]System.Object
{
.permissionset inheritcheck = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field enum SecurityDeclarations.TestEnum TestEnumType = int32(0)
field object TestBoxed = object(int32(1))
property enum SecurityDeclarations.TestEnum[] TestEnumArray = int32[3](0 1 2)
field object TestBoxed2 = object(object[4](int32(0) int32(1) int32(2) object[1](int32(3))))
field object TestBoxedArray = object(int32[3](0 1 2))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestEnumTypes::.ctor
} // end of class SecurityDeclarations.TestEnumTypes
.class private auto ansi beforefieldinit SecurityDeclarations.TestInt32Types
extends [mscorlib]System.Object
{
.permissionset permitonly = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field int32 TestInt32 = int32(5)
field object TestBoxed = object(int32(10))
property int32[] TestInt32Array = int32[3](1 2 3)
field object TestBoxedArray = object(int32[3](4 5 6))
field object TestBoxed2 = object(object[3](int32(7) int32(8) int32(9)))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method TestInt32Types::.ctor
} // end of class SecurityDeclarations.TestInt32Types
.class private auto ansi beforefieldinit SecurityDeclarations.NestedArrays
extends [mscorlib]System.Object
{
.permissionset assert = {
class 'SecurityDeclarations.SecurityAttrTest, SecurityDeclarations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' = {
field object TestBoxed2 = object(object[4](int32(1) int32(2) int32(3) object[3](int32(4) int32(5) int32(6))))
}
}
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method NestedArrays::.ctor
} // end of class SecurityDeclarations.NestedArrays

14
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
internal class EmptyBodies
{
public static void RetVoid()
{
}
public static int RetInt()
{
/*Error: Method body consists only of 'ret', but nothing is being returned. Decompiled assembly might be a reference assembly.*/;
}
public static void Nop()
{
/*Error: End of method reached without returning.*/;
}
}

45
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/EmptyBodies.il

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
#define CORE_ASSEMBLY "System.Runtime"
.assembly extern CORE_ASSEMBLY
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:0:0:0
}
.class private auto ansi beforefieldinit EmptyBodies
extends [CORE_ASSEMBLY]System.Object
{
// I cannot test a truly empty body because the assembler will automatically add a ret instruction.
.method public hidebysig static void RetVoid () cil managed
{
.maxstack 8
ret
}
.method public hidebysig static int32 RetInt () cil managed
{
.maxstack 8
ret
}
.method public hidebysig static void Nop () cil managed
{
.maxstack 8
nop
}
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x206e
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Example::.ctor
} // end of class EmptyBodies

39
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/GuessAccessors.cs

@ -15,9 +15,8 @@ namespace ClassLibrary1 @@ -15,9 +15,8 @@ namespace ClassLibrary1
//IL_0007: Expected O, but got Unknown
UnknownClass val = new UnknownClass();
int? unknownProperty = val.UnknownProperty;
int? num = unknownProperty.GetValueOrDefault();
val.UnknownProperty = num;
int? num2 = num;
int? num2 = (val.UnknownProperty = unknownProperty.GetValueOrDefault());
int? num3 = num2;
List<object> list = new List<object> {
val[unknownProperty.Value] ?? "",
val.NotProperty,
@ -51,10 +50,9 @@ namespace ClassLibrary1 @@ -51,10 +50,9 @@ namespace ClassLibrary1
//IL_00e1: Expected O, but got Unknown
//IL_00e1: Expected O, but got Unknown
UnknownGenericClass<UnknownEventArgs> val = new UnknownGenericClass<UnknownEventArgs>();
UnknownEventArgs unknownProperty = val.UnknownProperty;
val.UnknownProperty = unknownProperty;
UnknownEventArgs val2 = (val.UnknownProperty = val.UnknownProperty);
List<object> list = new List<object> {
val[((object)unknownProperty).GetHashCode()] ?? "",
val[((object)val2).GetHashCode()] ?? "",
val.NotProperty,
val.get_NotPropertyWithGeneric<string>(42),
val[42],
@ -63,18 +61,17 @@ namespace ClassLibrary1 @@ -63,18 +61,17 @@ namespace ClassLibrary1
};
val.OnEvent += Instance_OnEvent;
val.OnEvent -= Instance_OnEvent;
UnknownEventArgs val2 = val[(UnknownEventArgs)null];
val[new UnknownEventArgs()] = val2;
UnknownEventArgs val3 = val[new UnknownEventArgs(), new UnknownEventArgs()];
val[new UnknownEventArgs(), new UnknownEventArgs()] = val3;
UnknownEventArgs val3 = val[(UnknownEventArgs)null];
val[new UnknownEventArgs()] = val3;
UnknownEventArgs val4 = val[new UnknownEventArgs(), new UnknownEventArgs()];
val[new UnknownEventArgs(), new UnknownEventArgs()] = val4;
}
public void MethodUnknownStatic()
{
int? unknownProperty = UnknownStaticClass.UnknownProperty;
UnknownStaticClass.UnknownProperty = unknownProperty;
int? num = (UnknownStaticClass.UnknownProperty = UnknownStaticClass.UnknownProperty);
List<object> list = new List<object> {
UnknownStaticClass[unknownProperty.Value] ?? "",
UnknownStaticClass[num.Value] ?? "",
UnknownStaticClass.NotProperty,
UnknownStaticClass.get_NotPropertyWithGeneric<string>(42),
UnknownStaticClass[42],
@ -87,10 +84,9 @@ namespace ClassLibrary1 @@ -87,10 +84,9 @@ namespace ClassLibrary1
public void MethodUnknownStaticGeneric()
{
string unknownProperty = UnknownStaticGenericClass<string>.UnknownProperty;
UnknownStaticGenericClass<string>.UnknownProperty = unknownProperty;
string text = (UnknownStaticGenericClass<string>.UnknownProperty = UnknownStaticGenericClass<string>.UnknownProperty);
List<object> list = new List<object> {
UnknownStaticGenericClass<string>[unknownProperty.Length] ?? "",
UnknownStaticGenericClass<string>[text.Length] ?? "",
UnknownStaticGenericClass<string>.NotProperty,
UnknownStaticGenericClass<string>.get_NotPropertyWithGeneric<string>(42),
UnknownStaticGenericClass<string>[42],
@ -101,6 +97,15 @@ namespace ClassLibrary1 @@ -101,6 +97,15 @@ namespace ClassLibrary1
UnknownStaticGenericClass<string>.OnEvent -= Instance_OnEvent;
}
public void MethodUnknownIndexerInitializer()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
new UnknownClass {
["a"] = 1,
["b"] = 2
};
}
private void Instance_OnEvent(object sender, EventArgs e)
{
throw new NotImplementedException();
@ -121,4 +126,4 @@ namespace ClassLibrary1 @@ -121,4 +126,4 @@ namespace ClassLibrary1
throw new NotImplementedException();
}
}
}
}

22
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/GuessAccessors.il

@ -378,6 +378,28 @@ @@ -378,6 +378,28 @@
IL_0098: ret
} // end of method UnknownClassTest::MethodUnknownStaticGeneric
.method public hidebysig
instance void MethodUnknownIndexerInitializer () cil managed
{
// Method begins at RVA 0x2050
// Code size 32 (0x20)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [UnknownAssembly]UnknownNamespace.UnknownClass::.ctor()
IL_0006: dup
IL_0007: ldstr "a"
IL_000c: ldc.i4.1
IL_000d: callvirt instance void [UnknownAssembly]UnknownNamespace.UnknownClass::set_Item(string, int32)
IL_0012: nop
IL_0013: ldstr "b"
IL_0018: ldc.i4.2
IL_0019: callvirt instance void [UnknownAssembly]UnknownNamespace.UnknownClass::set_Item(string, int32)
IL_001e: nop
IL_001f: ret
} // end of method C::MethodUnknownIndexerInitializer
.method /* 100663301 */ private hidebysig
instance void Instance_OnEvent (
object sender,

4
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs

@ -2,16 +2,16 @@ using System; @@ -2,16 +2,16 @@ using System;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: CLSCompliant(false)]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyInformationalVersion("4.0.0.0")]
[assembly: AssemblyTitle("System.Runtime.CompilerServices.Unsafe")]
[assembly: AssemblyDescription("System.Runtime.CompilerServices.Unsafe")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: CLSCompliant(false)]
internal sealed class ExtraUnsafeTests
{

26
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il

@ -493,9 +493,35 @@ @@ -493,9 +493,35 @@
#ifdef netcoreapp
#else
.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute
extends [CORE_ASSEMBLY]System.Attribute
{
.custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
01 00 00 00
)
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [CORE_ASSEMBLY]System.Attribute::.ctor()
IL_0006: ret
} // end of method EmbeddedAttribute::.ctor
} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute
.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsReadOnlyAttribute
extends [CORE_ASSEMBLY]System.Attribute
{
.custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
01 00 00 00
)
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{

4
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/CustomPdbId.xml

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\CustomPdbId.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen;
public class HelloWorld
public class CustomPdbId
{
public static void Main(string[] args)
{

44
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ProgressReporting.xml

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\ProgressReporting.cs" language="C#" checksumAlgorithm="SHA256">
<![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen;
public class ProgressReporting
{
public static void Main(string[] args)
{
Console.ReadKey();
Console.WriteLine("Hello World!");
Console.ReadKey();
}
}
public class Class1
{
public static void Test()
{
Console.WriteLine("Class1");
}
}
public class Class2
{
public static void Test()
{
Console.WriteLine("Class2");
}
}
public class Class3
{
public static void Test()
{
Console.WriteLine("Class3");
}
}
]]></file>
</files>
</symbols>

17
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs

@ -4,6 +4,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -4,6 +4,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class AutoProperties
{
#if CS110
public required int RequiredField;
#endif
public int A { get; } = 1;
public int B { get; set; } = 2;
@ -22,9 +25,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -22,9 +25,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public int issue1319 { get; }
#if CS110
public required int RequiredProperty { get; set; }
#endif
public AutoProperties(int issue1319)
{
this.issue1319 = issue1319;
#if CS110
RequiredProperty = 42;
RequiredField = 42;
#endif
}
}
#if !NET70
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
#endif
}

1117
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

File diff suppressed because it is too large Load Diff

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs

@ -1,10 +1,25 @@ @@ -1,10 +1,25 @@
using System;
#if !(CS110 && NET70)
using System;
#endif
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class ConstantsTests
{
#if CS90
public nint? NullableNInt()
{
return null;
}
public nuint? NullableNUInt()
{
return null;
}
#endif
#if !(CS110 && NET70)
public IntPtr? NullableIntPtr()
{
return null;
@ -14,6 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -14,6 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return null;
}
#endif
public ulong Issue1308(ulong u = 8uL)
{

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributes.cs

@ -163,8 +163,13 @@ namespace CustomAttributes @@ -163,8 +163,13 @@ namespace CustomAttributes
public static void UseGenericAttribute()
{
}
// TODO: add test for generic attributes with arguments of type T
// This is blocked by https://github.com/dotnet/runtime/issues/58073
[Generic<int>(42)]
[Generic<string>("Hi")]
[Generic<object>("Hi")]
[Generic<object>((short)42)]
public static void UseGenericAttributeWithArg()
{
}
#endif
}
}

44
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -601,6 +601,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction @@ -601,6 +601,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
}
}
internal class Issue2791
{
public void M()
{
Run(delegate (object o) {
try
{
List<int> list = o as List<int>;
Action action = delegate {
list.Select((int x) => x * 2);
};
#if OPT && ROSLYN
Action obj = delegate {
#else
Action action2 = delegate {
#endif
list.Select((int x) => x * 2);
};
Console.WriteLine();
action();
Console.WriteLine();
#if OPT && ROSLYN
obj();
#else
action2();
#endif
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
}, null);
}
private void Run(ParameterizedThreadStart del, object x)
{
del(x);
}
}
[AttributeUsage(AttributeTargets.All)]
internal class MyAttribute : Attribute
{

32
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs

@ -42,7 +42,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -42,7 +42,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public interface I
{
}
private static dynamic field;
private static volatile dynamic volatileField;
private static object objectField;
public dynamic Property { get; set; }
@ -431,10 +436,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -431,10 +436,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return true.Equals(a);
}
#if CS110 && NET70
private static nint NewIntPtr(dynamic a)
{
return new nint(a);
}
#else
private static IntPtr NewIntPtr(dynamic a)
{
return new IntPtr(a);
}
#endif
private static dynamic GetDynamic(int i)
{
@ -492,6 +504,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -492,6 +504,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return (int)(dynamic)o;
}
private static dynamic GetI()
{
return null;
}
public I Test()
{
return GetI();
}
public I Test1()
{
return (I)GetI();
}
public I Test2()
{
return (I)(object)GetI();
}
#if CS72
public void RefParams(ref object a, ref dynamic b, ref dynamic c)
{

14
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FunctionPointers.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
using System;
#if !(CS110 && NET70)
using System;
#endif
using System.Text;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
@ -17,10 +19,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -17,10 +19,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return &Overloaded;
}
#if !(CS110 && NET70)
public unsafe IntPtr GetAddressAsIntPtr()
{
return (IntPtr)(delegate*<void>)(&Overloaded);
}
#endif
public unsafe nint GetAddressAsNInt()
{
return (nint)(delegate*<void>)(&Overloaded);
}
public unsafe void* GetAddressAsVoidPtr()
{
@ -93,6 +102,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -93,6 +102,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
internal class FunctionPointersWithNativeIntegerTypes
{
public unsafe delegate*<nint, nint, nint> F1;
#if !(CS110 && NET70)
public unsafe delegate*<IntPtr, IntPtr, nint> F2;
public unsafe delegate*<nint, IntPtr, IntPtr> F3;
public unsafe delegate*<IntPtr, nint, IntPtr> F4;
@ -100,6 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -100,6 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe delegate*<nint, delegate*<IntPtr, IntPtr, IntPtr>> F6;
public unsafe delegate*<delegate*<IntPtr, IntPtr, nint>, IntPtr> F7;
public unsafe delegate*<IntPtr, delegate*<IntPtr, nint, IntPtr>> F8;
public unsafe delegate*<IntPtr, delegate*<IntPtr, IntPtr, IntPtr>> F9;
#endif
}
internal class FunctionPointersWithRefParams

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs

@ -382,6 +382,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests @@ -382,6 +382,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests
public static ReadOnlySpan<byte> StaticData3 => new byte[3] { 1, 2, 3 };
public static Span<byte> StaticData3Span => new byte[3] { 1, 2, 3 };
#endif
#if CS110 && !NET40
public static ReadOnlySpan<byte> UTF8Literal => "Hello, world!"u8;
#endif
#endregion

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -844,10 +844,10 @@ namespace LocalFunctions @@ -844,10 +844,10 @@ namespace LocalFunctions
#if CS90
public void Issue2196()
{
EnumWindows(IntPtr.Zero, IntPtr.Zero);
EnumWindows(0L, 0L);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EnumWindows")]
static extern int EnumWindows(IntPtr hWnd, IntPtr lParam);
static extern int EnumWindows(long hWnd, long lParam);
}
#endif
}

41
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs

@ -26,23 +26,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -26,23 +26,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private const nint nint_const = 42;
private const nuint nuint_const = 99u;
#if CS110 && NET70
// C#11 on .NET7 no longer uses NativeIntegerAttribute,
// instead nint+IntPtr are considered to be the same type.
private nint intptr;
private nuint uintptr;
#else
private IntPtr intptr;
private UIntPtr uintptr;
#endif
private nint i;
private nuint u;
private int i32;
private uint u32;
private long i64;
private ulong u64;
#if !(CS110 && NET70)
private (IntPtr, nint, UIntPtr, nuint) tuple_field;
private (object, int, IntPtr, nint, UIntPtr, nuint) tuple_field2;
private Dictionary<nint, IntPtr> dict1;
private Dictionary<IntPtr, nint> dict2;
private Dictionary<IntPtr?, nint?> dict3;
private Dictionary<IntPtr, nint[]> dict4;
#endif
private Dictionary<nuint, nint[]> dict5;
public void Convert()
{
i = (nint)u;
u = (nuint)i;
#if !(CS110 && NET70)
intptr = i;
intptr = (nint)u;
intptr = (nint)(nuint)uintptr;
@ -58,15 +71,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -58,15 +71,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
u = (nuint)i;
u = uintptr;
u = (nuint)(nint)intptr;
#endif
}
public void Convert2()
{
i32 = (int)i;
i = i32;
#if !(CS110 && NET70)
intptr = (IntPtr)i32;
i64 = (long)intptr;
#endif
i64 = i;
i = (nint)i64;
@ -79,7 +95,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -79,7 +95,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Arithmetic()
{
#if !(CS110 && NET70)
Console.WriteLine((nint)intptr * 2);
#endif
Console.WriteLine(i * 2);
Console.WriteLine(i + (nint)u);
@ -155,6 +173,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -155,6 +173,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
GetInstance(3).u *= 2u;
}
#if !(CS110 && NET70)
GetInstance(4).intptr += (nint)i32;
checked
{
@ -164,10 +183,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -164,10 +183,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
// multiplication results in compiler-error without the cast
GetInstance(6).intptr *= (nint)2;
#endif
GetInstance(7).i <<= i32;
GetInstance(7).i += i32;
GetInstance(8).i <<= i32;
}
#if !(CS110 && NET70)
public void LocalTypeFromStore()
{
nint num = 42;
@ -188,10 +210,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -188,10 +210,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
intptr = num3;
intptr = intPtr;
}
#endif
public void LocalTypeFromUse()
{
#if CS110 && NET70
nint num = intptr;
nint num2 = intptr;
Console.WriteLine();
intptr = num;
i = num2 + 1;
#else
IntPtr intPtr = intptr;
nint num = intptr;
@ -199,6 +230,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -199,6 +230,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
intptr = intPtr;
i = num + 1;
#endif
}
public nint NegateUnsigned(nuint x)
@ -206,6 +238,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -206,6 +238,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return (nint)(0 - x);
}
public bool CompareToMinus3(nuint x)
{
return x == unchecked((nuint)(-3));
}
public nint SignedNotFittingIn32Bits()
{
// Explicit `unchecked` is necessary when casting oversized constant to nint

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs

@ -111,4 +111,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -111,4 +111,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private Entry[]? _entries;
private IEqualityComparer<TKey>? _comparer;
}
public class T05_NullableUnconstrainedGeneric
{
public static TValue? Default<TValue>()
{
return default(TValue);
}
public static void CallDefault()
{
#if OPT
string? format = Default<string>();
#else
// With optimizations it's a stack slot, so ILSpy picks a nullable type.
// Without optimizations it's a local, so the nullability is missing.
string format = Default<string>();
#endif
int num = Default<int>();
#if CS110 && NET70
nint num2 = Default<nint>();
#else
int num2 = Default<int>();
#endif
(object, string) tuple = Default<(object, string)>();
Console.WriteLine("No inlining");
Console.WriteLine(format, num, num2, tuple);
}
}
}

225
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Operators.cs

@ -0,0 +1,225 @@ @@ -0,0 +1,225 @@
// Copyright (c) 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
// 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;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class AllOperators
{
public static AllOperators operator +(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator -(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator *(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator /(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator %(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator &(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator |(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator ^(AllOperators a, AllOperators b)
{
return null;
}
public static AllOperators operator <<(AllOperators a, int b)
{
return null;
}
public static AllOperators operator >>(AllOperators a, int b)
{
return null;
}
#if CS110
public static AllOperators operator >>>(AllOperators a, int b)
{
return null;
}
#endif
public static AllOperators operator ~(AllOperators a)
{
return null;
}
public static AllOperators operator !(AllOperators a)
{
return null;
}
public static AllOperators operator -(AllOperators a)
{
return null;
}
public static AllOperators operator +(AllOperators a)
{
return null;
}
public static AllOperators operator ++(AllOperators a)
{
return null;
}
public static AllOperators operator --(AllOperators a)
{
return null;
}
public static bool operator true(AllOperators a)
{
return false;
}
public static bool operator false(AllOperators a)
{
return false;
}
public static bool operator ==(AllOperators a, AllOperators b)
{
return false;
}
public static bool operator !=(AllOperators a, AllOperators b)
{
return false;
}
public static bool operator <(AllOperators a, AllOperators b)
{
return false;
}
public static bool operator >(AllOperators a, AllOperators b)
{
return false;
}
public static bool operator <=(AllOperators a, AllOperators b)
{
return false;
}
public static bool operator >=(AllOperators a, AllOperators b)
{
return false;
}
public static implicit operator AllOperators(int a)
{
return null;
}
public static explicit operator int(AllOperators a)
{
return 0;
}
}
public class UseAllOperators
{
private AllOperators a = new AllOperators();
private AllOperators b = new AllOperators();
private AllOperators c;
public void Test()
{
c = a + b;
c = a - b;
c = a * b;
c = a / b;
c = a % b;
c = a & b;
c = a | b;
c = a ^ b;
c = a << 5;
c = a >> 5;
#if CS110
c = a >>> 5;
#endif
c = ~a;
c = !a;
c = -a;
c = +a;
c = ++a;
c = --a;
if (a)
{
Console.WriteLine("a");
}
if (!a)
{
Console.WriteLine("!a");
}
if (a == b)
{
Console.WriteLine("a == b");
}
if (a != b)
{
Console.WriteLine("a != b");
}
if (a < b)
{
Console.WriteLine("a < b");
}
if (a > b)
{
Console.WriteLine("a > b");
}
if (a <= b)
{
Console.WriteLine("a <= b");
}
if (a >= b)
{
Console.WriteLine("a >= b");
}
int num = (int)a;
a = num;
}
}
}

58
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
@ -225,5 +226,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -225,5 +226,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
#endif
public static void Issue2920a(int x)
{
}
public static void Issue2920b([DefaultParameterValue(3)] int x)
{
}
public static void Issue2920c(ref int x)
{
}
public static void Issue2920d([DefaultParameterValue(3)] ref int x)
{
}
public static void Issue2920e(out int x)
{
x = 0;
}
public static void Issue2920f([DefaultParameterValue(3)] out int x)
{
x = 0;
}
#if CS70
public static void Issue2920g(in int x)
{
}
public static void Issue2920h([DefaultParameterValue(3)] in int x)
{
}
#endif
public static void Issue2920i([Optional] int x)
{
}
public static void Issue2920j(int x = 3)
{
}
public static void Issue2920k([Optional] ref int x)
{
}
public static void Issue2920l([Optional][DefaultParameterValue(3)] ref int x)
{
}
public static void Issue2920m([Optional] out int x)
{
x = 0;
}
public static void Issue2920n([Optional][DefaultParameterValue(3)] out int x)
{
x = 0;
}
#if CS70
public static void Issue2920o([Optional] in int x)
{
}
public static void Issue2920p(in int x = 3)
{
}
#endif
}
}

29
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs

@ -43,5 +43,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -43,5 +43,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
return null;
}
private bool TryGet<T>(out T result)
{
result = default(T);
return true;
}
public void M3()
{
TryGet<Dictionary<int, (int, string)>>(out Dictionary<int, (int A, string B)> data);
Test();
int Test()
{
return data[0].A;
}
}
public void GetObject(out object obj)
{
obj = null;
}
public void M4()
{
GetObject(out dynamic obj);
obj.Method();
}
}
}

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs

@ -89,9 +89,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -89,9 +89,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
#if CS110 && NET70
[DllImport("ws2_32.dll", SetLastError = true)]
internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp);
internal static extern nint ioctlsocket([In] nint socketHandle, [In] int cmd, [In][Out] ref int argp);
#else
[DllImport("ws2_32.dll", SetLastError = true)]
internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp);
#endif
public void CallMethodWithInOutParameter()
{
int argp = 0;

32
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
using System;
#if CS100
using System.Runtime.InteropServices;
#endif
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
@ -127,6 +129,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -127,6 +129,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
#if CS100
internal class RecordStructs
{
public record struct Base(string A);
@ -227,10 +231,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -227,10 +231,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
}
#endif
#if CS110
public record struct WithRequiredMembers
{
public int A { get; set; }
public required double B { get; set; }
public object C;
public required dynamic D;
}
#endif
}
#if !NET60
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public CompilerFeatureRequiredAttribute(string featureName)
{
}
}
internal class IsExternalInit
{
}
#endif
#if !NET70
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
#endif
#if !NET60
}
#endif

15
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
@ -566,5 +567,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -566,5 +567,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
}
private static string ShouldNotDuplicateReturnStatementIntoTry(IDictionary<int, string> dict)
{
string value;
lock (dict)
{
if (!dict.TryGetValue(1, out value))
{
value = "test";
dict.Add(1, value);
}
}
return value;
}
}
}

87
ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefFields.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class LifetimeTests
{
private static int staticField;
public Span<int> CreateWithoutCapture(scoped ref int value)
{
// Okay: value is not captured
return new Span<int>(ref staticField);
}
public Span<int> CreateAndCapture(ref int value)
{
// Okay: value Rule 3 specifies that the safe-to-escape be limited to the ref-safe-to-escape
// of the ref argument. That is the *calling method* for value hence this is not allowed.
return new Span<int>(ref value);
}
public Span<int> ScopedRefSpan(scoped ref Span<int> span)
{
return span;
}
public Span<int> ScopedSpan(scoped Span<int> span)
{
return default(Span<int>);
}
public void OutSpan(out Span<int> span)
{
span = default(Span<int>);
}
public void Calls()
{
int value = 0;
Span<int> span = CreateWithoutCapture(ref value);
//span = CreateAndCapture(ref value); -- would need scoped local, not yet implemented
span = ScopedRefSpan(ref span);
span = ScopedSpan(span);
OutSpan(out span);
}
}
internal ref struct RefFields
{
public ref int Field0;
public ref readonly int Field1;
public readonly ref int Field2;
public readonly ref readonly int Field3;
public int PropertyAccessingRefFieldByValue {
get {
return Field0;
}
set {
Field0 = value;
}
}
public ref int PropertyReturningRefFieldByReference => ref Field0;
public void Uses(int[] array)
{
Field1 = ref array[0];
Field2 = array[0];
}
public void ReadonlyLocal()
{
ref readonly int field = ref Field1;
Console.WriteLine("No inlining");
field.ToString();
}
public RefFields(ref int v)
{
Field0 = ref v;
Field1 = ref v;
Field2 = ref v;
Field3 = ref v;
}
}
}

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/StaticAbstractInterfaceMembers.cs

@ -4,11 +4,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM @@ -4,11 +4,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM
{
public interface I
{
abstract static int Capacity { get; }
abstract static int Count { get; set; }
abstract static int SetterOnly { set; }
abstract static event EventHandler E;
abstract static I CreateI();
static abstract int Capacity { get; }
static abstract int Count { get; set; }
static abstract int SetterOnly { set; }
static abstract event EventHandler E;
static abstract I CreateI();
}
public class X : I
@ -66,4 +66,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM @@ -66,4 +66,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM
throw new NotImplementedException();
}
}
internal class ZOperatorTest
{
public interface IGetNext<T> where T : IGetNext<T>
{
static abstract T operator ++(T other);
}
public struct WrappedInteger : IGetNext<WrappedInteger>
{
public int Value;
public static WrappedInteger operator ++(WrappedInteger other)
{
WrappedInteger result = other;
result.Value++;
return result;
}
}
public void GenericUse<T>(T t) where T : IGetNext<T>
{
++t;
}
}
}

26
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Structs.cs

@ -51,4 +51,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -51,4 +51,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
#endif
}
#if CS110
public struct StructWithRequiredMembers
{
public required string FirstName;
public required string LastName { get; set; }
}
#endif
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
internal sealed class CompilerFeatureRequiredAttribute : Attribute
{
public CompilerFeatureRequiredAttribute(string featureName)
{
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal sealed class RequiredMemberAttribute : Attribute
{
}
}

30
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -106,9 +106,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -106,9 +106,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public uint RShiftByteWithZeroExtension(byte num)
{
// zero extend -> cast to unsigned -> unsigned shift
return (uint)num >> 8;
}
public int RShiftByteWithZeroExtensionReturnAsSigned(byte num)
{
#if CS110
// zero extend -> unsigned shift
return num >>> 8;
#else
// zero extend -> cast to unsigned -> unsigned shift -> cast to signed
return (int)((uint)num >> 8);
#endif
}
public int RShiftByteAsSByte(byte num)
{
return (sbyte)num >> 8;
@ -121,9 +133,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -121,9 +133,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public uint RShiftSByteWithZeroExtension(sbyte num)
{
return (uint)num >> 8;
return (uint)((byte)num >> 4);
}
public uint RShiftSByteWithSignExtension(sbyte num)
{
// sign extend -> cast to unsigned -> unsigned shift
return (uint)num >> 4;
}
public int RShiftSByteWithSignExtensionReturnAsSigned(sbyte num)
{
#if CS110
// sign extend -> unsigned shift
return num >>> 4;
#else
// sign extend -> cast to unsigned -> unsigned shift -> cast to signed
return (int)((uint)num >> 4);
#endif
}
public int RShiftSByteAsByte(sbyte num)
{
return (byte)num >> 8;

61
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -17,10 +17,58 @@ @@ -17,10 +17,58 @@
// DEALINGS IN THE SOFTWARE.
using System;
#if !NET40 && ROSLYN
using System.Runtime.CompilerServices;
#endif
using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class SizeofTest
{
private struct StructWithStaticField
{
public static object StaticObj;
#if CS110 && NET70
public nint A;
#else
public IntPtr A;
#endif
}
private struct UnmanagedStruct
{
public StructWithStaticField Value;
}
private struct ManagedStruct
{
public object Obj;
}
#if CS73
private unsafe int GenericMethod<T>() where T : unmanaged
{
return sizeof(T);
}
#endif
private unsafe void Test(out int s1, out int s2, out int s3)
{
s1 = 0;
s2 = 0;
s3 = 0;
#if CS73
GenericMethod<UnmanagedStruct>();
#endif
s1 = sizeof(UnmanagedStruct);
#if !NET40 && ROSLYN
s2 = Unsafe.SizeOf<UnmanagedStruct>();
s3 = Unsafe.SizeOf<ManagedStruct>();
#endif
}
}
public class UnsafeCode
{
public struct SimpleStruct
@ -561,6 +609,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -561,6 +609,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return value.Integers[(int)s];
}
#if CS90
private unsafe static void* CastNIntToVoidPtr(nint intptr)
{
return (void*)intptr;
}
private unsafe static void* CastNIntToVoidPtr(nuint intptr)
{
return (void*)intptr;
}
#endif
#if !(CS110 && NET70)
private unsafe static void* CastToVoidPtr(IntPtr intptr)
{
return (void*)intptr;
@ -570,6 +630,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -570,6 +630,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return (void*)intptr;
}
#endif
private unsafe static void* CastToVoidPtr(int* intptr)
{

13
ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 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
@ -101,24 +101,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -101,24 +101,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
yield return 2;
}
#if TODO
// TODO: adjust lock-pattern for this case
public static IEnumerable<int> YieldReturnInLock1(object o)
{
lock (o) {
lock (o)
{
yield return 1;
}
}
public static IEnumerable<int> YieldReturnInLock2(object o)
{
lock (o) {
lock (o)
{
yield return 1;
o = null;
yield return 2;
}
}
#endif
public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle)
{
@ -450,4 +449,4 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -450,4 +449,4 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
}
}
}

4
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/.gitignore vendored

@ -1 +1,3 @@ @@ -1 +1,3 @@
*.dll
/*.dll
/*.exe
/*.pdb

262
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs

@ -1,45 +1,255 @@ @@ -1,45 +1,255 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace EquivalentCSharpConsoleApp
using Microsoft.VisualBasic.CompilerServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.VBPretty
{
static class Program
public class Async
{
public static void Main(string[] args)
private int memberField;
private static bool True()
{
return true;
}
public async void SimpleVoidMethod()
{
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
}
public async void VoidMethodWithoutAwait()
{
Console.WriteLine("No Await");
}
public async void EmptyVoidMethod()
{
}
public async void AwaitYield()
{
await Task.Yield();
}
public async void AwaitDefaultYieldAwaitable()
{
#if LEGACY_VBC || (OPTIMIZE && !ROSLYN4)
YieldAwaitable yieldAwaitable = default(YieldAwaitable);
YieldAwaitable yieldAwaitable2 = yieldAwaitable;
await yieldAwaitable2;
#else
await default(YieldAwaitable);
#endif
}
public async void AwaitDefaultHopToThreadPool()
{
#if LEGACY_VBC || (OPTIMIZE && !ROSLYN4)
HopToThreadPoolAwaitable hopToThreadPoolAwaitable = default(HopToThreadPoolAwaitable);
HopToThreadPoolAwaitable hopToThreadPoolAwaitable2 = hopToThreadPoolAwaitable;
await hopToThreadPoolAwaitable2;
#else
await default(HopToThreadPoolAwaitable);
#endif
}
public async Task SimpleVoidTaskMethod()
{
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
}
public async Task TaskMethodWithoutAwait()
{
Console.WriteLine("No Await");
}
public async Task CapturingThis()
{
await Task.Delay(memberField);
}
public async Task CapturingThisWithoutAwait()
{
Console.WriteLine(memberField);
}
public async Task<bool> SimpleBoolTaskMethod()
{
var task = new Task(ProcessDataAsync);
task.Start();
task.Wait();
Console.ReadLine();
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
return true;
}
public async static void ProcessDataAsync()
public async void TwoAwaitsWithDifferentAwaiterTypes()
{
Task<int> task = HandleFileAsync("C:\\enable1.txt");
Console.WriteLine("Please wait, processing");
int result = await task;
Console.WriteLine("Count: " + result.ToString());
Console.WriteLine("Before");
if (await SimpleBoolTaskMethod())
{
await Task.Delay(TimeSpan.FromSeconds(1.0));
}
Console.WriteLine("After");
}
public async void AwaitInLoopCondition()
{
while (await SimpleBoolTaskMethod())
{
Console.WriteLine("Body");
}
}
public async static Task<int> HandleFileAsync(string file)
public async Task Issue2366a()
{
Console.WriteLine("HandleFile enter");
int count = 0;
using (StreamReader reader = new StreamReader(file))
while (true)
{
string value = await reader.ReadToEndAsync();
count += value.Length;
for (var i = 0; i <= 10000; i += 1)
try
{
var x = value.GetHashCode();
if (x == 0)
count -= 1;
await Task.CompletedTask;
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
ProjectData.ClearProjectError();
}
}
}
public static async Task<int> GetIntegerSumAsync(IEnumerable<int> items)
{
await Task.Delay(100);
int num = 0;
foreach (int item in items)
{
num = checked(num + item);
}
return num;
}
Console.WriteLine("HandleFile exit");
return count;
public async Task AsyncCatch(bool b, Task<int> task1, Task<int> task2)
{
try
{
Console.WriteLine("Start try");
await task1;
Console.WriteLine("End try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("No await");
ProjectData.ClearProjectError();
}
}
public async Task AsyncCatchThrow(bool b, Task<int> task1, Task<int> task2)
{
try
{
Console.WriteLine("Start try");
await task1;
Console.WriteLine("End try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("No await");
throw;
}
}
public async Task AsyncFinally(bool b, Task<int> task1, Task<int> task2)
{
try
{
Console.WriteLine("Start try");
await task1;
Console.WriteLine("End try");
}
finally
{
Console.WriteLine("No await");
}
}
public static async Task AlwaysThrow()
{
throw new Exception();
}
public static async Task InfiniteLoop()
{
while (true)
{
}
}
public static async Task InfiniteLoopWithAwait()
{
while (true)
{
await Task.Delay(10);
}
}
public async Task AsyncWithLocalVar()
{
object objectValue = RuntimeHelpers.GetObjectValue(new object());
await UseObj(RuntimeHelpers.GetObjectValue(objectValue));
await UseObj(RuntimeHelpers.GetObjectValue(objectValue));
}
public static async Task UseObj(object a)
{
}
}
public struct AsyncInStruct
{
private int i;
public async Task<int> Test(AsyncInStruct xx)
{
checked
{
xx.i++;
i++;
await Task.Yield();
return i + xx.i;
}
}
}
public struct HopToThreadPoolAwaitable : INotifyCompletion
{
public bool IsCompleted { get; set; }
public HopToThreadPoolAwaitable GetAwaiter()
{
return this;
}
public void OnCompleted(Action continuation)
{
Task.Run(continuation);
}
void INotifyCompletion.OnCompleted(Action continuation)
{
//ILSpy generated this explicit interface implementation from .override directive in OnCompleted
this.OnCompleted(continuation);
}
public void GetResult()
{
}
}
}
}

226
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.vb

@ -1,47 +1,181 @@ @@ -1,47 +1,181 @@
Imports System
Imports System.IO
Module Program
' Sample taken verbatim from https://www.dotnetperls.com/async-vbnet
Sub Main(args As String())
Dim task = New Task(AddressOf ProcessDataAsync)
' Start and wait for task to end.
task.Start()
task.Wait()
Console.ReadLine()
End Sub
Async Sub ProcessDataAsync()
' Create a task Of Integer.
' ... Use HandleFileAsync method with a large file.
Dim task As Task(Of Integer) = HandleFileAsync("C:\enable1.txt")
' This statement runs while HandleFileAsync executes.
Console.WriteLine("Please wait, processing")
' Use await to wait for task to complete.
Dim result As Integer = Await task
Console.WriteLine("Count: " + result.ToString())
End Sub
Async Function HandleFileAsync(ByVal file As String) As Task(Of Integer)
Console.WriteLine("HandleFile enter")
' Open the file.
Dim count As Integer = 0
Using reader As StreamReader = New StreamReader(file)
Dim value As String = Await reader.ReadToEndAsync()
count += value.Length
' Do a slow computation on the file.
For i = 0 To 10000 Step 1
Dim x = value.GetHashCode()
If x = 0 Then
count -= 1
End If
Next
End Using
Console.WriteLine("HandleFile exit")
Return count
End Function
End Module
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports System.Runtime.CompilerServices
Namespace ICSharpCode.Decompiler.Tests.TestCases.VBPretty
Public Class Async
Private memberField As Integer
Private Shared Function [True]() As Boolean
Return True
End Function
Public Async Sub SimpleVoidMethod()
Console.WriteLine("Before")
Await Task.Delay(TimeSpan.FromSeconds(1.0))
Console.WriteLine("After")
End Sub
Public Async Sub VoidMethodWithoutAwait()
Console.WriteLine("No Await")
End Sub
Public Async Sub EmptyVoidMethod()
End Sub
Public Async Sub AwaitYield()
Await Task.Yield()
End Sub
Public Async Sub AwaitDefaultYieldAwaitable()
Await CType(Nothing, YieldAwaitable)
End Sub
Public Async Sub AwaitDefaultHopToThreadPool()
' unlike YieldAwaitable which implements ICriticalNotifyCompletion,
' the HopToThreadPoolAwaitable struct only implements
' INotifyCompletion, so this results in different codegen
Await CType(Nothing, HopToThreadPoolAwaitable)
End Sub
Public Async Function SimpleVoidTaskMethod() As Task
Console.WriteLine("Before")
Await Task.Delay(TimeSpan.FromSeconds(1.0))
Console.WriteLine("After")
End Function
Public Async Function TaskMethodWithoutAwait() As Task
Console.WriteLine("No Await")
End Function
Public Async Function CapturingThis() As Task
Await Task.Delay(memberField)
End Function
Public Async Function CapturingThisWithoutAwait() As Task
Console.WriteLine(memberField)
End Function
Public Async Function SimpleBoolTaskMethod() As Task(Of Boolean)
Console.WriteLine("Before")
Await Task.Delay(TimeSpan.FromSeconds(1.0))
Console.WriteLine("After")
Return True
End Function
Public Async Sub TwoAwaitsWithDifferentAwaiterTypes()
Console.WriteLine("Before")
If Await SimpleBoolTaskMethod() Then
Await Task.Delay(TimeSpan.FromSeconds(1.0))
End If
Console.WriteLine("After")
End Sub
Public Async Sub AwaitInLoopCondition()
While Await SimpleBoolTaskMethod()
Console.WriteLine("Body")
End While
End Sub
Public Async Function Issue2366a() As Task
While True
Try
Await Task.CompletedTask
Catch
End Try
End While
End Function
Public Shared Async Function GetIntegerSumAsync(ByVal items As IEnumerable(Of Integer)) As Task(Of Integer)
Await Task.Delay(100)
Dim num = 0
For Each item In items
num += item
Next
Return num
End Function
Public Async Function AsyncCatch(ByVal b As Boolean, ByVal task1 As Task(Of Integer), ByVal task2 As Task(Of Integer)) As Task
Try
Console.WriteLine("Start try")
Await task1
Console.WriteLine("End try")
Catch ex As Exception
Console.WriteLine("No await")
End Try
End Function
Public Async Function AsyncCatchThrow(ByVal b As Boolean, ByVal task1 As Task(Of Integer), ByVal task2 As Task(Of Integer)) As Task
Try
Console.WriteLine("Start try")
Await task1
Console.WriteLine("End try")
Catch ex As Exception
Console.WriteLine("No await")
Throw
End Try
End Function
Public Async Function AsyncFinally(ByVal b As Boolean, ByVal task1 As Task(Of Integer), ByVal task2 As Task(Of Integer)) As Task
Try
Console.WriteLine("Start try")
Await task1
Console.WriteLine("End try")
Finally
Console.WriteLine("No await")
End Try
End Function
Public Shared Async Function AlwaysThrow() As Task
Throw New Exception
End Function
Public Shared Async Function InfiniteLoop() As Task
While True
End While
End Function
Public Shared Async Function InfiniteLoopWithAwait() As Task
While True
Await Task.Delay(10)
End While
End Function
Public Async Function AsyncWithLocalVar() As Task
Dim a As Object = New Object()
Await UseObj(a)
Await UseObj(a)
End Function
Public Shared Async Function UseObj(ByVal a As Object) As Task
End Function
End Class
Public Structure AsyncInStruct
Private i As Integer
Public Async Function Test(ByVal xx As AsyncInStruct) As Task(Of Integer)
xx.i += 1
i += 1
Await Task.Yield()
Return i + xx.i
End Function
End Structure
Public Structure HopToThreadPoolAwaitable
Implements INotifyCompletion
Public Property IsCompleted As Boolean
Public Function GetAwaiter() As HopToThreadPoolAwaitable
Return Me
End Function
Public Sub OnCompleted(ByVal continuation As Action) Implements INotifyCompletion.OnCompleted
Task.Run(continuation)
End Sub
Public Sub GetResult()
End Sub
End Structure
End Namespace

14
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
public class VBAutomaticEvents
{
public delegate void EventWithParameterEventHandler(int EventNumber);
public delegate void EventWithoutParameterEventHandler();
public event EventWithParameterEventHandler EventWithParameter;
public event EventWithoutParameterEventHandler EventWithoutParameter;
public void RaiseEvents()
{
EventWithParameter?.Invoke(1);
EventWithoutParameter?.Invoke();
}
}

9
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.vb

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
Public Class VBAutomaticEvents
Event EventWithParameter(ByVal EventNumber As Integer)
Event EventWithoutParameter()
Sub RaiseEvents()
RaiseEvent EventWithParameter(1)
RaiseEvent EventWithoutParameter()
End Sub
End Class

20
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBNonGenericForEach.cs

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class VBNonGenericForEach
{
public static void M()
{
ArrayList arrayList = new ArrayList();
foreach (object item in arrayList)
{
#if ROSLYN && OPT
Console.WriteLine(RuntimeHelpers.GetObjectValue(RuntimeHelpers.GetObjectValue(item)));
#else
object objectValue = RuntimeHelpers.GetObjectValue(item);
Console.WriteLine(RuntimeHelpers.GetObjectValue(objectValue));
#endif
}
}
}

11
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBNonGenericForEach.vb

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
Imports System
Imports System.Collections
Public Class VBNonGenericForEach
Public Shared Sub M()
Dim collection = New ArrayList
For Each element In collection
Console.WriteLine(element)
Next
End Sub
End Class

419
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/YieldReturn.cs

@ -0,0 +1,419 @@ @@ -0,0 +1,419 @@
using System;
using System.Collections.Generic;
using Microsoft.VisualBasic.CompilerServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.VBPretty
{
internal struct StructWithYieldReturn
{
private int val;
public IEnumerable<int> Count()
{
yield return val;
yield return val;
}
}
public class YieldReturnPrettyTest
{
private int fieldOnThis;
public static IEnumerable<char> YieldChars {
get {
yield return 'a';
yield return 'b';
yield return 'c';
}
}
internal static void Print<T>(string name, IEnumerator<T> enumerator)
{
Console.WriteLine(name + ": Test start");
while (enumerator.MoveNext())
{
Console.WriteLine(name + ": " + enumerator.Current.ToString());
}
}
public static IEnumerable<string> SimpleYieldReturn()
{
yield return "A";
yield return "B";
yield return "C";
}
public static IEnumerator<string> SimpleYieldReturnEnumerator()
{
yield return "A";
yield return "B";
yield return "C";
}
public IEnumerable<int> YieldReturnParameters(int p)
{
yield return p;
yield return fieldOnThis;
}
public IEnumerator<int> YieldReturnParametersEnumerator(int p)
{
yield return p;
yield return fieldOnThis;
}
public static IEnumerable<int> YieldReturnInLoop()
{
int num = 0;
do
{
yield return num;
num = checked(num + 1);
} while (num <= 99);
}
public static IEnumerable<int> YieldReturnWithTryFinally()
{
yield return 0;
try
{
yield return 1;
}
finally
{
Console.WriteLine("Finally!");
}
yield return 2;
}
public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle)
{
Console.WriteLine("Start of method - 1");
yield return "Start of method";
Console.WriteLine("Start of method - 2");
try
{
Console.WriteLine("Within outer try - 1");
yield return "Within outer try";
Console.WriteLine("Within outer try - 2");
try
{
Console.WriteLine("Within inner try - 1");
yield return "Within inner try";
Console.WriteLine("Within inner try - 2");
if (breakInMiddle)
{
Console.WriteLine("Breaking...");
yield break;
}
Console.WriteLine("End of inner try - 1");
yield return "End of inner try";
Console.WriteLine("End of inner try - 2");
}
finally
{
Console.WriteLine("Inner Finally");
}
Console.WriteLine("End of outer try - 1");
yield return "End of outer try";
Console.WriteLine("End of outer try - 2");
}
finally
{
Console.WriteLine("Outer Finally");
}
Console.WriteLine("End of method - 1");
yield return "End of method";
Console.WriteLine("End of method - 2");
}
public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input)
{
// outer try-finally block
foreach (string item in input)
{
// nested try-finally block
try
{
yield return item;
}
finally
{
Console.WriteLine("Processed " + item);
}
}
yield return "A";
yield return "B";
yield return "C";
yield return "D";
yield return "E";
yield return "F";
// outer try-finally block
foreach (string item2 in input)
{
yield return item2.ToUpper();
}
}
public static IEnumerable<int> GetEvenNumbers(int n)
{
int num = checked(n - 1);
for (int i = 0; i <= num; i = checked(i + 1))
{
if (i % 2 == 0)
{
yield return i;
}
}
}
public static IEnumerable<char> ExceptionHandling()
{
yield return 'a';
try
{
Console.WriteLine("1 - try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("1 - catch");
ProjectData.ClearProjectError();
}
yield return 'b';
try
{
try
{
Console.WriteLine("2 - try");
}
finally
{
Console.WriteLine("2 - finally");
}
yield return 'c';
}
finally
{
Console.WriteLine("outer finally");
}
}
public static IEnumerable<int> YieldBreakInCatch()
{
yield return 0;
try
{
Console.WriteLine("In Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
ProjectData.ClearProjectError();
// yield return is not allowed in catch, but yield break is
yield break;
}
yield return 1;
}
public static IEnumerable<int> YieldBreakInCatchInTryFinally()
{
try
{
yield return 0;
try
{
Console.WriteLine("In Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
ProjectData.ClearProjectError();
// yield return is not allowed in catch, but yield break is
// Note that pre-roslyn, this code triggers a compiler bug:
// If the finally block throws an exception, it ends up getting
// called a second time.
yield break;
}
yield return 1;
}
finally
{
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakInTryCatchInTryFinally()
{
try
{
yield return 0;
try
{
Console.WriteLine("In Try");
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
yield return 1;
}
finally
{
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakInTryFinallyInTryFinally(bool b)
{
try
{
yield return 0;
try
{
Console.WriteLine("In Try");
if (b)
{
// same compiler bug as in YieldBreakInCatchInTryFinally
yield break;
}
}
finally
{
Console.WriteLine("Inner Finally");
}
yield return 1;
}
finally
{
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> YieldBreakOnly()
{
yield break;
}
public static IEnumerable<int> UnconditionalThrowInTryFinally()
{
// Here, MoveNext() doesn't call the finally methods at all
// (only indirectly via Dispose())
try
{
yield return 0;
throw new NotImplementedException();
}
finally
{
Console.WriteLine("Finally");
}
}
public static IEnumerable<int> NestedTryFinallyStartingOnSamePosition()
{
// The first user IL instruction is already in 2 nested try blocks.
#if ((ROSLYN2 && !ROSLYN4) && OPT)
int num = -1;
#endif
try
{
#if ((ROSLYN2 && !ROSLYN4) && OPT)
_ = num - 1;
#endif
try
{
yield return 0;
}
finally
{
Console.WriteLine("Inner Finally");
}
}
finally
{
Console.WriteLine("Outer Finally");
}
}
#if ROSLYN
public static IEnumerable<int> LocalInFinally<T>(T a) where T : IDisposable
{
yield return 1;
try
{
yield return 2;
}
finally
{
T val = a;
val.Dispose();
val.Dispose();
}
yield return 3;
}
#endif
public static IEnumerable<T> GenericYield<T>() where T : new()
{
T val = new T();
int num = 0;
do
{
yield return val;
num = checked(num + 1);
} while (num <= 2);
}
public static IEnumerable<int> MultipleYieldBreakInTryFinally(int i)
{
try
{
if (i == 2)
{
yield break;
}
while (i < 40)
{
if (i % 2 == 0)
{
yield break;
}
i = checked(i + 1);
yield return i;
}
}
finally
{
Console.WriteLine("finally");
}
Console.WriteLine("normal exit");
}
internal IEnumerable<int> ForLoopWithYieldReturn(int end, int evil)
{
// This loop needs to pick the implicit "yield break;" as exit point
// in order to produce pretty code; not the "throw" which would
// be a less-pretty option.
checked
{
int num = end - 1;
for (int i = 0; i <= num; i++)
{
if (i == evil)
{
throw new InvalidOperationException("Found evil number");
}
yield return i;
}
}
}
}
}

300
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/YieldReturn.vb

@ -0,0 +1,300 @@ @@ -0,0 +1,300 @@
Imports System
Imports System.Collections.Generic
Namespace ICSharpCode.Decompiler.Tests.TestCases.VBPretty
Friend Structure StructWithYieldReturn
Private val As Integer
Public Iterator Function Count() As IEnumerable(Of Integer)
Yield val
Yield val
End Function
End Structure
Public Class YieldReturnPrettyTest
Private fieldOnThis As Integer
Public Shared ReadOnly Iterator Property YieldChars As IEnumerable(Of Char)
Get
Yield "a"c
Yield "b"c
Yield "c"c
End Get
End Property
Friend Shared Sub Print(Of T)(ByVal name As String, ByVal enumerator As IEnumerator(Of T))
Console.WriteLine(name + ": Test start")
While enumerator.MoveNext()
Console.WriteLine(name + ": " + enumerator.Current.ToString())
End While
End Sub
Public Shared Iterator Function SimpleYieldReturn() As IEnumerable(Of String)
Yield "A"
Yield "B"
Yield "C"
End Function
Public Shared Iterator Function SimpleYieldReturnEnumerator() As IEnumerator(Of String)
Yield "A"
Yield "B"
Yield "C"
End Function
Public Iterator Function YieldReturnParameters(ByVal p As Integer) As IEnumerable(Of Integer)
Yield p
Yield fieldOnThis
End Function
Public Iterator Function YieldReturnParametersEnumerator(ByVal p As Integer) As IEnumerator(Of Integer)
Yield p
Yield fieldOnThis
End Function
Public Shared Iterator Function YieldReturnInLoop() As IEnumerable(Of Integer)
For i = 0 To 99
Yield i
Next
End Function
Public Shared Iterator Function YieldReturnWithTryFinally() As IEnumerable(Of Integer)
Yield 0
Try
Yield 1
Finally
Console.WriteLine("Finally!")
End Try
Yield 2
End Function
Public Shared Iterator Function YieldReturnWithNestedTryFinally(ByVal breakInMiddle As Boolean) As IEnumerable(Of String)
Console.WriteLine("Start of method - 1")
Yield "Start of method"
Console.WriteLine("Start of method - 2")
Try
Console.WriteLine("Within outer try - 1")
Yield "Within outer try"
Console.WriteLine("Within outer try - 2")
Try
Console.WriteLine("Within inner try - 1")
Yield "Within inner try"
Console.WriteLine("Within inner try - 2")
If breakInMiddle Then
Console.WriteLine("Breaking...")
Return
End If
Console.WriteLine("End of inner try - 1")
Yield "End of inner try"
Console.WriteLine("End of inner try - 2")
Finally
Console.WriteLine("Inner Finally")
End Try
Console.WriteLine("End of outer try - 1")
Yield "End of outer try"
Console.WriteLine("End of outer try - 2")
Finally
Console.WriteLine("Outer Finally")
End Try
Console.WriteLine("End of method - 1")
Yield "End of method"
Console.WriteLine("End of method - 2")
End Function
Public Shared Iterator Function YieldReturnWithTwoNonNestedFinallyBlocks(ByVal input As IEnumerable(Of String)) As IEnumerable(Of String)
' outer try-finally block
For Each line In input
' nested try-finally block
Try
Yield line
Finally
Console.WriteLine("Processed " & line)
End Try
Next
Yield "A"
Yield "B"
Yield "C"
Yield "D"
Yield "E"
Yield "F"
' outer try-finally block
For Each item In input
Yield item.ToUpper()
Next
End Function
Public Shared Iterator Function GetEvenNumbers(ByVal n As Integer) As IEnumerable(Of Integer)
For i = 0 To n - 1
If i Mod 2 = 0 Then
Yield i
End If
Next
End Function
Public Shared Iterator Function ExceptionHandling() As IEnumerable(Of Char)
Yield "a"c
Try
Console.WriteLine("1 - try")
Catch __unusedException1__ As Exception
Console.WriteLine("1 - catch")
End Try
Yield "b"c
Try
Try
Console.WriteLine("2 - try")
Finally
Console.WriteLine("2 - finally")
End Try
Yield "c"c
Finally
Console.WriteLine("outer finally")
End Try
End Function
Public Shared Iterator Function YieldBreakInCatch() As IEnumerable(Of Integer)
Yield 0
Try
Console.WriteLine("In Try")
Catch
' yield return is not allowed in catch, but yield break is
Return
End Try
Yield 1
End Function
Public Shared Iterator Function YieldBreakInCatchInTryFinally() As IEnumerable(Of Integer)
Try
Yield 0
Try
Console.WriteLine("In Try")
Catch
' yield return is not allowed in catch, but yield break is
' Note that pre-roslyn, this code triggers a compiler bug:
' If the finally block throws an exception, it ends up getting
' called a second time.
Return
End Try
Yield 1
Finally
Console.WriteLine("Finally")
End Try
End Function
Public Shared Iterator Function YieldBreakInTryCatchInTryFinally() As IEnumerable(Of Integer)
Try
Yield 0
Try
Console.WriteLine("In Try")
' same compiler bug as in YieldBreakInCatchInTryFinally
Return
Catch
Console.WriteLine("Catch")
End Try
Yield 1
Finally
Console.WriteLine("Finally")
End Try
End Function
Public Shared Iterator Function YieldBreakInTryFinallyInTryFinally(ByVal b As Boolean) As IEnumerable(Of Integer)
Try
Yield 0
Try
Console.WriteLine("In Try")
If b Then
' same compiler bug as in YieldBreakInCatchInTryFinally
Return
End If
Finally
Console.WriteLine("Inner Finally")
End Try
Yield 1
Finally
Console.WriteLine("Finally")
End Try
End Function
Public Shared Iterator Function YieldBreakOnly() As IEnumerable(Of Integer)
Return
End Function
Public Shared Iterator Function UnconditionalThrowInTryFinally() As IEnumerable(Of Integer)
' Here, MoveNext() doesn't call the finally methods at all
' (only indirectly via Dispose())
Try
Yield 0
Throw New NotImplementedException()
Finally
Console.WriteLine("Finally")
End Try
End Function
Public Shared Iterator Function NestedTryFinallyStartingOnSamePosition() As IEnumerable(Of Integer)
' The first user IL instruction is already in 2 nested try blocks.
Try
Try
Yield 0
Finally
Console.WriteLine("Inner Finally")
End Try
Finally
Console.WriteLine("Outer Finally")
End Try
End Function
#If ROSLYN Then
Public Shared Iterator Function LocalInFinally(Of T As IDisposable)(ByVal a As T) As IEnumerable(Of Integer)
Yield 1
Try
Yield 2
Finally
Dim val = a
val.Dispose()
val.Dispose()
End Try
Yield 3
End Function
#End If
Public Shared Iterator Function GenericYield(Of T As New)() As IEnumerable(Of T)
Dim val As T = New T()
For i = 0 To 2
Yield val
Next
End Function
Public Shared Iterator Function MultipleYieldBreakInTryFinally(ByVal i As Integer) As IEnumerable(Of Integer)
Try
If i = 2 Then
Return
End If
While i < 40
If i Mod 2 = 0 Then
Return
End If
i += 1
Yield i
End While
Finally
Console.WriteLine("finally")
End Try
Console.WriteLine("normal exit")
End Function
Friend Iterator Function ForLoopWithYieldReturn(ByVal [end] As Integer, ByVal evil As Integer) As IEnumerable(Of Integer)
' This loop needs to pick the implicit "yield break;" as exit point
' in order to produce pretty code; not the "throw" which would
' be a less-pretty option.
For i = 0 To [end] - 1
If i = evil Then
Throw New InvalidOperationException("Found evil number")
End If
Yield i
Next
End Function
End Class
End Namespace

10
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -616,6 +616,16 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -616,6 +616,16 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsTrue(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));
}
[Test]
public void NoDefaultConstructorAddedToClass()
{

5
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs

@ -140,6 +140,11 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -140,6 +140,11 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public MyStructWithCtor(int a) { }
}
public struct MyStructWithDefaultCtor
{
public MyStructWithDefaultCtor() { }
}
public class MyClassWithCtor
{
private MyClassWithCtor(int a) { }

4
ICSharpCode.Decompiler.Tests/Util/FileUtilityTests.cs

@ -16,9 +16,11 @@ @@ -16,9 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Util;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Util
namespace ICSharpCode.Decompiler.Tests.Util
{
[TestFixture]
public class FileUtilityTests

189
ICSharpCode.Decompiler.Tests/Util/ResourceReaderWriterTests.cs

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
// Copyright (c) 2023 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.Globalization;
using System.IO;
using System.Linq;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using System.Xml.XPath;
using ICSharpCode.Decompiler.Util;
using NUnit.Framework;
using NUnit.Framework.Internal;
namespace ICSharpCode.Decompiler.Tests.Util
{
[TestFixture]
public class ResourceReaderWriterTests
{
const string WinFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
const string MSCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
[Serializable]
public class SerializableClass
{
public string Name { get; set; }
public int Age { get; set; }
}
static readonly object[][] TestWriteCases = {
new object[] { "Decimal", 1.0m, "1.0", "System.Decimal" + MSCorLibAssemblyName },
new object[] { "TimeSpan", TimeSpan.FromSeconds(42), "00:00:42", "System.TimeSpan" + MSCorLibAssemblyName },
new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture), "06/18/2023 21:36:30", "System.DateTime" + MSCorLibAssemblyName },
};
static readonly object[][] TestReadCases = {
new object[] { "Decimal", 1.0m },
new object[] { "TimeSpan", TimeSpan.FromSeconds(42) },
new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture) },
};
static MemoryStream ProduceResourcesTestFile<T>(string name, T value)
{
var ms = new MemoryStream();
var writer = new ResourceWriter(ms);
writer.AddResource(name, value);
writer.Generate();
ms.Position = 0;
return ms;
}
static XElement ProduceResXTest<T>(string name, T value)
{
using var ms = new MemoryStream();
var writer = new ResXResourceWriter(ms);
writer.AddResource(name, value);
writer.Generate();
ms.Position = 0;
var doc = XDocument.Load(ms);
return doc.XPathSelectElement(".//data");
}
[TestCase("Null", null)]
[TestCase("String", "Hello World!")]
[TestCase("Char", 'A')]
[TestCase("Bool", true)]
[TestCase("Bool", false)]
[TestCase("Byte", (byte)1)]
[TestCase("SByte", (sbyte)-1)]
[TestCase("Int16", (short)1)]
[TestCase("UInt16", (ushort)1)]
[TestCase("Int32", 1)]
[TestCase("UInt32", (uint)1)]
[TestCase("Int64", (long)1)]
[TestCase("UInt64", (ulong)1)]
[TestCase("Single", 1.0f)]
[TestCase("Double", 1.0d)]
[TestCase("Bytes", new byte[] { 42, 43, 44 })]
[TestCaseSource(nameof(TestReadCases))]
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);
}
[TestCase("Null", null, null, "System.Resources.ResXNullRef" + WinFormsAssemblyName)]
[TestCase("String", "Hello World!", "Hello World!", null)]
[TestCase("Bool", true, "True", "System.Boolean" + MSCorLibAssemblyName)]
[TestCase("Bool", false, "False", "System.Boolean" + MSCorLibAssemblyName)]
[TestCase("Char", 'A', "A", "System.Char" + MSCorLibAssemblyName)]
[TestCase("Byte", (byte)1, "1", "System.Byte" + MSCorLibAssemblyName)]
[TestCase("SByte", (sbyte)-1, "-1", "System.SByte" + MSCorLibAssemblyName)]
[TestCase("Int16", (short)1, "1", "System.Int16" + MSCorLibAssemblyName)]
[TestCase("UInt16", (ushort)1, "1", "System.UInt16" + MSCorLibAssemblyName)]
[TestCase("Int32", 1, "1", "System.Int32" + MSCorLibAssemblyName)]
[TestCase("UInt32", (uint)1, "1", "System.UInt32" + MSCorLibAssemblyName)]
[TestCase("Int64", (long)1, "1", "System.Int64" + MSCorLibAssemblyName)]
[TestCase("UInt64", (ulong)1, "1", "System.UInt64" + MSCorLibAssemblyName)]
[TestCase("Single", 1.0f, "1", "System.Single" + MSCorLibAssemblyName)]
[TestCase("Double", 1.0d, "1", "System.Double" + MSCorLibAssemblyName)]
[TestCaseSource(nameof(TestWriteCases))]
public void Write(string name, object value, string serializedValue, string typeName)
{
var element = ProduceResXTest(name, value);
Assert.AreEqual(name, element.Attribute("name")?.Value);
if (typeName != null)
{
Assert.AreEqual(typeName, element.Attribute("type")?.Value);
}
var v = element.Element("value");
Assert.IsNotNull(v);
Assert.IsTrue(v.IsEmpty ? serializedValue == null : v.Value == serializedValue);
}
[Test]
public void ResXSerializableClassIsRejected()
{
Assert.Throws<NotSupportedException>(
() => ProduceResXTest("Serial", new SerializableClass { Name = "Hugo", Age = 42 })
);
}
[Test]
public void BitmapIsResourceSerializedObject()
{
Stream stream = typeof(ResourceReaderWriterTests).Assembly
.GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
using var reader = new ResourcesFile(stream);
var items = reader.ToArray();
Assert.AreEqual(3, items.Length);
var item = items.FirstOrDefault(i => i.Key == "Bitmap");
Assert.IsNotNull(item.Key);
Assert.IsInstanceOf<ResourceSerializedObject>(item.Value);
}
[Test]
public void ByteArrayIsSupported()
{
Stream stream = typeof(ResourceReaderWriterTests).Assembly
.GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
using var reader = new ResourcesFile(stream);
var items = reader.ToArray();
Assert.AreEqual(3, items.Length);
var item = items.FirstOrDefault(i => i.Key == "Byte[]");
Assert.IsNotNull(item.Key);
Assert.IsInstanceOf<byte[]>(item.Value);
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]);
}
[Test]
public void MemoryStreamIsSupported()
{
Stream stream = typeof(ResourceReaderWriterTests).Assembly
.GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
using var reader = new ResourcesFile(stream);
var items = reader.ToArray();
Assert.AreEqual(3, items.Length);
var item = items.FirstOrDefault(i => i.Key == "MemoryStream");
Assert.IsNotNull(item.Key);
Assert.IsInstanceOf<MemoryStream>(item.Value);
}
}
}

BIN
ICSharpCode.Decompiler.Tests/Util/Test.resources

Binary file not shown.

26
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 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
@ -89,10 +89,10 @@ namespace ICSharpCode.Decompiler.Tests @@ -89,10 +89,10 @@ namespace ICSharpCode.Decompiler.Tests
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
[Test, Ignore("Implement VB async/await")]
[Test]
public async Task Async([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
await Run(options: options);
await Run(options: options | CompilerOptions.Library);
}
[Test] // TODO: legacy VB compound assign
@ -125,6 +125,24 @@ namespace ICSharpCode.Decompiler.Tests @@ -125,6 +125,24 @@ namespace ICSharpCode.Decompiler.Tests
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task VBAutomaticEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task VBNonGenericForEach([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
await Run(options: options | CompilerOptions.Library);
}
async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
{
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
@ -136,7 +154,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -136,7 +154,7 @@ namespace ICSharpCode.Decompiler.Tests
}
var executable = await Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile).ConfigureAwait(false);
var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings).ConfigureAwait(false);
var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings ?? new DecompilerSettings { FileScopedNamespaces = false }).ConfigureAwait(false);
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
Tester.RepeatOnIOError(() => File.Delete(decompiled));

130
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1,4 +1,4 @@ @@ -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
@ -367,8 +367,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -367,8 +367,16 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
}
// event-fields are not [CompilerGenerated]
if (settings.AutomaticEvents && metadata.GetTypeDefinition(field.GetDeclaringType()).GetEvents().Any(ev => metadata.GetEventDefinition(ev).Name == field.Name))
return true;
if (settings.AutomaticEvents)
{
foreach (var ev in metadata.GetTypeDefinition(field.GetDeclaringType()).GetEvents())
{
var eventName = metadata.GetString(metadata.GetEventDefinition(ev).Name);
var fieldName = metadata.GetString(field.Name);
if (IsEventBackingFieldName(fieldName, eventName, out _))
return true;
}
}
if (settings.ArrayInitializers && metadata.GetString(metadata.GetTypeDefinition(field.GetDeclaringType()).Name).StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
{
// only hide fields starting with '__StaticArrayInit'
@ -412,6 +420,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -412,6 +420,20 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
internal static bool IsEventBackingFieldName(string fieldName, string eventName, out int suffixLength)
{
suffixLength = 0;
if (fieldName == eventName)
return true;
var vbSuffixLength = "Event".Length;
if (fieldName.Length == eventName.Length + vbSuffixLength && fieldName.StartsWith(eventName, StringComparison.Ordinal) && fieldName.EndsWith("Event", StringComparison.Ordinal))
{
suffixLength = vbSuffixLength;
return true;
}
return false;
}
static bool IsAnonymousMethodCacheField(SRM.FieldDefinition field, MetadataReader metadata)
{
var name = metadata.GetString(field.Name);
@ -508,6 +530,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -508,6 +530,7 @@ namespace ICSharpCode.Decompiler.CSharp
typeSystemAstBuilder.SupportInitAccessors = settings.InitAccessors;
typeSystemAstBuilder.SupportRecordClasses = settings.RecordClasses;
typeSystemAstBuilder.SupportRecordStructs = settings.RecordStructs;
typeSystemAstBuilder.SupportUnsignedRightShift = settings.UnsignedRightShift;
typeSystemAstBuilder.AlwaysUseGlobal = settings.AlwaysUseGlobal;
return typeSystemAstBuilder;
}
@ -827,7 +850,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -827,7 +850,7 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var m in closureType.GetMethods())
{
var methodDef = module.Metadata.GetMethodDefinition(m);
if (methodDef.Name == memberRef.Name)
if (methodDef.Name == memberRef.Name && m.IsCompilerGeneratedOrIsInCompilerGeneratedClass(module.Metadata))
connectedMethods.Enqueue(m);
}
}
@ -953,7 +976,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -953,7 +976,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
if (type.ParentModule != typeSystem.MainModule)
throw new NotSupportedException("Decompiling types that are not part of the main module is not supported.");
throw new NotSupportedException($"Type {fullTypeName} was not found in the module being decompiled, but only in {type.ParentModule.Name}");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree();
@ -1266,6 +1289,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1266,6 +1289,11 @@ namespace ICSharpCode.Decompiler.CSharp
{
typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef);
if (entityDecl is DelegateDeclaration delegateDeclaration)
{
// Fix empty parameter names in delegate declarations
FixParameterNames(delegateDeclaration);
}
var typeDecl = entityDecl as TypeDeclaration;
if (typeDecl == null)
{
@ -1369,16 +1397,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1369,16 +1397,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
if (settings.IntroduceRefModifiersOnStructs)
{
if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr))
{
if (obsoleteAttributePattern.IsMatch(attr))
{
if (attr.Parent is AttributeSection section && section.Attributes.Count == 1)
section.Remove();
else
attr.Remove();
}
}
RemoveObsoleteAttribute(typeDecl, "Types with embedded references are not supported in this version of your compiler.");
RemoveCompilerFeatureRequiredAttribute(typeDecl, "RefStructs");
}
if (settings.RequiredMembers)
{
RemoveAttribute(typeDecl, KnownAttribute.RequiredAttribute);
}
if (typeDecl.ClassType == ClassType.Enum)
{
@ -1551,14 +1575,6 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1551,14 +1575,6 @@ namespace ICSharpCode.Decompiler.CSharp
return firstValue == 0 ? EnumValueDisplayMode.None : EnumValueDisplayMode.FirstOnly;
}
static readonly Syntax.Attribute obsoleteAttributePattern = new Syntax.Attribute() {
Type = new TypePattern(typeof(ObsoleteAttribute)),
Arguments = {
new PrimitiveExpression("Types with embedded references are not supported in this version of your compiler."),
new Choice() { new PrimitiveExpression(true), new PrimitiveExpression(false) }
}
};
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == method);
@ -1612,6 +1628,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1612,6 +1628,10 @@ namespace ICSharpCode.Decompiler.CSharp
methodDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
methodDecl.Modifiers |= Modifiers.Override;
}
if (method.IsConstructor && settings.RequiredMembers && RemoveCompilerFeatureRequiredAttribute(methodDecl, "RequiredMembers"))
{
RemoveObsoleteAttribute(methodDecl, "Constructors of types with required members are not supported in this version of your compiler.");
}
return methodDecl;
bool IsTypeHierarchyKnown(IType type)
@ -1773,6 +1793,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1773,6 +1793,14 @@ namespace ICSharpCode.Decompiler.CSharp
{
RemoveAttribute(entityDecl, KnownAttribute.DebuggerHidden);
}
if (function.StateMachineCompiledWithLegacyVisualBasic)
{
RemoveAttribute(entityDecl, KnownAttribute.DebuggerStepThrough);
if (function.Method?.IsAccessor == true && entityDecl.Parent is EntityDeclaration parentDecl)
{
RemoveAttribute(parentDecl, KnownAttribute.DebuggerStepThrough);
}
}
}
if (function.IsAsync)
{
@ -1812,6 +1840,54 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1812,6 +1840,54 @@ namespace ICSharpCode.Decompiler.CSharp
return found;
}
internal static bool RemoveCompilerFeatureRequiredAttribute(EntityDeclaration entityDecl, string feature)
{
bool found = false;
foreach (var section in entityDecl.Attributes)
{
foreach (var attr in section.Attributes)
{
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == KnownAttribute.CompilerFeatureRequired.GetTypeName()
&& attr.Arguments.Count == 1 && attr.Arguments.SingleOrDefault() is PrimitiveExpression pe
&& pe.Value is string s && s == feature)
{
attr.Remove();
found = true;
}
}
if (section.Attributes.Count == 0)
{
section.Remove();
}
}
return found;
}
internal static bool RemoveObsoleteAttribute(EntityDeclaration entityDecl, string message)
{
bool found = false;
foreach (var section in entityDecl.Attributes)
{
foreach (var attr in section.Attributes)
{
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == KnownAttribute.Obsolete.GetTypeName()
&& attr.Arguments.Count >= 1 && attr.Arguments.First() is PrimitiveExpression pe
&& pe.Value is string s && s == message)
{
attr.Remove();
found = true;
}
}
if (section.Attributes.Count == 0)
{
section.Remove();
}
}
return found;
}
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute)
{
attribute = null;
@ -1871,6 +1947,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1871,6 +1947,10 @@ namespace ICSharpCode.Decompiler.CSharp
typeSystemAstBuilder.UseSpecialConstants = !(field.DeclaringType.Equals(field.ReturnType) || isMathPIOrE);
var fieldDecl = typeSystemAstBuilder.ConvertEntity(field);
SetNewModifier(fieldDecl);
if (settings.RequiredMembers && RemoveAttribute(fieldDecl, KnownAttribute.RequiredAttribute))
{
fieldDecl.Modifiers |= Modifiers.Required;
}
if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount))
{
var fixedFieldDecl = new FixedFieldDeclaration();
@ -1983,6 +2063,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1983,6 +2063,10 @@ namespace ICSharpCode.Decompiler.CSharp
propertyDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
propertyDecl.Modifiers |= Modifiers.Override;
}
if (settings.RequiredMembers && RemoveAttribute(propertyDecl, KnownAttribute.RequiredAttribute))
{
propertyDecl.Modifiers |= Modifiers.Required;
}
return propertyDecl;
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))

39
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -77,8 +77,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -77,8 +77,8 @@ namespace ICSharpCode.Decompiler.CSharp
ResolveResult GetResolveResult(int index, TranslatedExpression expression)
{
var param = expectedParameters[index];
if (useImplicitlyTypedOut && param.IsOut)
return OutVarResolveResult.Instance;
if (useImplicitlyTypedOut && param.IsOut && expression.Type is ByReferenceType brt)
return new OutVarResolveResult(brt.ElementType);
return expression.ResolveResult;
}
}
@ -539,6 +539,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -539,6 +539,8 @@ namespace ICSharpCode.Decompiler.CSharp
public ExpressionWithResolveResult BuildDictionaryInitializerExpression(OpCode callOpCode, IMethod method,
InitializedObjectResolveResult target, IReadOnlyList<ILInstruction> indices, ILInstruction value = null)
{
if (method is null)
throw new ArgumentNullException(nameof(method));
ExpectedTargetDetails expectedTargetDetails = new ExpectedTargetDetails { CallOpCode = callOpCode };
var callArguments = new List<ILInstruction>();
@ -1017,6 +1019,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1017,6 +1019,10 @@ namespace ICSharpCode.Decompiler.CSharp
{
switch (errors)
{
case OverloadResolutionErrors.OutVarTypeMismatch:
Debug.Assert(argumentList.UseImplicitlyTypedOut);
argumentList.UseImplicitlyTypedOut = false;
continue;
case OverloadResolutionErrors.TypeInferenceFailed:
if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0)
{
@ -1318,6 +1324,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1318,6 +1324,20 @@ namespace ICSharpCode.Decompiler.CSharp
foundMember = or.GetBestCandidateWithSubstitutedTypeArguments();
if (!IsAppropriateCallTarget(expectedTargetDetails, method, foundMember))
return OverloadResolutionErrors.AmbiguousMatch;
var map = or.GetArgumentToParameterMap();
for (int i = 0; i < arguments.Length; i++)
{
ResolveResult arg = arguments[i];
int parameterIndex = map[i];
if (arg is OutVarResolveResult rr && parameterIndex >= 0)
{
var param = foundMember.Parameters[parameterIndex];
var paramType = param.Type.UnwrapByRef();
if (!paramType.Equals(rr.OriginalVariableType))
return OverloadResolutionErrors.OutVarTypeMismatch;
}
}
return OverloadResolutionErrors.None;
}
@ -1533,12 +1553,25 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1533,12 +1553,25 @@ namespace ICSharpCode.Decompiler.CSharp
CastArguments(argumentList.Arguments, argumentList.ExpectedParameters);
break; // make sure that we don't not end up in an infinite loop
}
IType returnTypeOverride = null;
if (typeSystem.MainModule.TypeSystemOptions.HasFlag(TypeSystemOptions.NativeIntegersWithoutAttribute))
{
// For DeclaringType, we don't use nint/nuint (so that DeclaringType.GetConstructors etc. works),
// but in NativeIntegersWithoutAttribute mode we must use nint/nuint for expression types,
// so that the appropriate set of conversions is used for further overload resolution.
if (method.DeclaringType.IsKnownType(KnownTypeCode.IntPtr))
returnTypeOverride = SpecialType.NInt;
else if (method.DeclaringType.IsKnownType(KnownTypeCode.UIntPtr))
returnTypeOverride = SpecialType.NUInt;
}
return new ObjectCreateExpression(
expressionBuilder.ConvertType(method.DeclaringType),
argumentList.GetArgumentExpressions()
).WithRR(new CSharpInvocationResolveResult(
target, method, argumentList.GetArgumentResolveResults().ToArray(),
isExpandedForm: argumentList.IsExpandedForm, argumentToParameterMap: argumentList.ArgumentToParameterMap
isExpandedForm: argumentList.IsExpandedForm,
argumentToParameterMap: argumentList.ArgumentToParameterMap,
returnTypeOverride: returnTypeOverride
));
}
}

75
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2014-2020 Daniel Grunwald
// Copyright (c) 2014-2020 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
@ -375,7 +375,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -375,7 +375,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var arg = Translate(inst.Argument);
arg = UnwrapBoxingConversion(arg);
return new IsExpression(arg.Expression, ConvertType(inst.Type))
return new IsExpression(arg.Expression, ConvertType(inst.Type.TupleUnderlyingTypeOrSelf()))
.WithILInstruction(inst)
.WithRR(new TypeIsResolveResult(arg.ResolveResult, inst.Type, compilation.FindType(TypeCode.Boolean)));
}
@ -617,6 +617,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -617,6 +617,14 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.String), inst.Value));
}
protected internal override TranslatedExpression VisitLdStrUtf8(LdStrUtf8 inst, TranslationContext context)
{
var type = new ParameterizedType(compilation.FindType(KnownTypeCode.ReadOnlySpanOfT), new[] { compilation.FindType(KnownTypeCode.Byte) });
return new PrimitiveExpression(inst.Value, LiteralFormat.Utf8Literal)
.WithILInstruction(inst)
.WithRR(new ConstantResolveResult(type, inst.Value));
}
protected internal override TranslatedExpression VisitLdNull(LdNull inst, TranslationContext context)
{
return GetDefaultValueExpression(SpecialType.NullType).WithILInstruction(inst);
@ -1200,9 +1208,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1200,9 +1208,9 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryNumericOperator.BitXor:
return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr, context);
case BinaryNumericOperator.ShiftLeft:
return HandleShift(inst, BinaryOperatorType.ShiftLeft);
return HandleShift(inst, BinaryOperatorType.ShiftLeft, context);
case BinaryNumericOperator.ShiftRight:
return HandleShift(inst, BinaryOperatorType.ShiftRight);
return HandleShift(inst, BinaryOperatorType.ShiftRight, context);
default:
throw new ArgumentOutOfRangeException();
}
@ -1579,7 +1587,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1579,7 +1587,7 @@ namespace ICSharpCode.Decompiler.CSharp
var rr = resolverWithOverflowCheck.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult);
if (rr.IsError || NullableType.GetUnderlyingType(rr.Type).GetStackType() != inst.UnderlyingResultType
|| !IsCompatibleWithSign(left.Type, inst.Sign) || !IsCompatibleWithSign(right.Type, inst.Sign))
|| !IsCompatibleWithSign(rr.Type, inst.Sign))
{
// Left and right operands are incompatible, so convert them to a common type
Sign sign = inst.Sign;
@ -1721,13 +1729,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1721,13 +1729,14 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryOperatorType.ExclusiveOr:
case BinaryOperatorType.ShiftLeft:
case BinaryOperatorType.ShiftRight:
case BinaryOperatorType.UnsignedShiftRight:
return false;
default:
return true;
}
}
TranslatedExpression HandleShift(BinaryNumericInstruction inst, BinaryOperatorType op)
TranslatedExpression HandleShift(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context)
{
var left = Translate(inst.Left);
var right = Translate(inst.Right);
@ -1736,10 +1745,27 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1736,10 +1745,27 @@ namespace ICSharpCode.Decompiler.CSharp
Sign sign = inst.Sign;
var leftUType = NullableType.GetUnderlyingType(left.Type);
if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4)
bool couldUseUnsignedRightShift = (
sign == Sign.Unsigned && op == BinaryOperatorType.ShiftRight && settings.UnsignedRightShift
&& (leftUType.IsCSharpPrimitiveIntegerType() || leftUType.IsCSharpNativeIntegerType())
// If we need to cast to unsigned anyway, don't use >>> operator.
&& context.TypeHint.GetSign() != Sign.Unsigned
);
if (leftUType.IsCSharpSmallIntegerType() && inst.UnderlyingResultType == StackType.I4 &&
(sign != Sign.Unsigned || couldUseUnsignedRightShift))
{
// With small integer types, C# will promote to int and perform signed shifts.
// We thus don't need any casts in this case.
// The >>> operator also promotes to signed int, but then performs an unsigned shift.
if (sign == Sign.Unsigned)
{
op = BinaryOperatorType.UnsignedShiftRight;
}
}
else if (couldUseUnsignedRightShift && leftUType.GetSize() == inst.UnderlyingResultType.GetSize() && leftUType.GetSign() == Sign.Signed)
{
// Use C# 11 unsigned right shift operator. We don't need any casts in this case.
op = BinaryOperatorType.UnsignedShiftRight;
}
else
{
@ -1796,7 +1822,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1796,7 +1822,7 @@ namespace ICSharpCode.Decompiler.CSharp
else if (inst.Method.Parameters.Count == 2)
{
var value = Translate(inst.Value).ConvertTo(inst.Method.Parameters[1].Type, this);
AssignmentOperatorType? op = GetAssignmentOperatorTypeFromMetadataName(inst.Method.Name);
AssignmentOperatorType? op = GetAssignmentOperatorTypeFromMetadataName(inst.Method.Name, settings);
Debug.Assert(op != null);
return new AssignmentExpression(target, op.Value, value)
@ -1814,7 +1840,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1814,7 +1840,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
internal static AssignmentOperatorType? GetAssignmentOperatorTypeFromMetadataName(string name)
internal static AssignmentOperatorType? GetAssignmentOperatorTypeFromMetadataName(string name, DecompilerSettings settings)
{
switch (name)
{
@ -1838,6 +1864,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1838,6 +1864,8 @@ namespace ICSharpCode.Decompiler.CSharp
return AssignmentOperatorType.ShiftLeft;
case "op_RightShift":
return AssignmentOperatorType.ShiftRight;
case "op_UnsignedRightShift" when settings.UnsignedRightShift:
return AssignmentOperatorType.UnsignedShiftRight;
default:
return null;
}
@ -1879,7 +1907,22 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1879,7 +1907,22 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryNumericOperator.ShiftLeft:
return HandleCompoundShift(inst, AssignmentOperatorType.ShiftLeft);
case BinaryNumericOperator.ShiftRight:
return HandleCompoundShift(inst, AssignmentOperatorType.ShiftRight);
if (inst.Sign == Sign.Unsigned && inst.Type.GetSign() == Sign.Signed)
{
Debug.Assert(settings.UnsignedRightShift);
return HandleCompoundShift(inst, AssignmentOperatorType.UnsignedShiftRight);
}
else if (inst.Sign == Sign.Unsigned && inst.Type.IsCSharpSmallIntegerType() && settings.UnsignedRightShift)
{
// For small unsigned integer types promoted to signed int, the sign bit will be zero,
// so there is no difference between signed and unsigned shift.
// However the IL still indicates which C# operator was used, so preserve that if the setting allows us to.
return HandleCompoundShift(inst, AssignmentOperatorType.UnsignedShiftRight);
}
else
{
return HandleCompoundShift(inst, AssignmentOperatorType.ShiftRight);
}
default:
throw new ArgumentOutOfRangeException();
}
@ -1901,7 +1944,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1901,7 +1944,16 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.EvalMode == CompoundEvalMode.EvaluatesToOldValue)
{
Debug.Assert(op == AssignmentOperatorType.Add || op == AssignmentOperatorType.Subtract);
Debug.Assert(inst.Value.MatchLdcI(1) || inst.Value.MatchLdcF4(1) || inst.Value.MatchLdcF8(1));
#if DEBUG
if (target.Type is PointerType ptrType)
{
ILInstruction instValue = PointerArithmeticOffset.Detect(inst.Value, ptrType.ElementType, inst.CheckForOverflow);
Debug.Assert(instValue is not null);
Debug.Assert(instValue.MatchLdcI(1));
}
else
Debug.Assert(inst.Value.MatchLdcI(1) || inst.Value.MatchLdcF4(1) || inst.Value.MatchLdcF8(1));
#endif
UnaryOperatorType unary;
ExpressionType exprType;
if (op == AssignmentOperatorType.Add)
@ -3340,6 +3392,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3340,6 +3392,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var property = (IProperty)lastElement.Member;
Debug.Assert(property.IsIndexer);
Debug.Assert(property.Setter != null, $"Indexer property {property} has no setter");
elementsStack.Peek().Add(
new CallBuilder(this, typeSystem, settings)
.BuildDictionaryInitializerExpression(lastElement.OpCode, property.Setter, initObjRR, GetIndices(lastElement.Indices, indexVariables).ToList(), info.Values.Single())

5
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -83,6 +83,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -83,6 +83,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
case ClassType.RecordClass:
writer.WriteKeyword(Roles.RecordKeyword, "record");
break;
case ClassType.RecordStruct:
writer.WriteKeyword(Roles.RecordKeyword, "record");
writer.WriteKeyword(Roles.StructKeyword, "struct");
break;
default:
throw new Exception("Invalid value for ClassType");
}
@ -233,6 +237,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -233,6 +237,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
astBuilder.SupportInitAccessors = (ConversionFlags & ConversionFlags.SupportInitAccessors) != 0;
astBuilder.SupportRecordClasses = (ConversionFlags & ConversionFlags.SupportRecordClasses) != 0;
astBuilder.SupportRecordStructs = (ConversionFlags & ConversionFlags.SupportRecordStructs) != 0;
astBuilder.SupportUnsignedRightShift = (ConversionFlags & ConversionFlags.SupportUnsignedRightShift) != 0;
return astBuilder;
}

11
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -826,6 +826,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -826,6 +826,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
break;
case BinaryOperatorType.ShiftLeft:
case BinaryOperatorType.ShiftRight:
case BinaryOperatorType.UnsignedShiftRight:
spacePolicy = policy.SpaceAroundShiftOperator;
break;
case BinaryOperatorType.NullCoalescing:
@ -2565,9 +2566,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2565,9 +2566,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteKeyword(ParameterDeclaration.ThisModifierRole);
Space();
}
if (parameterDeclaration.IsRefScoped)
if (parameterDeclaration.IsScopedRef)
{
WriteKeyword(ParameterDeclaration.RefScopedRole);
WriteKeyword(ParameterDeclaration.ScopedRefRole);
Space();
}
switch (parameterDeclaration.ParameterModifier)
@ -2589,11 +2590,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2589,11 +2590,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
Space();
break;
}
if (parameterDeclaration.IsValueScoped)
{
WriteKeyword(ParameterDeclaration.ValueScopedRole);
Space();
}
parameterDeclaration.Type.AcceptVisitor(this);
if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name))
{
@ -2835,6 +2831,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2835,6 +2831,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(primitiveType);
writer.WritePrimitiveType(primitiveType.Keyword);
isAfterSpace = false;
EndNode(primitiveType);
}

3
ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs

@ -92,6 +92,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -92,6 +92,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
case BinaryOperatorType.ShiftRight when genericNestingLevel >= 2:
genericNestingLevel -= 2;
break;
case BinaryOperatorType.UnsignedShiftRight when genericNestingLevel >= 3:
genericNestingLevel -= 3;
break;
default:
return true; // stop visiting, no ambiguity found
}

1
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -122,6 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -122,6 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return PrecedenceLevel.Additive;
case BinaryOperatorType.ShiftLeft:
case BinaryOperatorType.ShiftRight:
case BinaryOperatorType.UnsignedShiftRight:
return PrecedenceLevel.Shift;
case BinaryOperatorType.GreaterThan:
case BinaryOperatorType.GreaterThanOrEqual:

5
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs

@ -159,7 +159,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -159,7 +159,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return;
if (value is string)
{
lastWritten = LastWritten.Other;
if (format == LiteralFormat.VerbatimStringLiteral)
lastWritten = LastWritten.KeywordOrIdentifier;
else
lastWritten = LastWritten.Other;
}
else if (value is char)
{

6
ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs

@ -269,6 +269,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -269,6 +269,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
textWriter.Write('"');
textWriter.Write(tmp);
textWriter.Write('"');
if (format == LiteralFormat.Utf8Literal)
{
textWriter.Write("u8");
column += 2;
Length += 2;
}
}
else if (value is char)
{

5
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs

@ -34,9 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -34,9 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
/// <param name="target">The target to write to.</param>
/// <param name="project">The information about the project being created.</param>
/// <param name="files">A collection of source files to be included into the project, each item is a pair
/// of the project entry type and the file path.</param>
/// <param name="files">A collection of source files to be included into the project.</param>
/// <param name="module">The module being decompiled.</param>
void Write(TextWriter target, IProjectInfoProvider project, IEnumerable<(string itemType, string fileName)> files, PEFile module);
void Write(TextWriter target, IProjectInfoProvider project, IEnumerable<ProjectItemInfo> files, PEFile module);
}
}

14
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs

@ -25,6 +25,7 @@ using System.Xml; @@ -25,6 +25,7 @@ using System.Xml;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
public void Write(
TextWriter target,
IProjectInfoProvider project,
IEnumerable<(string itemType, string fileName)> files,
IEnumerable<ProjectItemInfo> files,
PEFile module)
{
const string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
@ -162,13 +163,18 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -162,13 +163,18 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
w.WriteEndElement(); // </ItemGroup> (References)
foreach (IGrouping<string, string> gr in from f in files group f.fileName by f.itemType into g orderby g.Key select g)
foreach (IGrouping<string, ProjectItemInfo> gr in files.GroupBy(f => f.ItemType).OrderBy(g => g.Key))
{
w.WriteStartElement("ItemGroup");
foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))
foreach (var item in gr.OrderBy(f => f.FileName, StringComparer.OrdinalIgnoreCase))
{
w.WriteStartElement(gr.Key);
w.WriteAttributeString("Include", file);
w.WriteAttributeString("Include", item.FileName);
if (item.AdditionalProperties != null)
{
foreach (var (key, value) in item.AdditionalProperties)
w.WriteAttributeString(key, value);
}
w.WriteEndElement();
}
w.WriteEndElement();

31
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
public void Write(
TextWriter target,
IProjectInfoProvider project,
IEnumerable<(string itemType, string fileName)> files,
IEnumerable<ProjectItemInfo> files,
PEFile module)
{
using (XmlTextWriter xmlWriter = new XmlTextWriter(target))
@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable<(string itemType, string fileName)> files, PEFile module)
static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable<ProjectItemInfo> files, PEFile module)
{
xml.WriteStartElement("Project");
@ -188,27 +188,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -188,27 +188,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
static void WriteMiscellaneousPropertyGroup(XmlTextWriter xml, IEnumerable<(string itemType, string fileName)> files)
static void WriteMiscellaneousPropertyGroup(XmlTextWriter xml, IEnumerable<ProjectItemInfo> files)
{
var (itemType, fileName) = files.FirstOrDefault(t => t.itemType == "ApplicationIcon");
var (itemType, fileName) = files.FirstOrDefault(t => t.ItemType == "ApplicationIcon");
if (fileName != null)
xml.WriteElementString("ApplicationIcon", fileName);
(itemType, fileName) = files.FirstOrDefault(t => t.itemType == "ApplicationManifest");
(itemType, fileName) = files.FirstOrDefault(t => t.ItemType == "ApplicationManifest");
if (fileName != null)
xml.WriteElementString("ApplicationManifest", fileName);
if (files.Any(t => t.itemType == "EmbeddedResource"))
if (files.Any(t => t.ItemType == "EmbeddedResource"))
xml.WriteElementString("RootNamespace", string.Empty);
// TODO: We should add CustomToolNamespace for resources, otherwise we should add empty RootNamespace
}
static void WriteResources(XmlTextWriter xml, IEnumerable<(string itemType, string fileName)> files)
static void WriteResources(XmlTextWriter xml, IEnumerable<ProjectItemInfo> files)
{
// remove phase
foreach (var (itemType, fileName) in files.Where(t => t.itemType == "EmbeddedResource"))
foreach (var item in files.Where(t => t.ItemType == "EmbeddedResource"))
{
string buildAction = Path.GetExtension(fileName).ToUpperInvariant() switch {
string buildAction = Path.GetExtension(item.FileName).ToUpperInvariant() switch {
".CS" => "Compile",
".RESX" => "EmbeddedResource",
_ => "None"
@ -217,18 +217,23 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -217,18 +217,23 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
continue;
xml.WriteStartElement(buildAction);
xml.WriteAttributeString("Remove", fileName);
xml.WriteAttributeString("Remove", item.FileName);
xml.WriteEndElement();
}
// include phase
foreach (var (itemType, fileName) in files.Where(t => t.itemType == "EmbeddedResource"))
foreach (var item in files.Where(t => t.ItemType == "EmbeddedResource"))
{
if (Path.GetExtension(fileName) == ".resx")
if (Path.GetExtension(item.FileName) == ".resx")
continue;
xml.WriteStartElement("EmbeddedResource");
xml.WriteAttributeString("Include", fileName);
xml.WriteAttributeString("Include", item.FileName);
if (item.AdditionalProperties != null)
{
foreach (var (key, value) in item.AdditionalProperties)
xml.WriteAttributeString(key, value);
}
xml.WriteEndElement();
}
}

187
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax; @@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
@ -150,8 +151,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -150,8 +151,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
TargetDirectory = targetDirectory;
directories.Clear();
var resources = WriteResourceFilesInProject(moduleDefinition).ToList();
var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.partialTypes ?? Enumerable.Empty<PartialTypeInfo>()).ToList(), cancellationToken).ToList();
files.AddRange(resources.Select(r => (r.itemType, r.fileName)));
var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty<PartialTypeInfo>()).ToList(), cancellationToken).ToList();
files.AddRange(resources);
files.AddRange(WriteMiscellaneousFilesInProject(moduleDefinition));
if (StrongNameKeyFile != null)
{
@ -169,9 +170,13 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -169,9 +170,13 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
var metadata = module.Metadata;
var typeDef = metadata.GetTypeDefinition(type);
if (metadata.GetString(typeDef.Name) == "<Module>" || CSharpDecompiler.MemberIsHidden(module, type, Settings))
string name = metadata.GetString(typeDef.Name);
string ns = metadata.GetString(typeDef.Namespace);
if (name == "<Module>" || CSharpDecompiler.MemberIsHidden(module, type, Settings))
return false;
if (metadata.GetString(typeDef.Namespace) == "XamlGeneratedNamespace" && metadata.GetString(typeDef.Name) == "GeneratedInternalTypeHelper")
if (ns == "XamlGeneratedNamespace" && name == "GeneratedInternalTypeHelper")
return false;
if (!typeDef.IsNested && RemoveEmbeddedAttributes.attributeNames.Contains(ns + "." + name))
return false;
return true;
}
@ -185,7 +190,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -185,7 +190,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
return decompiler;
}
IEnumerable<(string itemType, string fileName)> WriteAssemblyInfo(DecompilerTypeSystem ts, CancellationToken cancellationToken)
IEnumerable<ProjectItemInfo> WriteAssemblyInfo(DecompilerTypeSystem ts, CancellationToken cancellationToken)
{
var decompiler = CreateDecompiler(ts);
decompiler.CancellationToken = cancellationToken;
@ -200,43 +205,63 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -200,43 +205,63 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
return new[] { ("Compile", assemblyInfo) };
return new[] { new ProjectItemInfo("Compile", assemblyInfo) };
}
IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
IEnumerable<ProjectItemInfo> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
{
var metadata = module.Metadata;
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy(
delegate (TypeDefinitionHandle h) {
var type = metadata.GetTypeDefinition(h);
string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs";
string ns = metadata.GetString(type.Namespace);
if (string.IsNullOrEmpty(ns))
{
return file;
}
else
{
string dir = Settings.UseNestedDirectoriesForNamespaces ? CleanUpPath(ns) : CleanUpDirectoryName(ns);
if (directories.Add(dir))
Directory.CreateDirectory(Path.Combine(TargetDirectory, dir));
return Path.Combine(dir, file);
}
}, StringComparer.OrdinalIgnoreCase).ToList();
int total = files.Count;
var progress = ProgressIndicator;
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td))
.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList();
var progressReporter = ProgressIndicator;
var progress = new DecompilationProgress { TotalUnits = files.Count, Title = "Exporting project..." };
DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings);
Parallel.ForEach(
Partitioner.Create(files, loadBalance: true),
new ParallelOptions {
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
CancellationToken = cancellationToken
},
delegate (IGrouping<string, TypeDefinitionHandle> file) {
using (StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key)))
{
var workList = new HashSet<TypeDefinitionHandle>();
var processedTypes = new HashSet<TypeDefinitionHandle>();
ProcessFiles(files);
while (workList.Count > 0)
{
var additionalFiles = workList
.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList();
workList.Clear();
ProcessFiles(additionalFiles);
files.AddRange(additionalFiles);
progress.TotalUnits = files.Count;
}
return files.Select(f => new ProjectItemInfo("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
string GetFileFileNameForHandle(TypeDefinitionHandle h)
{
var type = metadata.GetTypeDefinition(h);
string file = SanitizeFileName(metadata.GetString(type.Name) + ".cs");
string ns = metadata.GetString(type.Namespace);
if (string.IsNullOrEmpty(ns))
{
return file;
}
else
{
string dir = Settings.UseNestedDirectoriesForNamespaces ? CleanUpPath(ns) : CleanUpDirectoryName(ns);
if (directories.Add(dir))
Directory.CreateDirectory(Path.Combine(TargetDirectory, dir));
return Path.Combine(dir, file);
}
}
void ProcessFiles(List<IGrouping<string, TypeDefinitionHandle>> files)
{
processedTypes.AddRange(files.SelectMany(f => f));
Parallel.ForEach(
Partitioner.Create(files, loadBalance: true),
new ParallelOptions {
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
CancellationToken = cancellationToken
},
delegate (IGrouping<string, TypeDefinitionHandle> file) {
try
{
using StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key));
CSharpDecompiler decompiler = CreateDecompiler(ts);
foreach (var partialType in partialTypes)
@ -245,22 +270,43 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -245,22 +270,43 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
decompiler.CancellationToken = cancellationToken;
var syntaxTree = decompiler.DecompileTypes(file.ToArray());
var declaredTypes = file.ToArray();
var syntaxTree = decompiler.DecompileTypes(declaredTypes);
foreach (var node in syntaxTree.Descendants)
{
var td = (node.GetResolveResult() as TypeResolveResult)?.Type.GetDefinition();
if (td?.ParentModule != ts.MainModule)
continue;
while (td?.DeclaringTypeDefinition != null)
{
td = td.DeclaringTypeDefinition;
}
if (td != null && td.MetadataToken is { IsNil: false } token && !processedTypes.Contains((TypeDefinitionHandle)token))
{
lock (workList)
{
workList.Add((TypeDefinitionHandle)token);
}
}
}
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))
{
throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException);
}
}
progress?.Report(new DecompilationProgress(total, file.Key));
});
return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
progress.Status = file.Key;
Interlocked.Increment(ref progress.UnitsCompleted);
progressReporter?.Report(progress);
});
}
}
#endregion
#region WriteResourceFilesInProject
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceFilesInProject(Metadata.PEFile module)
protected virtual IEnumerable<ProjectItemInfo> WriteResourceFilesInProject(Metadata.PEFile module)
{
foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded))
{
@ -270,7 +316,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -270,7 +316,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
bool decodedIntoIndividualFiles;
var individualResources = new List<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)>();
var individualResources = new List<ProjectItemInfo>();
try
{
var resourcesFile = new ResourcesFile(stream);
@ -330,12 +376,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -330,12 +376,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
stream.Position = 0;
stream.CopyTo(fs);
}
yield return ("EmbeddedResource", fileName, null);
yield return new ProjectItemInfo("EmbeddedResource", fileName).With("LogicalName", r.Name);
}
}
}
protected virtual IEnumerable<(string itemType, string fileName, List<PartialTypeInfo> partialTypes)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
protected virtual IEnumerable<ProjectItemInfo> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
if (fileName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
@ -350,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -350,7 +396,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
writer.AddResource(entry.Key, entry.Value);
}
}
return new[] { ("EmbeddedResource", resx, (List<PartialTypeInfo>)null) };
return new[] { new ProjectItemInfo("EmbeddedResource", resx).With("LogicalName", resourceName) };
}
catch (BadImageFormatException)
{
@ -365,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -365,7 +411,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
entryStream.CopyTo(fs);
}
return new[] { ("EmbeddedResource", fileName, (List<PartialTypeInfo>)null) };
return new[] { new ProjectItemInfo("EmbeddedResource", fileName).With("LogicalName", resourceName) };
}
string GetFileNameForResource(string fullName)
@ -378,7 +424,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -378,7 +424,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
// the directory part Namespace1\Namespace2\... reuses as many existing directories as
// possible, and only the remaining name parts are used as prefix for the filename.
// This is not affected by the UseNestedDirectoriesForNamespaces setting.
string[] splitName = fullName.Split(Path.DirectorySeparatorChar);
string[] splitName = fullName.Split('\\', '/');
string fileName = string.Join(".", splitName);
string separator = Path.DirectorySeparatorChar.ToString();
for (int i = splitName.Length - 1; i > 0; i--)
@ -396,7 +442,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -396,7 +442,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#endregion
#region WriteMiscellaneousFilesInProject
protected virtual IEnumerable<(string itemType, string fileName)> WriteMiscellaneousFilesInProject(PEFile module)
protected virtual IEnumerable<ProjectItemInfo> WriteMiscellaneousFilesInProject(PEFile module)
{
var resources = module.Reader.ReadWin32Resources();
if (resources == null)
@ -406,21 +452,21 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -406,21 +452,21 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (appIcon != null)
{
File.WriteAllBytes(Path.Combine(TargetDirectory, "app.ico"), appIcon);
yield return ("ApplicationIcon", "app.ico");
yield return new ProjectItemInfo("ApplicationIcon", "app.ico");
}
byte[] appManifest = CreateApplicationManifest(resources);
if (appManifest != null && !IsDefaultApplicationManifest(appManifest))
{
File.WriteAllBytes(Path.Combine(TargetDirectory, "app.manifest"), appManifest);
yield return ("ApplicationManifest", "app.manifest");
yield return new ProjectItemInfo("ApplicationManifest", "app.manifest");
}
var appConfig = module.FileName + ".config";
if (File.Exists(appConfig))
{
File.Copy(appConfig, Path.Combine(TargetDirectory, "app.config"), overwrite: true);
yield return ("ApplicationConfig", Path.GetFileName(appConfig));
yield return new ProjectItemInfo("ApplicationConfig", Path.GetFileName(appConfig));
}
}
@ -570,10 +616,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -570,10 +616,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName)
{
// Remove anything that could be confused with a rooted path.
int pos = text.IndexOf(':');
if (pos > 0)
text = text.Substring(0, pos);
pos = text.IndexOf('`');
if (pos > 0)
text = text.Substring(0, pos);
text = text.Trim();
@ -604,6 +648,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -604,6 +648,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
}
// Remove generics
pos = text.IndexOf('`');
if (pos > 0)
{
text = text.Substring(0, pos).Trim();
}
// Whitelist allowed characters, replace everything else:
StringBuilder b = new StringBuilder(text.Length + (extension?.Length ?? 0));
foreach (var c in text)
@ -645,7 +695,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -645,7 +695,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
b.Append('-');
string name = b.ToString();
if (extension != null)
{
// make sure that adding the extension to the filename
// does not exceed maxSegmentLength.
// trim the name, if necessary.
if (name.Length + extension.Length > maxSegmentLength)
name = name.Remove(name.Length - extension.Length);
name += extension;
}
if (IsReservedFileSystemName(name))
return name + "_";
else if (name == ".")
@ -706,15 +764,24 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -706,15 +764,24 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
}
public readonly struct DecompilationProgress
public record struct ProjectItemInfo(string ItemType, string FileName)
{
public readonly int TotalNumberOfFiles;
public readonly string Status;
public List<PartialTypeInfo> PartialTypes { get; set; } = null;
public Dictionary<string, string> AdditionalProperties { get; set; } = null;
public ProjectItemInfo With(string name, string value)
{
AdditionalProperties ??= new Dictionary<string, string>();
AdditionalProperties.Add(name, value);
return this;
}
public DecompilationProgress(int total, string status = null)
public ProjectItemInfo With(IEnumerable<KeyValuePair<string, string>> pairs)
{
this.TotalNumberOfFiles = total;
this.Status = status ?? "";
AdditionalProperties ??= new Dictionary<string, string>();
AdditionalProperties.AddRange(pairs);
return this;
}
}
}

26
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -53,8 +53,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -53,8 +53,8 @@ namespace ICSharpCode.Decompiler.CSharp
this.settings = settings;
this.cancellationToken = cancellationToken;
this.baseClass = recordTypeDef.DirectBaseTypes.FirstOrDefault(b => b.Kind == TypeKind.Class);
this.isStruct = baseClass.IsKnownType(KnownTypeCode.ValueType);
this.isInheritedRecord = !isStruct && !baseClass.IsKnownType(KnownTypeCode.Object);
this.isStruct = baseClass?.IsKnownType(KnownTypeCode.ValueType) ?? false;
this.isInheritedRecord = !isStruct && !(baseClass?.IsKnownType(KnownTypeCode.Object) ?? false);
this.isSealed = recordTypeDef.IsSealed;
DetectAutomaticProperties();
this.orderedMembers = DetectMemberOrder(recordTypeDef, backingFieldToAutoProperty);
@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.CSharp
// virtual bool Equals(R? other): generated unless user-declared
return IsGeneratedEquals(method);
}
else if (isInheritedRecord && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(paramType, baseClass) && method.IsOverride)
else if (isInheritedRecord && baseClass != null && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(paramType, baseClass) && method.IsOverride)
{
// override bool Equals(BaseClass? obj): always generated
return true;
@ -445,11 +445,23 @@ namespace ICSharpCode.Decompiler.CSharp @@ -445,11 +445,23 @@ namespace ICSharpCode.Decompiler.CSharp
var getter = property.Getter;
if (!(getter != null && !property.CanSet))
return false;
if (property.GetAttributes().Any())
return false;
var attrs = property.GetAttributes().ToList();
switch (attrs.Count)
{
case 0:
// Roslyn 3.x does not emit a CompilerGeneratedAttribute on the property itself.
break;
case 1:
// Roslyn 4.4 started doing so.
if (!attrs[0].AttributeType.IsKnownType(KnownAttribute.CompilerGenerated))
return false;
break;
default:
return false;
}
if (getter.GetReturnTypeAttributes().Any())
return false;
var attrs = getter.GetAttributes().ToList();
attrs = getter.GetAttributes().ToList();
if (attrs.Count != 1)
return false;
if (!attrs[0].AttributeType.IsKnownType(KnownAttribute.CompilerGenerated))
@ -760,7 +772,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -760,7 +772,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (!(conditions[pos] is Call { Method: { Name: "Equals" } } call))
return false;
if (!NormalizeTypeVisitor.TypeErasure.EquivalentTypes(call.Method.DeclaringType, baseClass))
if (baseClass != null && !NormalizeTypeVisitor.TypeErasure.EquivalentTypes(call.Method.DeclaringType, baseClass))
return false;
if (call.Arguments.Count != 2)
return false;

2
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -137,11 +137,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -137,11 +137,13 @@ namespace ICSharpCode.Decompiler.CSharp
break;
case IProperty property:
HandleAttributes(property.GetAttributes());
CollectNamespacesForTypeReference(property.ReturnType);
CollectNamespaces(property.Getter, module, mappingInfo);
CollectNamespaces(property.Setter, module, mappingInfo);
break;
case IEvent @event:
HandleAttributes(@event.GetAttributes());
CollectNamespacesForTypeReference(@event.ReturnType);
CollectNamespaces(@event.AddAccessor, module, mappingInfo);
CollectNamespaces(@event.RemoveAccessor, module, mappingInfo);
break;

21
ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs

@ -674,6 +674,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -674,6 +674,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
}
OperatorMethod[]? unsignedShiftRightOperators;
public OperatorMethod[] UnsignedShiftRightOperators {
get {
OperatorMethod[]? ops = LazyInit.VolatileRead(ref unsignedShiftRightOperators);
if (ops != null)
{
return ops;
}
else
{
return LazyInit.GetOrSet(ref unsignedShiftRightOperators, Lift(
new LambdaBinaryOperatorMethod<int, int>(this, (a, b) => (int)((uint)a >> b)),
new LambdaBinaryOperatorMethod<uint, int>(this, (a, b) => a >> b),
new LambdaBinaryOperatorMethod<long, int>(this, (a, b) => (long)((ulong)a >> b)),
new LambdaBinaryOperatorMethod<ulong, int>(this, (a, b) => a >> b)
));
}
}
}
#endregion
#region Equality operators

18
ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs

@ -685,7 +685,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -685,7 +685,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
{
isNullable = true;
}
if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight)
if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight || op == BinaryOperatorType.UnsignedShiftRight)
{
// special case: the shift operators allow "var x = null << null", producing int?.
if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null)
@ -805,6 +805,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -805,6 +805,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
case BinaryOperatorType.ShiftRight:
methodGroup = operators.ShiftRightOperators;
break;
case BinaryOperatorType.UnsignedShiftRight:
methodGroup = operators.UnsignedShiftRightOperators;
break;
case BinaryOperatorType.Equality:
case BinaryOperatorType.InEquality:
case BinaryOperatorType.LessThan:
@ -1223,14 +1226,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1223,14 +1226,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
ResolveResult rr = ResolveCast(targetType, expression);
if (rr.IsError)
return rr;
Debug.Assert(rr.IsCompileTimeConstant);
return new ConstantResolveResult(nullableType, rr.ConstantValue);
}
else
{
return Convert(expression, nullableType,
isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion);
if (rr.IsCompileTimeConstant)
return new ConstantResolveResult(nullableType, rr.ConstantValue);
}
return Convert(expression, nullableType,
isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion);
}
#endregion
@ -1259,6 +1259,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1259,6 +1259,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return "op_LeftShift";
case BinaryOperatorType.ShiftRight:
return "op_RightShift";
case BinaryOperatorType.UnsignedShiftRight:
return "op_UnsignedRightShift";
case BinaryOperatorType.Equality:
return "op_Equality";
case BinaryOperatorType.InEquality:

6
ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolutionErrors.cs

@ -82,6 +82,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -82,6 +82,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
/// <remarks>
/// This error does not prevent a candidate from being applicable.
/// </remarks>
MethodConstraintsNotSatisfied = 0x0800
MethodConstraintsNotSatisfied = 0x0800,
/// <summary>
/// Using 'out var' instead of 'out T' would result in loss of type information.
/// </summary>
OutVarTypeMismatch = 0x1000,
}
}

53
ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs

@ -66,8 +66,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -66,8 +66,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Modifiers.Public, Modifiers.Private, Modifiers.Protected, Modifiers.Internal,
Modifiers.New,
Modifiers.Unsafe,
Modifiers.Abstract, Modifiers.Virtual, Modifiers.Sealed, Modifiers.Static, Modifiers.Override,
Modifiers.Readonly, Modifiers.Volatile,
Modifiers.Static, Modifiers.Abstract, Modifiers.Virtual, Modifiers.Sealed, Modifiers.Override,
Modifiers.Required, Modifiers.Readonly, Modifiers.Volatile,
Modifiers.Ref,
Modifiers.Extern, Modifiers.Partial, Modifiers.Const,
Modifiers.Async,
@ -119,6 +119,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -119,6 +119,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return "async";
case Modifiers.Ref:
return "ref";
case Modifiers.Required:
return "required";
case Modifiers.Any:
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return "any";
@ -129,50 +131,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -129,50 +131,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static int GetModifierLength(Modifiers modifier)
{
switch (modifier)
{
case Modifiers.Private:
return "private".Length;
case Modifiers.Internal:
return "internal".Length;
case Modifiers.Protected:
return "protected".Length;
case Modifiers.Public:
return "public".Length;
case Modifiers.Abstract:
return "abstract".Length;
case Modifiers.Virtual:
return "virtual".Length;
case Modifiers.Sealed:
return "sealed".Length;
case Modifiers.Static:
return "static".Length;
case Modifiers.Override:
return "override".Length;
case Modifiers.Readonly:
return "readonly".Length;
case Modifiers.Const:
return "const".Length;
case Modifiers.New:
return "new".Length;
case Modifiers.Partial:
return "partial".Length;
case Modifiers.Extern:
return "extern".Length;
case Modifiers.Volatile:
return "volatile".Length;
case Modifiers.Unsafe:
return "unsafe".Length;
case Modifiers.Async:
return "async".Length;
case Modifiers.Ref:
return "ref".Length;
case Modifiers.Any:
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return "any".Length;
default:
throw new NotSupportedException("Invalid value for Modifiers");
}
return GetModifierName(modifier).Length;
}
public static Modifiers GetModifierValue(string modifier)
@ -215,6 +174,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -215,6 +174,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return Modifiers.Async;
case "ref":
return Modifiers.Ref;
case "required":
return Modifiers.Required;
case "any":
// even though it's used for pattern matching only, 'any' needs to be in this list to be usable in the AST
return Modifiers.Any;

9
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs

@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public readonly static TokenRole ModulusRole = new TokenRole("%=");
public readonly static TokenRole ShiftLeftRole = new TokenRole("<<=");
public readonly static TokenRole ShiftRightRole = new TokenRole(">>=");
public readonly static TokenRole UnsignedShiftRightRole = new TokenRole(">>>=");
public readonly static TokenRole BitwiseAndRole = new TokenRole("&=");
public readonly static TokenRole BitwiseOrRole = new TokenRole("|=");
public readonly static TokenRole ExclusiveOrRole = new TokenRole("^=");
@ -129,6 +130,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -129,6 +130,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return ShiftLeftRole;
case AssignmentOperatorType.ShiftRight:
return ShiftRightRole;
case AssignmentOperatorType.UnsignedShiftRight:
return UnsignedShiftRightRole;
case AssignmentOperatorType.BitwiseAnd:
return BitwiseAndRole;
case AssignmentOperatorType.BitwiseOr:
@ -164,6 +167,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -164,6 +167,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return BinaryOperatorType.ShiftLeft;
case AssignmentOperatorType.ShiftRight:
return BinaryOperatorType.ShiftRight;
case AssignmentOperatorType.UnsignedShiftRight:
return BinaryOperatorType.UnsignedShiftRight;
case AssignmentOperatorType.BitwiseAnd:
return BinaryOperatorType.BitwiseAnd;
case AssignmentOperatorType.BitwiseOr:
@ -195,6 +200,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -195,6 +200,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return ExpressionType.LeftShiftAssign;
case AssignmentOperatorType.ShiftRight:
return ExpressionType.RightShiftAssign;
case AssignmentOperatorType.UnsignedShiftRight:
return ExpressionType.Extension;
case AssignmentOperatorType.BitwiseAnd:
return ExpressionType.AndAssign;
case AssignmentOperatorType.BitwiseOr:
@ -259,6 +266,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -259,6 +266,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
ShiftLeft,
/// <summary>left >>= right</summary>
ShiftRight,
/// <summary>left >>>= right</summary>
UnsignedShiftRight,
/// <summary>left &amp;= right</summary>
BitwiseAnd,

6
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs

@ -52,6 +52,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -52,6 +52,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public readonly static TokenRole ModulusRole = new TokenRole("%");
public readonly static TokenRole ShiftLeftRole = new TokenRole("<<");
public readonly static TokenRole ShiftRightRole = new TokenRole(">>");
public readonly static TokenRole UnsignedShiftRightRole = new TokenRole(">>>");
public readonly static TokenRole NullCoalescingRole = new TokenRole("??");
public readonly static TokenRole RangeRole = new TokenRole("..");
public readonly static TokenRole IsKeywordRole = IsExpression.IsKeywordRole;
@ -151,6 +152,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -151,6 +152,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return ShiftLeftRole;
case BinaryOperatorType.ShiftRight:
return ShiftRightRole;
case BinaryOperatorType.UnsignedShiftRight:
return UnsignedShiftRightRole;
case BinaryOperatorType.NullCoalescing:
return NullCoalescingRole;
case BinaryOperatorType.Range:
@ -205,6 +208,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -205,6 +208,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case BinaryOperatorType.NullCoalescing:
return ExpressionType.Coalesce;
case BinaryOperatorType.Range:
case BinaryOperatorType.UnsignedShiftRight:
return ExpressionType.Extension;
default:
throw new NotSupportedException("Invalid value for BinaryOperatorType");
@ -262,6 +266,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -262,6 +266,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
ShiftLeft,
/// <summary>left &gt;&gt; right</summary>
ShiftRight,
/// <summary>left &gt;&gt;&gt; right</summary>
UnsignedShiftRight,
/// <summary>left ?? right</summary>
NullCoalescing,

1
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
StringLiteral,
VerbatimStringLiteral,
CharLiteral,
Utf8Literal,
}
/// <summary>

1
ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs

@ -55,6 +55,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -55,6 +55,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Unsafe = 0x8000,
Async = 0x10000,
Ref = 0x20000,
Required = 0x40000,
VisibilityMask = Private | Internal | Protected | Public,

5
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs

@ -57,6 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -57,6 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
ExclusiveOr,
LeftShift,
RightShift,
UnsignedRightShift,
Equality,
Inequality,
GreaterThan,
@ -94,6 +95,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -94,6 +95,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole ExclusiveOrRole = new TokenRole("^");
public static readonly TokenRole LeftShiftRole = new TokenRole("<<");
public static readonly TokenRole RightShiftRole = new TokenRole(">>");
public static readonly TokenRole UnsignedRightShiftRole = new TokenRole(">>>");
public static readonly TokenRole EqualityRole = new TokenRole("==");
public static readonly TokenRole InequalityRole = new TokenRole("!=");
public static readonly TokenRole GreaterThanRole = new TokenRole(">");
@ -127,6 +129,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -127,6 +129,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
names[(int)OperatorType.ExclusiveOr] = new string[] { "^", "op_ExclusiveOr" };
names[(int)OperatorType.LeftShift] = new string[] { "<<", "op_LeftShift" };
names[(int)OperatorType.RightShift] = new string[] { ">>", "op_RightShift" };
names[(int)OperatorType.UnsignedRightShift] = new string[] { ">>>", "op_UnsignedRightShift" };
names[(int)OperatorType.Equality] = new string[] { "==", "op_Equality" };
names[(int)OperatorType.Inequality] = new string[] { "!=", "op_Inequality" };
names[(int)OperatorType.GreaterThan] = new string[] { ">", "op_GreaterThan" };
@ -230,6 +233,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -230,6 +233,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return LeftShiftRole;
case OperatorType.RightShift:
return RightShiftRole;
case OperatorType.UnsignedRightShift:
return UnsignedRightShiftRole;
case OperatorType.Equality:
return EqualityRole;
case OperatorType.Inequality:

28
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs

@ -26,6 +26,8 @@ @@ -26,6 +26,8 @@
#nullable enable
using System;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public enum ParameterModifier
@ -42,10 +44,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -42,10 +44,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public static readonly Role<AttributeSection> AttributeRole = EntityDeclaration.AttributeRole;
public static readonly TokenRole ThisModifierRole = new TokenRole("this");
public static readonly TokenRole RefScopedRole = new TokenRole("scoped");
public static readonly TokenRole ScopedRefRole = new TokenRole("scoped");
[Obsolete("Renamed to ScopedRefRole")]
public static readonly TokenRole RefScopedRole = ScopedRefRole;
public static readonly TokenRole RefModifierRole = new TokenRole("ref");
public static readonly TokenRole OutModifierRole = new TokenRole("out");
public static readonly TokenRole InModifierRole = new TokenRole("in");
[Obsolete("C# 11 preview: \"ref scoped\" no longer supported")]
public static readonly TokenRole ValueScopedRole = new TokenRole("scoped");
public static readonly TokenRole ParamsModifierRole = new TokenRole("params");
@ -102,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -102,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
bool hasThisModifier;
bool isRefScoped, isValueScoped;
bool isScopedRef;
public CSharpTokenNode ThisKeyword {
get {
@ -122,22 +127,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -122,22 +127,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public bool IsRefScoped {
get { return isRefScoped; }
public bool IsScopedRef {
get { return isScopedRef; }
set {
ThrowIfFrozen();
isRefScoped = value;
isScopedRef = value;
}
}
public bool IsValueScoped {
get { return isValueScoped; }
[Obsolete("Renamed to IsScopedRef")]
public bool IsRefScoped {
get { return isScopedRef; }
set {
ThrowIfFrozen();
isValueScoped = value;
isScopedRef = value;
}
}
[Obsolete("C# 11 preview: \"ref scoped\" no longer supported")]
public bool IsValueScoped {
get { return false; }
set { }
}
ParameterModifier parameterModifier;
public ParameterModifier ParameterModifier {

16
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -225,6 +225,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -225,6 +225,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </summary>
public bool SupportRecordStructs { get; set; }
/// <summary>
/// Controls whether C# 11 "operator >>>" is supported.
/// </summary>
public bool SupportUnsignedRightShift { get; set; }
/// <summary>
/// Controls whether all fully qualified type names should be prefixed with "global::".
/// </summary>
@ -1654,8 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1654,8 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
decl.ParameterModifier = ParameterModifier.Params;
}
decl.IsRefScoped = parameter.Lifetime.RefScoped;
decl.IsValueScoped = parameter.Lifetime.ValueScoped;
decl.IsScopedRef = parameter.Lifetime.ScopedRef;
if (ShowAttributes)
{
decl.Attributes.AddRange(ConvertAttributes(parameter.GetAttributes()));
@ -1675,7 +1679,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1675,7 +1679,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
decl.Name = parameter.Name;
}
if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues)
if (parameter.IsOptional && decl.ParameterModifier is ParameterModifier.None or ParameterModifier.In && parameter.HasConstantValueInSignature && this.ShowConstantValues)
{
try
{
@ -1970,6 +1974,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1970,6 +1974,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.AddAnnotation(new MemberResolveResult(null, field));
}
decl.ReturnType = ConvertType(field.ReturnType);
if (decl.ReturnType is ComposedType ct && ct.HasRefSpecifier && field.ReturnTypeIsRefReadOnly)
{
ct.HasReadOnlySpecifier = true;
}
Expression initializer = null;
if (field.IsConst && this.ShowConstantValues)
{
@ -2214,6 +2222,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2214,6 +2222,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
OperatorType? opType = OperatorDeclaration.GetOperatorType(op.Name);
if (opType == null)
return ConvertMethod(op);
if (opType == OperatorType.UnsignedRightShift && !SupportUnsignedRightShift)
return ConvertMethod(op);
OperatorDeclaration decl = new OperatorDeclaration();
decl.Modifiers = GetMemberModifiers(op);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save