Browse Source

Merge 75b099f5b6 into 0bfe222cf4

pull/3500/merge
Siegfried Pammer 17 hours ago committed by GitHub
parent
commit
2b558bd0cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .github/workflows/build-frontends.yml
  2. 20
      .github/workflows/build-ilspy.yml
  3. 6
      .github/workflows/codeql-analysis.yml
  4. 1
      .gitmodules
  5. 4
      BuildTools/pre-commit
  6. 6
      ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj
  7. 2
      ICSharpCode.BamlDecompiler/packages.lock.json
  8. 2
      ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
  9. 103
      ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs
  10. 24
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  11. 146
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  12. 6
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  13. 12
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  14. 4
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs
  15. 2
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.il
  16. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  17. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MetadataAttributes.cs
  18. 21
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs
  19. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  20. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs
  21. 4
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  22. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  23. 3
      ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs
  24. 79
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  25. 2
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  26. 129
      ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs
  27. 21
      ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs
  28. 1
      ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs
  29. 12
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  30. 24
      ICSharpCode.Decompiler/DecompilerSettings.cs
  31. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  32. 4
      ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs
  33. 2
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  34. 16
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  35. 5
      ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
  36. 15
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  37. 18
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  38. 13
      ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
  39. 2
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
  40. 6
      ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs
  41. 11
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  42. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  43. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  44. 18
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  45. 17
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  46. 4
      ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj
  47. 11
      ICSharpCode.ILSpyCmd/packages.lock.json
  48. 4
      ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
  49. 2
      ICSharpCode.ILSpyX/MermaidDiagrammer/html/.vscode/tasks.json
  50. 14
      ICSharpCode.ILSpyX/packages.lock.json
  51. 2
      ILSpy-tests
  52. 4
      ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj
  53. 2
      ILSpy.AddIn/ILSpy.AddIn.csproj
  54. 2
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
  55. 2
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  56. 2
      ILSpy.Installer/setup.cs
  57. 2
      ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
  58. 2
      ILSpy.Tests/ILSpy.Tests.csproj
  59. 1
      ILSpy.sln
  60. 2
      ILSpy/ILSpy.csproj
  61. 1
      ILSpy/Languages/CSharpLanguage.cs
  62. 9
      ILSpy/Properties/Resources.Designer.cs
  63. 3
      ILSpy/Properties/Resources.resx
  64. 3
      ILSpy/Properties/Resources.zh-Hans.resx
  65. 2
      TestPlugin/TestPlugin.csproj
  66. 2
      global.json
  67. 6
      publish.ps1
  68. 4
      publishlocaldev.ps1

6
.github/workflows/build-frontends.yml

@ -21,11 +21,11 @@ jobs: @@ -21,11 +21,11 @@ jobs:
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-quality: 'ga'
dotnet-version: '10.0.x'
dotnet-quality: 'preview'
- name: Install dependencies
run: dotnet restore ILSpy.XPlat.slnf
run: dotnet restore ILSpy.XPlat.slnf -p:RestoreEnablePackagePruning=false
- name: Build Debug
run: dotnet msbuild ILSpy.XPlat.slnf -p:Configuration=Debug -bl:Debug.binlog

20
.github/workflows/build-ilspy.yml

@ -34,8 +34,8 @@ jobs: @@ -34,8 +34,8 @@ jobs:
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-quality: 'ga'
dotnet-version: '10.0.x'
dotnet-quality: 'preview'
env:
DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet
DOTNET_ROOT: ${{ runner.temp }}/.dotnet
@ -44,7 +44,7 @@ jobs: @@ -44,7 +44,7 @@ jobs:
uses: microsoft/setup-msbuild@v2
- name: Install dotnet-format
run: dotnet tool install -g dotnet-format --version "8.3.546805" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json
run: dotnet tool install -g dotnet-format --version "9.0.520307" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json
- name: Install wix (locked version)
run: dotnet tool install --global wix --version 6.0.0
@ -57,7 +57,7 @@ jobs: @@ -57,7 +57,7 @@ jobs:
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
run: msbuild ILSpy.sln /t:Restore /p:RestoreEnablePackagePruning=false /p:Configuration=${{ matrix.configuration }} /p:Platform=$env:BuildPlatform
- name: Build
run: msbuild ILSpy.sln /p:Configuration=${{ matrix.configuration }} /p:Platform=$env:BuildPlatform /m
@ -65,9 +65,9 @@ jobs: @@ -65,9 +65,9 @@ jobs:
- name: Execute unit tests
run: dotnet test --logger "trx;LogFileName=${{ matrix.configuration }}.trx" --results-directory test-results $env:Tests1 $env:Tests2 $env:Tests3
env:
Tests1: ICSharpCode.Decompiler.Tests\bin\${{ matrix.configuration }}\net8.0-windows\win-x64\ICSharpCode.Decompiler.Tests.dll
Tests2: ILSpy.Tests\bin\${{ matrix.configuration }}\net8.0-windows\ILSpy.Tests.dll
Tests3: ILSpy.BamlDecompiler.Tests\bin\${{ matrix.configuration }}\net8.0-windows\win-x64\ILSpy.BamlDecompiler.Tests.dll
Tests1: ICSharpCode.Decompiler.Tests\bin\${{ matrix.configuration }}\net10.0-windows\win-x64\ICSharpCode.Decompiler.Tests.dll
Tests2: ILSpy.Tests\bin\${{ matrix.configuration }}\net10.0-windows\ILSpy.Tests.dll
Tests3: ILSpy.BamlDecompiler.Tests\bin\${{ matrix.configuration }}\net10.0-windows\win-x64\ILSpy.BamlDecompiler.Tests.dll
- name: Upload Test Logs
uses: actions/upload-artifact@v4
@ -94,7 +94,7 @@ jobs: @@ -94,7 +94,7 @@ jobs:
git diff --exit-code
- name: Zip ILSpy (framework-dependent)
run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries.zip .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.dll .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.exe .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.config .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*.json .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*\ILSpy.resources.dll .\ILSpy\bin\${{ matrix.configuration }}\net8.0-windows\*\ILSpy.ReadyToRun.Plugin.resources.dll
run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries.zip .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*.dll .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*.exe .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*.config .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*.json .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*\ILSpy.resources.dll .\ILSpy\bin\${{ matrix.configuration }}\net10.0-windows\*\ILSpy.ReadyToRun.Plugin.resources.dll
- name: Publish x64/arm64 framework-dependent/self-contained
shell: pwsh
@ -102,11 +102,11 @@ jobs: @@ -102,11 +102,11 @@ jobs:
- name: Zip ILSpy Release (x64 self-contained)
if: matrix.configuration == 'release'
run: 7z a -tzip $env:StagingDirectory\ILSpy_selfcontained_x64.zip .\ILSpy\bin\Release\net8.0-windows\win-x64\publish\selfcontained\*
run: 7z a -tzip $env:StagingDirectory\ILSpy_selfcontained_x64.zip .\ILSpy\bin\Release\net10.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\net8.0-windows\win-arm64\publish\fwdependent\*
run: 7z a -tzip $env:StagingDirectory\ILSpy_binaries_arm64.zip .\ILSpy\bin\Release\net10.0-windows\win-arm64\publish\fwdependent\*
- name: Pack NuGets
if: matrix.configuration == 'release'

6
.github/workflows/codeql-analysis.yml

@ -37,11 +37,11 @@ jobs: @@ -37,11 +37,11 @@ jobs:
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-quality: 'ga'
dotnet-version: '10.0.x'
dotnet-quality: 'preview'
- name: Build
run: dotnet build ILSpy.XPlat.slnf --configuration Release
run: dotnet build ILSpy.XPlat.slnf --configuration Release -p:RestoreEnablePackagePruning=false
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

1
.gitmodules vendored

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
[submodule "ILSpy-tests"]
path = ILSpy-tests
url = https://github.com/icsharpcode/ILSpy-tests
branch = master

4
BuildTools/pre-commit

@ -5,11 +5,11 @@ @@ -5,11 +5,11 @@
set -eu
DOTNET_FORMAT_VERSION=8.3.546805
DOTNET_FORMAT_VERSION=9.0.520307
DOTNET_PATH="$LOCALAPPDATA/ICSharpCode/ILSpy/dotnet-format-$DOTNET_FORMAT_VERSION"
if [ ! -d "$DOTNET_PATH" ]; then
echo "Downloading dotnet-format $DOTNET_FORMAT_VERSION..."
dotnet tool install --tool-path "$DOTNET_PATH" dotnet-format --version "$DOTNET_FORMAT_VERSION" --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json"
dotnet tool install --tool-path "$DOTNET_PATH" dotnet-format --version "$DOTNET_FORMAT_VERSION" --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json"
fi
"$DOTNET_PATH/dotnet-format.exe" --version

6
ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
<PropertyGroup>
<PackageId>ICSharpCode.BamlDecompiler</PackageId>
<PackageVersion>8.0.0.0-noversion</PackageVersion>
<PackageVersion>10.0.0.0-noversion</PackageVersion>
<Title>ILSpy BAML Decompiler</Title>
<Authors>ILSpy Contributors</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
<!-- https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/ -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(GITHUB_ACTIONS)' == 'true'">true</RestoreLockedMode>
<RestoreLockedMode>true</RestoreLockedMode>
</PropertyGroup>
<ItemGroup>

2
ICSharpCode.BamlDecompiler/packages.lock.json

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"net10.0": {
"Microsoft.Sbom.Targets": {
"type": "Direct",
"requested": "[3.1.0, )",

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

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>

103
ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs

@ -18,12 +18,13 @@ @@ -18,12 +18,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Metadata;
using NuGet.Common;
using NuGet.Packaging;
@ -31,6 +32,8 @@ using NuGet.Protocol; @@ -31,6 +32,8 @@ using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
abstract class AbstractToolset
@ -50,29 +53,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -50,29 +53,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
protected async Task FetchPackage(string packageName, string version, string sourcePath, string outputPath)
{
if (!Directory.Exists(Path.Combine(Roundtrip.RoundtripAssembly.TestDir, "nuget")))
Assert.Fail("No nuget cache found!");
ILogger logger = NullLogger.Instance;
CancellationToken cancellationToken = CancellationToken.None;
using MemoryStream packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
packageName,
NuGetVersion.Parse(version),
packageStream,
cache,
logger,
cancellationToken).ConfigureAwait(false);
using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream);
NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken).ConfigureAwait(false);
var files = (await packageReader.GetFilesAsync(cancellationToken).ConfigureAwait(false)).ToArray();
files = files.Where(f => f.StartsWith(sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray();
await packageReader.CopyFilesAsync(outputPath, files,
(sourceFile, targetPath, fileStream) => {
fileStream.CopyToFile(targetPath);
return targetPath;
},
logger, cancellationToken).ConfigureAwait(false);
string pathToPackage = Path.Combine(Roundtrip.RoundtripAssembly.TestDir, "nuget", $"{packageName}-{version}.nupkg");
Stream packageStream;
if (File.Exists(pathToPackage))
{
packageStream = File.OpenRead(pathToPackage);
}
else
{
packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
packageName,
NuGetVersion.Parse(version),
packageStream,
cache,
logger,
cancellationToken).ConfigureAwait(false);
packageStream.Position = 0;
}
using (packageStream)
{
using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream);
NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken).ConfigureAwait(false);
var files = (await packageReader.GetFilesAsync(cancellationToken).ConfigureAwait(false)).ToArray();
files = files.Where(f => f.StartsWith(sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray();
await packageReader.CopyFilesAsync(outputPath, files,
(sourceFile, targetPath, fileStream) => {
fileStream.CopyToFile(targetPath);
return targetPath;
},
logger, cancellationToken).ConfigureAwait(false);
}
}
}
@ -145,4 +164,44 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -145,4 +164,44 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public string GetVsWhere() => vswherePath;
}
class RefAssembliesToolset : AbstractToolset
{
readonly Dictionary<string, string> installedFrameworks = new Dictionary<string, string> {
{ "legacy", Path.Combine(Roundtrip.RoundtripAssembly.TestDir, "dotnet", "legacy") },
{ "2.2.0", Path.Combine(Roundtrip.RoundtripAssembly.TestDir, "dotnet", "netcore-2.2") },
};
public RefAssembliesToolset()
: base(Path.Combine(AppContext.BaseDirectory, "netfx"))
{
}
public async Task Fetch(string version, string packageName = "Microsoft.NETCore.App.Ref", string sourcePath = "ref/net5.0")
{
string path = Path.Combine(baseDir, version, sourcePath);
if (!Directory.Exists(path))
{
await FetchPackage(packageName, version, sourcePath, Path.Combine(baseDir, version)).ConfigureAwait(false);
}
installedFrameworks.Add(RoslynToolset.SanitizeVersion(version), path);
}
internal string GetPath(string targetFramework)
{
var (id, version) = UniversalAssemblyResolver.ParseTargetFramework(targetFramework);
string path;
if (id == TargetFrameworkIdentifier.NETFramework)
{
path = installedFrameworks["legacy"];
}
else
{
path = installedFrameworks[version.ToString(3)];
}
Debug.Assert(Path.Exists(path));
return path;
}
}
}

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

@ -16,12 +16,9 @@ @@ -16,12 +16,9 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@ -49,27 +46,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -49,27 +46,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
CompilerResults results = new CompilerResults();
results.PathToAssembly = outputFileName;
var (roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch {
0 => ("legacy", "11"),
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "14"),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
bool targetNet40 = (flags & CompilerOptions.TargetNet40) != 0;
var (roslynVersion, languageVersion, targetFramework) = (flags & CompilerOptions.UseRoslynMask) switch {
0 => ("legacy", "11", null),
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "14", null),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest", targetNet40 ? null : ".NETCoreApp,Version=v2.2"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest", targetNet40 ? null : ".NETCoreApp,Version=v5.0"),
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest", targetNet40 ? null : ".NETCoreApp,Version=v10.0")
};
var vbcPath = roslynToolset.GetVBCompiler(roslynVersion);
IEnumerable<string> references;
string libPath;
if ((flags & CompilerOptions.UseRoslynMask) != 0 && (flags & CompilerOptions.TargetNet40) == 0)
if ((flags & CompilerOptions.UseRoslynMask) != 0 && targetFramework != null)
{
var coreRefAsmPath = RefAssembliesToolset.GetPath(targetFramework);
references = coreDefaultReferences.Select(r => "-r:\"" + r + "\"");
libPath = coreRefAsmPath;
}
else
{
references = defaultReferences.Select(r => "-r:\"" + r + "\"");
libPath = RefAsmPath;
libPath = RefAssembliesToolset.GetPath("legacy");
}
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
@ -121,7 +121,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -121,7 +121,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var command = Cli.Wrap(vbcPath)
.WithArguments($"{otherOptions}-libpath:\"{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);

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

@ -99,15 +99,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -99,15 +99,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
static readonly string roslynLatestVersion;
static readonly RoslynToolset roslynToolset;
static readonly VsWhereToolset vswhereToolset;
internal static readonly RefAssembliesToolset RefAssembliesToolset;
static Tester()
{
TesterPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
TestCasePath = Path.Combine(TesterPath, "../../../../TestCases");
#if DEBUG
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net8.0");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net10.0");
#else
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net8.0");
testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net10.0");
#endif
// To parse: <Project><ItemGroup><PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0-3.final" />
packagesPropsFile = Path.Combine(TesterPath, "../../../../../Directory.Packages.props");
@ -120,6 +121,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -120,6 +121,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
roslynToolset = new RoslynToolset();
vswhereToolset = new VsWhereToolset();
RefAssembliesToolset = new RefAssembliesToolset();
}
internal static async Task Initialize()
@ -130,6 +132,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -130,6 +132,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
await roslynToolset.Fetch(roslynLatestVersion).ConfigureAwait(false);
await vswhereToolset.Fetch().ConfigureAwait(false);
await RefAssembliesToolset.Fetch("5.0.0", sourcePath: "ref/net5.0").ConfigureAwait(false);
await RefAssembliesToolset.Fetch("10.0.0-preview.4.25258.110", sourcePath: "ref/net10.0").ConfigureAwait(false);
#if DEBUG
await BuildTestRunner("win-x86", "Debug").ConfigureAwait(false);
@ -276,21 +281,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -276,21 +281,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return Regex.Replace(il, @"'<PrivateImplementationDetails>\{[0-9A-F-]+\}'", "'<PrivateImplementationDetails>'");
}
static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NET,
new Version(8, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v8.0");
public static readonly string RefAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
static readonly string[] defaultReferences = new[] {
"System.dll",
"System.Core.dll",
"System.Runtime.dll",
"System.Xml.dll",
"Microsoft.CSharp.dll"
};
static readonly string[] coreDefaultReferences = new[]
static readonly string[] core220DefaultReferences = new[]
{
"netstandard.dll",
"mscorlib.dll",
@ -303,9 +302,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -303,9 +302,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
"System.Linq.Queryable.dll",
"System.IO.FileSystem.Watcher.dll",
"System.Memory.dll",
"System.Private.CoreLib.dll",
"System.Private.Xml.dll",
"System.Threading.dll",
"System.Threading.Thread.dll",
"System.Runtime.dll",
"System.Runtime.Extensions.dll",
"System.Runtime.InteropServices.dll",
"System.Xml.dll",
"System.Xml.ReaderWriter.dll",
@ -314,19 +316,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -314,19 +316,45 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
"Microsoft.VisualBasic.dll",
};
const string targetFrameworkAttributeSnippet = @"
[assembly: System.Runtime.Versioning.TargetFramework("".NETCoreApp,Version=v8.0"", FrameworkDisplayName = """")]
";
static readonly string[] coreDefaultReferences = new[]
{
"netstandard.dll",
"mscorlib.dll",
"System.dll",
"System.Collections.dll",
"System.Console.dll",
"System.Core.dll",
"System.Linq.dll",
"System.Linq.Expressions.dll",
"System.Linq.Queryable.dll",
"System.IO.FileSystem.Watcher.dll",
"System.Memory.dll",
"System.Threading.dll",
"System.Threading.Thread.dll",
"System.Runtime.dll",
"System.Runtime.InteropServices.dll",
"System.Xml.dll",
"System.Xml.ReaderWriter.dll",
"System.ValueTuple.dll",
"Microsoft.CSharp.dll",
"Microsoft.VisualBasic.dll",
};
static readonly Lazy<string> targetFrameworkAttributeSnippetFile = new Lazy<string>(GetTargetFrameworkAttributeSnippetFile);
static readonly Dictionary<string, Lazy<string>> targetFrameworkAttributeSnippetFiles = new() {
{ ".NETCoreApp,Version=v10.0", new Lazy<string>(() => GetTargetFrameworkAttributeSnippetFile(".NETCoreApp,Version=v10.0")) },
{ ".NETCoreApp,Version=v5.0", new Lazy<string>(() => GetTargetFrameworkAttributeSnippetFile(".NETCoreApp,Version=v5.0")) },
{ ".NETCoreApp,Version=v2.2", new Lazy<string>(() => GetTargetFrameworkAttributeSnippetFile(".NETCoreApp,Version=v2.2")) },
};
static string GetTargetFrameworkAttributeSnippetFile()
static string GetTargetFrameworkAttributeSnippetFile(string targetFrameworkMoniker)
{
// Note: this leaks a temporary file, we're not attempting to delete it, because it is only one.
var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, targetFrameworkAttributeSnippet);
File.WriteAllText(tempFile, $@"
[assembly: System.Runtime.Versioning.TargetFramework(""{targetFrameworkMoniker}"")]
");
return tempFile;
}
@ -389,9 +417,6 @@ namespace System.Runtime.CompilerServices @@ -389,9 +417,6 @@ namespace System.Runtime.CompilerServices
if (!flags.HasFlag(CompilerOptions.TargetNet40))
{
preprocessorSymbols.Add("NETCORE");
preprocessorSymbols.Add("NET60");
preprocessorSymbols.Add("NET70");
preprocessorSymbols.Add("NET80");
}
preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60");
@ -411,6 +436,10 @@ namespace System.Runtime.CompilerServices @@ -411,6 +436,10 @@ namespace System.Runtime.CompilerServices
if (flags.HasFlag(CompilerOptions.UseRoslyn3_11_0)
|| flags.HasFlag(CompilerOptions.UseRoslynLatest))
{
if (!flags.HasFlag(CompilerOptions.TargetNet40))
{
preprocessorSymbols.Add("NET50");
}
preprocessorSymbols.Add("ROSLYN3");
preprocessorSymbols.Add("CS80");
preprocessorSymbols.Add("CS90");
@ -418,10 +447,19 @@ namespace System.Runtime.CompilerServices @@ -418,10 +447,19 @@ namespace System.Runtime.CompilerServices
}
if (flags.HasFlag(CompilerOptions.UseRoslynLatest))
{
if (!flags.HasFlag(CompilerOptions.TargetNet40))
{
preprocessorSymbols.Add("NET60");
preprocessorSymbols.Add("NET70");
preprocessorSymbols.Add("NET80");
preprocessorSymbols.Add("NET90");
preprocessorSymbols.Add("NET100");
}
preprocessorSymbols.Add("ROSLYN4");
preprocessorSymbols.Add("CS100");
preprocessorSymbols.Add("CS110");
preprocessorSymbols.Add("CS120");
preprocessorSymbols.Add("CS130");
}
}
else if ((flags & CompilerOptions.UseMcsMask) != 0)
@ -453,10 +491,6 @@ namespace System.Runtime.CompilerServices @@ -453,10 +491,6 @@ namespace System.Runtime.CompilerServices
}
bool targetNet40 = (flags & CompilerOptions.TargetNet40) != 0;
bool useRoslyn = (flags & CompilerOptions.UseRoslynMask) != 0;
if (useRoslyn && !targetNet40)
{
sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
}
if (targetNet40)
{
@ -470,36 +504,58 @@ namespace System.Runtime.CompilerServices @@ -470,36 +504,58 @@ namespace System.Runtime.CompilerServices
CompilerResults results = new CompilerResults();
results.PathToAssembly = outputFileName;
var (roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch {
0 => ("legacy", "5"),
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6"),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
var (roslynVersion, languageVersion, targetFramework) = (flags & CompilerOptions.UseRoslynMask) switch {
0 => ("legacy", "5", null),
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6", null),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest", targetNet40 ? null : ".NETCoreApp,Version=v2.2"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest", targetNet40 ? null : ".NETCoreApp,Version=v5.0"),
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest", targetNet40 ? null : ".NETCoreApp,Version=v10.0")
};
var cscPath = roslynToolset.GetCSharpCompiler(roslynVersion);
string libPath;
string libPath, refAsmPath;
IEnumerable<string> references;
if (useRoslyn && !targetNet40)
if (useRoslyn && targetFramework != null)
{
libPath = "\"" + coreRefAsmPath + "\"";
references = coreDefaultReferences.Select(r => "-r:\"" + Path.Combine(coreRefAsmPath, r) + "\"");
refAsmPath = RefAssembliesToolset.GetPath(targetFramework);
if (targetFramework == ".NETCoreApp,Version=v2.2")
{
references = core220DefaultReferences;
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Append("Microsoft.VisualBasic.dll");
}
}
else
{
references = coreDefaultReferences;
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Append("Microsoft.VisualBasic.dll");
references = references.Append("Microsoft.VisualBasic.Core.dll");
}
}
libPath = "\"" + refAsmPath + "\"";
sourceFileNames.Add(targetFrameworkAttributeSnippetFiles[targetFramework].Value);
}
else
{
libPath = "\"" + RefAsmPath + "\",\"" + Path.Combine(RefAsmPath, "Facades") + "\"";
references = defaultReferences.Select(r => "-r:\"" + Path.Combine(RefAsmPath, r) + "\"");
}
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
refAsmPath = RefAssembliesToolset.GetPath("legacy");
libPath = "\"" + refAsmPath + "\"";
references = defaultReferences;
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
references = references.Append("Microsoft.VisualBasic.dll");
}
}
if (useRoslyn && !targetNet40 && flags.HasFlag(CompilerOptions.ReferenceUnsafe))
{
references = references.Concat(new[] { "-r:\"System.Runtime.CompilerServices.Unsafe.dll\"" });
references = references.Append("System.Runtime.CompilerServices.Unsafe.dll");
}
references = references.Select(r => "-r:\"" + Path.Combine(refAsmPath, r) + "\"");
string otherOptions = $"-nologo -noconfig " +
$"-langversion:{languageVersion} " +
$"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";
@ -650,7 +706,7 @@ namespace System.Runtime.CompilerServices @@ -650,7 +706,7 @@ namespace System.Runtime.CompilerServices
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.CSharp12_0,
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp13_0,
};
DecompilerSettings settings = new(langVersion) {
// Never use file-scoped namespaces
@ -685,7 +741,7 @@ namespace System.Runtime.CompilerServices @@ -685,7 +741,7 @@ namespace System.Runtime.CompilerServices
}
var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName),
syntaxTrees, coreDefaultReferences.Select(r => MetadataReference.CreateFromFile(Path.Combine(coreRefAsmPath, r))),
syntaxTrees, coreDefaultReferences.Select(r => MetadataReference.CreateFromFile(Path.Combine(RefAssembliesToolset.GetPath(".NETCoreApp,Version=v10.0"), r))),
new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
platform: Platform.AnyCpu,
@ -767,7 +823,7 @@ namespace System.Runtime.CompilerServices @@ -767,7 +823,7 @@ namespace System.Runtime.CompilerServices
string targetFramework = module.Metadata.DetectTargetFrameworkId();
var resolver = new UniversalAssemblyResolver(assemblyFileName, false,
targetFramework, null, PEStreamOptions.PrefetchMetadata);
resolver.AddSearchDirectory(targetFramework.Contains(".NETFramework") ? RefAsmPath : coreRefAsmPath);
resolver.AddSearchDirectory(RefAssembliesToolset.GetPath(targetFramework));
var typeSystem = new DecompilerTypeSystem(module, resolver, settings);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings);
decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAttributes());

6
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -7,7 +7,8 @@ @@ -7,7 +7,8 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<LangVersion>13</LangVersion>
<RuntimeIdentifier Condition="$(IsWindowsX64) == true">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="$(IsWindowsARM64) == true">win-arm64</RuntimeIdentifier>
@ -17,7 +18,7 @@ @@ -17,7 +18,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632;626;8618;8714;8602;8981</NoWarn>
<DefineConstants>ROSLYN;ROSLYN2;ROSLYN3;ROSLYN4;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100;CS110;CS120</DefineConstants>
<DefineConstants>ROSLYN;ROSLYN2;ROSLYN3;ROSLYN4;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100;CS110;CS120;CS130</DefineConstants>
<GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
@ -146,6 +147,7 @@ @@ -146,6 +147,7 @@
<Compile Include="TestCases\Pretty\Issue3442.cs" />
<Compile Include="TestCases\Pretty\Issue3483.cs" />
<Compile Include="TestCases\Pretty\PointerArithmetic.cs" />
<Compile Include="TestCases\Pretty\ParamsCollections.cs" />
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
<Compile Include="TestCases\VBPretty\VBAutomaticEvents.cs" />
<Compile Include="TestCases\VBPretty\VBNonGenericForEach.cs" />

12
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -59,8 +59,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -59,8 +59,6 @@ namespace ICSharpCode.Decompiler.Tests
static readonly CompilerOptions[] roslynOnlyWithNet40Options =
{
CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
@ -145,8 +143,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -145,8 +143,6 @@ namespace ICSharpCode.Decompiler.Tests
{
CompilerOptions.None,
CompilerOptions.Optimize,
CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
@ -167,8 +163,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -167,8 +163,6 @@ namespace ICSharpCode.Decompiler.Tests
{
CompilerOptions.None,
CompilerOptions.Optimize,
CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn1_3_2 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn2_10_0 | CompilerOptions.TargetNet40,
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.TargetNet40,
@ -611,6 +605,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -611,6 +605,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task ParamsCollections([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public async Task Issue1080([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{

4
ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length));
C1.Test();
#if ROSLYN2 && !NET40
#if CS120 && !NET40
C3.Run();
#endif
}
@ -204,7 +204,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -204,7 +204,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
}
}
#if ROSLYN2 && !NET40
#if CS120 && !NET40
class C3
{
[InlineArray(4)] struct MyArray { private int elem; }

2
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.il

@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
// .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.custom instance void [System.Runtime]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 18 2E 4E 45 54 43 6F 72 65 41 70 70 2C 56 // ....NETCoreApp,V
65 72 73 69 6F 6E 3D 76 32 2E 31 01 00 54 0E 14 // ersion=v2.1..T..
65 72 73 69 6F 6E 3D 76 32 2E 32 01 00 54 0E 14 // ersion=v2.2..T..
46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C 61 79 // FrameworkDisplay
4E 61 6D 65 00 ) // Name.
.custom instance void [System.Runtime]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 05 44 65 62 75 67 00 00 ) // ...Debug..

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

@ -631,21 +631,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction @@ -631,21 +631,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
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)
{

8
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MetadataAttributes.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public extern void A();
#if NETCORE
#if !NET40 && ROSLYN3
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public extern void B();
#endif
@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public extern void J();
[MethodImpl(MethodImplOptions.AggressiveInlining, MethodCodeType = MethodCodeType.Native)]
public extern void A1();
#if NETCORE
#if !NET40 && ROSLYN3
[MethodImpl(MethodImplOptions.AggressiveOptimization, MethodCodeType = MethodCodeType.Native)]
public extern void B1();
#endif
@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public extern void J1();
[MethodImpl(MethodImplOptions.AggressiveInlining, MethodCodeType = MethodCodeType.OPTIL)]
public extern void A2();
#if NETCORE
#if !NET40 && ROSLYN3
[MethodImpl(MethodImplOptions.AggressiveOptimization, MethodCodeType = MethodCodeType.OPTIL)]
public extern void B2();
#endif
@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public extern void J2();
[MethodImpl(MethodImplOptions.AggressiveInlining, MethodCodeType = MethodCodeType.OPTIL)]
public extern void A3();
#if NETCORE
#if !NET40 && ROSLYN3
[MethodImpl(MethodImplOptions.AggressiveOptimization, MethodCodeType = MethodCodeType.Runtime)]
public extern void B3();
#endif

21
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ParamsCollections.cs

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public static class ParamsCollections
{
public static void ParamsEnumerable(params IEnumerable<int> values)
{
}
public static void ParamsList(params List<int> values)
{
}
public static void ParamsReadOnlySpan(params ReadOnlySpan<int> values)
{
}
public static void ParamsSpan(params Span<int> values)
{
}
}
}

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

@ -1624,7 +1624,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -1624,7 +1624,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey key)
{
#if NET40 || !ROSLYN
#if NET40 || !ROSLYN4
key = (ConsoleKey)0;
#else
key = ConsoleKey.None;
@ -1641,7 +1641,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -1641,7 +1641,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
key = ConsoleKey.C;
break;
}
#if NET40 || !ROSLYN
#if NET40 || !ROSLYN4
return key != (ConsoleKey)0;
#else
return key != ConsoleKey.None;

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/WellKnownConstants.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public const float Float_Tenth = 0.1f;
public const double Double_Tenth = 0.1;
#if ROSLYN && !NET40
#if ROSLYN2 && !NET40
public const float Float_PI = MathF.PI;
public const float Float_HalfOfPI = MathF.PI / 2f;
public const float Float_QuarterOfPI = MathF.PI / 4f;

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

@ -47,12 +47,12 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -47,12 +47,12 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
static readonly Lazy<PEFile> mscorlib = new Lazy<PEFile>(
delegate {
return LoadAssembly(Path.Combine(Helpers.Tester.RefAsmPath, "mscorlib.dll"));
return LoadAssembly(Path.Combine(Helpers.Tester.RefAssembliesToolset.GetPath("legacy"), "mscorlib.dll"));
});
static readonly Lazy<PEFile> systemCore = new Lazy<PEFile>(
delegate {
return LoadAssembly(Path.Combine(Helpers.Tester.RefAsmPath, "System.Core.dll"));
return LoadAssembly(Path.Combine(Helpers.Tester.RefAssembliesToolset.GetPath("legacy"), "System.Core.dll"));
});
static readonly Lazy<PEFile> testAssembly = new Lazy<PEFile>(

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -316,6 +316,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -316,6 +316,8 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
if (settings.FixedBuffers && name.StartsWith("<", StringComparison.Ordinal) && name.Contains("__FixedBuffer"))
return true;
if (settings.InlineArrays && name.StartsWith("<>y__InlineArray", StringComparison.Ordinal) && name.EndsWith("`1"))
return true;
}
else if (type.IsCompilerGenerated(metadata))
{

3
ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs

@ -35,7 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -35,7 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp
CSharp10_0 = 1000,
CSharp11_0 = 1100,
CSharp12_0 = 1200,
Preview = 1100,
CSharp13_0 = 1300,
Preview = 1300,
Latest = 0x7FFFFFFF
}
}

79
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1026,25 +1026,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1026,25 +1026,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
private bool TransformParamsArgument(ExpectedTargetDetails expectedTargetDetails, ResolveResult targetResolveResult,
IMethod method, IParameter parameter, TranslatedExpression arg, ref List<IParameter> expectedParameters,
IMethod method, IParameter parameter, TranslatedExpression paramsArgument, ref List<IParameter> expectedParameters,
ref List<TranslatedExpression> arguments)
{
if (CheckArgument(out int length, out IType elementType))
var expressionBuilder = this.expressionBuilder;
if (ExtractArguments(out IType elementType, out var expandedParameters, out var expandedArguments))
{
var expandedParameters = new List<IParameter>(expectedParameters);
var expandedArguments = new List<TranslatedExpression>(arguments);
if (length > 0)
{
var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray();
for (int j = 0; j < length; j++)
{
expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j));
if (j < arrayElements.Length)
expandedArguments.Add(new TranslatedExpression(arrayElements[j]));
else
expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
}
}
expandedParameters.InsertRange(0, expectedParameters);
expandedArguments.InsertRange(0, arguments);
if (IsUnambiguousCall(expectedTargetDetails, method, targetResolveResult, Empty<IType>.Array,
expandedArguments.SelectArray(a => a.ResolveResult), argumentNames: null,
firstOptionalArgumentIndex: -1, out _,
@ -1057,30 +1046,46 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1057,30 +1046,46 @@ namespace ICSharpCode.Decompiler.CSharp
}
return false;
bool CheckArgument(out int len, out IType t)
bool ExtractArguments(out IType elementType, out List<IParameter> parameters, out List<TranslatedExpression> arguments)
{
len = 0;
t = null;
if (arg.ResolveResult is CSharpInvocationResolveResult csirr &&
csirr.Arguments.Count == 0 && csirr.Member is IMethod emptyMethod &&
emptyMethod.IsStatic &&
"System.Array.Empty" == emptyMethod.FullName &&
emptyMethod.TypeArguments.Count == 1)
elementType = null;
parameters = null;
arguments = null;
switch (paramsArgument.ResolveResult)
{
t = emptyMethod.TypeArguments[0];
return true;
}
if (arg.ResolveResult is ArrayCreateResolveResult acrr &&
acrr.SizeArguments.Count == 1 &&
acrr.SizeArguments[0].IsCompileTimeConstant &&
acrr.SizeArguments[0].ConstantValue is int l)
{
len = l;
t = ((ArrayType)acrr.Type).ElementType;
return true;
case CSharpInvocationResolveResult { Member: IMethod method, Arguments: var args }:
// match System.Array.Empty<T>()
if (args is [] && method is { IsStatic: true, FullName: "System.Array.Empty", TypeArguments: [var type] })
{
elementType = type;
arguments = new();
parameters = new();
return true;
}
if (paramsArgument.Expression is ObjectCreateExpression oce
&& method is { IsConstructor: true, DeclaringType: { TypeArguments: [var type2] } declaringType }
&& declaringType.IsKnownType(KnownTypeCode.ReadOnlySpanOfT))
{
elementType = type2;
arguments = new() { new TranslatedExpression(oce.Arguments.Single()) };
parameters = new() { new DefaultParameter(type2, string.Empty) };
return true;
}
return false;
case ArrayCreateResolveResult { Type: ArrayType { ElementType: var type3 }, SizeArguments: [{ ConstantValue: int arrayLength }] }:
elementType = type3;
arguments = new(((ArrayCreateExpression)paramsArgument.Expression).Initializer.Elements.Select(e => new TranslatedExpression(e)));
parameters = new List<IParameter>(arrayLength);
for (int i = 0; i < arrayLength; i++)
{
parameters.Add(new DefaultParameter(type3, string.Empty));
if (arguments.Count <= i)
arguments.Add(new TranslatedExpression(expressionBuilder.GetDefaultValueExpression(type3).WithoutILInstruction()));
}
return true;
default:
return false;
}
return false;
}
}

2
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -779,7 +779,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -779,7 +779,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
{
// C# 4.0 spec: §6.1.7
fromType = NullableType.GetUnderlyingType(fromType);
if (fromType.IsReferenceType == false && toType.IsReferenceType == true)
if (fromType.IsReferenceType == false && !fromType.IsByRefLike && toType.IsReferenceType == true)
return IsSubtypeOf(fromType, toType, 0);
else
return false;

129
ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
public readonly bool IsExpandedForm;
/// <summary>
/// Gets the parameter types. In the first step, these are the types without any substition.
/// Gets the parameter types. In the first step, these are the types without any substitution.
/// After type inference, substitutions will be performed.
/// </summary>
public readonly IType[] ParameterTypes;
@ -76,6 +76,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -76,6 +76,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
/// </summary>
public Conversion[] ArgumentConversions;
/// <summary>
/// Gets the type of the collection that is used for the 'params' parameter (before any substitution!).
/// Otherwise returns SpecialType.UnknownType.
/// </summary>
public IType ParamsCollectionType {
get {
if (IsExpandedForm && Parameters.Count > 0)
{
IParameter lastParameter = Parameters[Parameters.Count - 1];
if (lastParameter.IsParams)
{
return lastParameter.Type;
}
}
return SpecialType.UnknownType;
}
}
public bool IsGenericMethod {
get {
IMethod method = Member as IMethod;
@ -83,7 +101,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -83,7 +101,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
}
public int ArgumentsPassedToParamsArray {
public int ArgumentsPassedToParams {
get {
int count = 0;
if (IsExpandedForm)
@ -104,7 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -104,7 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
this.Member = member;
this.IsExpandedForm = isExpanded;
IParameterizedMember memberDefinition = (IParameterizedMember)member.MemberDefinition;
// For specificialized methods, go back to the original parameters:
// For specialized methods, go back to the original parameters:
// (without any type parameter substitution, not even class type parameters)
// We'll re-substitute them as part of RunTypeInference().
this.Parameters = memberDefinition.Parameters;
@ -286,9 +304,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -286,9 +304,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
}
if (candidate.IsExpandedForm && i == candidate.Parameters.Count - 1)
{
ArrayType arrayType = type as ArrayType;
if (arrayType != null && arrayType.Dimensions == 1)
if (type is ArrayType arrayType && arrayType.Dimensions == 1)
type = arrayType.ElementType;
else if (type.IsKnownType(KnownTypeCode.ReadOnlySpanOfT) || type.IsKnownType(KnownTypeCode.SpanOfT))
type = type.TypeArguments[0];
else if (type.IsArrayInterfaceType())
type = type.TypeArguments[0];
else
return false; // error: cannot unpack params-array. abort considering the expanded form for this candidate
}
@ -772,8 +793,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -772,8 +793,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
else if (c1.IsExpandedForm && !c2.IsExpandedForm)
return 2;
// prefer the member with less arguments mapped to the params-array
int r = c1.ArgumentsPassedToParamsArray.CompareTo(c2.ArgumentsPassedToParamsArray);
// prefer the member with less arguments mapped to the params-collection
int r = c1.ArgumentsPassedToParams.CompareTo(c2.ArgumentsPassedToParams);
if (r < 0)
return 1;
else if (r > 0)
@ -797,13 +818,105 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -797,13 +818,105 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return 1;
if (lift1 != null && lift2 == null)
return 2;
// prefer by-value parameters over in-parameters
r = BetterParameterPassingChoice(c1, c2);
if (r != 0)
return r;
if (c1.IsExpandedForm)
{
Debug.Assert(c2.IsExpandedForm);
r = BetterParamsCollectionType(c1.ParamsCollectionType, c2.ParamsCollectionType);
if (r != 0)
return r;
}
}
return 0;
}
int BetterParamsCollectionType(IType paramsCollectionType1, IType paramsCollectionType2)
{
// see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-13.0/params-collections#better-function-member
bool isSpan1 = paramsCollectionType1.IsKnownType(KnownTypeCode.SpanOfT) || paramsCollectionType1.IsKnownType(KnownTypeCode.ReadOnlySpanOfT);
bool isSpan2 = paramsCollectionType2.IsKnownType(KnownTypeCode.SpanOfT) || paramsCollectionType2.IsKnownType(KnownTypeCode.ReadOnlySpanOfT);
if (!isSpan1 && !isSpan2)
{
bool implicitConversion1to2 = conversions.ImplicitConversion(paramsCollectionType1, paramsCollectionType2).IsValid;
bool implicitConversion2to1 = conversions.ImplicitConversion(paramsCollectionType2, paramsCollectionType1).IsValid;
if (implicitConversion1to2 && !implicitConversion2to1)
return 1;
if (!implicitConversion1to2 && implicitConversion2to1)
return 2;
}
else if (paramsCollectionType1.IsKnownType(KnownTypeCode.ReadOnlySpanOfT) && paramsCollectionType2.IsKnownType(KnownTypeCode.SpanOfT))
{
if (conversions.IdentityConversion(paramsCollectionType1.TypeArguments[0], paramsCollectionType2.TypeArguments[0]))
return 1; // ReadOnlySpan<T> is better than Span<T> if there exists an identity conversion between the element types
}
else if (paramsCollectionType2.IsKnownType(KnownTypeCode.ReadOnlySpanOfT) && paramsCollectionType1.IsKnownType(KnownTypeCode.SpanOfT))
{
if (conversions.IdentityConversion(paramsCollectionType2.TypeArguments[0], paramsCollectionType1.TypeArguments[0]))
return 2; // ReadOnlySpan<T> is better than Span<T> if there exists an identity conversion between the element types
}
else if (isSpan1 && IsArrayOrArrayInterfaceType(paramsCollectionType2, out var elementType2))
{
if (conversions.IdentityConversion(paramsCollectionType1.TypeArguments[0], elementType2))
return 1; // Span<T> is better than an array type if there exists an identity conversion between the element types
}
else if (isSpan2 && IsArrayOrArrayInterfaceType(paramsCollectionType1, out var elementType1))
{
if (conversions.IdentityConversion(paramsCollectionType2.TypeArguments[0], elementType1))
return 2; // Span<T> is better than an array type if there exists an identity conversion between the element types
}
return 0;
}
bool IsArrayOrArrayInterfaceType(IType type, out IType elementType)
{
elementType = null;
if (type is ArrayType arrayType)
{
elementType = arrayType.ElementType;
return true;
}
if (type.IsArrayInterfaceType())
{
elementType = type.TypeArguments[0];
return true;
}
return false;
}
int BetterParameterPassingChoice(Candidate c1, Candidate c2)
{
Debug.Assert(c1.Parameters.Count == c2.Parameters.Count, "c1 and c2 must have the same number of parameters");
bool c1IsBetter = false;
bool c2IsBetter = false;
for (int i = 0; i < c1.Parameters.Count; i++)
{
ReferenceKind refKind1 = c1.Parameters[i].ReferenceKind;
ReferenceKind refKind2 = c2.Parameters[i].ReferenceKind;
if (refKind1 == ReferenceKind.None && refKind2 == ReferenceKind.In)
c1IsBetter = true; // by-value is better than in
if (refKind1 == ReferenceKind.In && refKind2 == ReferenceKind.None)
c2IsBetter = true;
}
if (c1IsBetter && !c2IsBetter)
return 1;
if (!c1IsBetter && c2IsBetter)
return 2;
return 0;
}
int MoreSpecificFormalParameters(Candidate c1, Candidate c2)
{
// prefer the member with more formal parmeters (in case both have different number of optional parameters)
// prefer the member with more formal parameters (in case both have different number of optional parameters)
int r = c1.Parameters.Count.CompareTo(c2.Parameters.Count);
if (r > 0)
return 1;

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

@ -759,7 +759,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -759,7 +759,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
MakeLowerBoundInference(arrU.ElementType, arrV.ElementType);
return;
}
else if (arrU != null && IsGenericInterfaceImplementedByArray(pV) && arrU.Dimensions == 1)
else if (arrU != null && pV.IsArrayInterfaceType() && arrU.Dimensions == 1)
{
MakeLowerBoundInference(arrU.ElementType, pV.GetTypeArgument(0));
return;
@ -829,23 +829,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -829,23 +829,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return;
}
}
static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt)
{
if (rt == null || rt.TypeParameterCount != 1)
return false;
switch (rt.GetDefinition()?.KnownTypeCode)
{
case KnownTypeCode.IEnumerableOfT:
case KnownTypeCode.ICollectionOfT:
case KnownTypeCode.IListOfT:
case KnownTypeCode.IReadOnlyCollectionOfT:
case KnownTypeCode.IReadOnlyListOfT:
return true;
default:
return false;
}
}
#endregion
#region MakeUpperBoundInference (§7.5.2.10)
@ -880,7 +863,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -880,7 +863,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
MakeUpperBoundInference(arrU.ElementType, arrV.ElementType);
return;
}
else if (arrV != null && IsGenericInterfaceImplementedByArray(pU) && arrV.Dimensions == 1)
else if (arrV != null && pU.IsArrayInterfaceType() && arrV.Dimensions == 1)
{
MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType);
return;

1
ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs

@ -166,6 +166,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -166,6 +166,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
"System.Runtime.CompilerServices.NullableAttribute",
"System.Runtime.CompilerServices.NullableContextAttribute",
"System.Runtime.CompilerServices.NativeIntegerAttribute",
"System.Runtime.CompilerServices.ParamCollectionAttribute",
"System.Runtime.CompilerServices.RefSafetyRulesAttribute",
"System.Runtime.CompilerServices.ScopedRefAttribute",
"System.Runtime.CompilerServices.RequiresLocationAttribute",

12
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -57,8 +57,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -57,8 +57,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var arguments = invocationExpression.Arguments.ToArray();
// Reduce "String.Concat(a, b)" to "a + b"
if (IsStringConcat(method) && context.Settings.StringConcat && CheckArgumentsForStringConcat(arguments))
if (IsStringConcat(method) && context.Settings.StringConcat)
{
if (arguments is [ArrayCreateExpression ace] && method.Parameters is [{ Type: ArrayType }])
{
arguments = ace.Initializer.Elements.ToArray();
}
if (!CheckArgumentsForStringConcat(arguments))
{
return;
}
bool isInExpressionTree = invocationExpression.Ancestors.OfType<LambdaExpression>().Any(
lambda => lambda.Annotation<IL.ILFunction>()?.Kind == IL.ILFunctionKind.ExpressionTree);
Expression arg0 = arguments[0].Detach();

24
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -166,10 +166,16 @@ namespace ICSharpCode.Decompiler @@ -166,10 +166,16 @@ namespace ICSharpCode.Decompiler
usePrimaryConstructorSyntaxForNonRecordTypes = false;
inlineArrays = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp13_0)
{
paramsCollections = false;
}
}
public CSharp.LanguageVersion GetMinimumRequiredVersion()
{
if (paramsCollections)
return CSharp.LanguageVersion.CSharp13_0;
if (refReadOnlyParameters || usePrimaryConstructorSyntaxForNonRecordTypes || inlineArrays)
return CSharp.LanguageVersion.CSharp12_0;
if (scopedRef || requiredMembers || numericIntPtr || utf8StringLiterals || unsignedRightShift || checkedOperators)
@ -849,6 +855,24 @@ namespace ICSharpCode.Decompiler @@ -849,6 +855,24 @@ namespace ICSharpCode.Decompiler
}
}
bool paramsCollections = true;
/// <summary>
/// Support params collections.
/// </summary>
[Category("C# 13.0 / VS 2022.12")]
[Description("DecompilerSettings.DecompileParamsCollections")]
public bool ParamsCollections {
get { return paramsCollections; }
set {
if (paramsCollections != value)
{
paramsCollections = value;
OnPropertyChanged();
}
}
}
bool lockStatement = true;
/// <summary>

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
<!-- https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/ -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(GITHUB_ACTIONS)' == 'true'">true</RestoreLockedMode>
<RestoreLockedMode>true</RestoreLockedMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">

4
ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs

@ -16,12 +16,10 @@ @@ -16,12 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
@ -109,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -109,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (objectVariable.LoadCount != 1 || objectVariable.StoreCount > 2)
continue;
var beforeExceptionCaptureBlock = (Block)LocalFunctionDecompiler.GetStatement(objectVariable.LoadInstructions[0])?.Parent;
var beforeExceptionCaptureBlock = Block.FindClosestBlock(objectVariable.LoadInstructions[0]);
if (beforeExceptionCaptureBlock == null)
continue;

2
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -238,6 +238,8 @@ namespace ICSharpCode.Decompiler.IL @@ -238,6 +238,8 @@ namespace ICSharpCode.Decompiler.IL
default:
return SpecialType.UnknownType;
}
case ILFunction func when func.DelegateType != null:
return func.DelegateType;
default:
return SpecialType.UnknownType;
}

16
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -383,6 +383,22 @@ namespace ICSharpCode.Decompiler.IL @@ -383,6 +383,22 @@ namespace ICSharpCode.Decompiler.IL
return null;
}
/// <summary>
/// Gets the closest ancestor that is child of a control-flow (top-level) Block.
/// Returns null, if the instruction is not a descendant of a Block.
/// </summary>
public static ILInstruction? GetContainingStatement(ILInstruction inst)
{
var curr = inst;
while (curr != null)
{
if (curr.Parent is Block { Kind: BlockKind.ControlFlow })
return curr;
curr = curr.Parent;
}
return null;
}
public bool MatchInlineAssignBlock([NotNullWhen(true)] out CallInstruction? call, [NotNullWhen(true)] out ILInstruction? value)
{
call = null;

5
ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs

@ -16,9 +16,6 @@ @@ -16,9 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -107,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -107,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// We are only interested in store "statements" copying the exception variable
// without modifying it.
var statement = LocalFunctionDecompiler.GetStatement(load);
var statement = Block.GetContainingStatement(load);
if (!(statement is StLoc stloc))
{
i++;

15
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -312,25 +312,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -312,25 +312,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitNewObj(NewObj inst)
{
Block block;
if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan))
{
context.Step("new Span<T>(stackalloc) -> stackalloc Span<T>", inst);
inst.ReplaceWith(locallocSpan);
block = null;
ILInstruction stmt = locallocSpan;
while (stmt.Parent != null)
{
if (stmt.Parent is Block b)
{
block = b;
break;
}
stmt = stmt.Parent;
}
ILInstruction stmt = Block.GetContainingStatement(locallocSpan);
// Special case to eliminate extra store
if (stmt.GetNextSibling() is StLoc storeStmt && storeStmt.Value is LdLoc)
ILInlining.InlineIfPossible(block, stmt.ChildIndex, context);
ILInlining.InlineIfPossible((Block)stmt.Parent, stmt.ChildIndex, context);
return;
}
if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out var replacement))

18
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -337,20 +337,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -337,20 +337,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
return true;
}
else if (IsPassedToReadOnlySpanOfCharCtor(loadInst))
else if (IsPassedToReadOnlySpanCtor(loadInst))
{
// Always inlining is possible here, because it's an 'in' or 'ref readonly' parameter
// and the C# compiler allows calling it with an rvalue, even though that might produce
// a warning. Note that we don't need to check the expression classification, because
// expressionBuilder.VisitAddressOf will handle creating the copy for us.
// This is necessary, because there are compiler-generated uses of this ctor when
// concatenating a string to a char and our following transforms assume the char is
// already inlined.
// passing a single-element array to a params ROS<T> parameter and our following transforms
// assume the value is already inlined.
return true;
}
if (IsPassedToInlineArrayAsSpan(loadInst))
else if (IsPassedToInlineArrayAsSpan(loadInst))
{
// Inlining is not allowed
// Inlining is not allowed:
// <PrivateImplementationDetails>.InlineArrayAsReadOnlySpan(GetInlineArray()) is invalid C# code
return false;
}
else if (IsPassedToInParameter(loadInst))
@ -491,13 +492,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -491,13 +492,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return call.GetParameter(ldloca.ChildIndex)?.ReferenceKind is ReferenceKind.In;
}
static bool IsPassedToReadOnlySpanOfCharCtor(LdLoca ldloca)
static bool IsPassedToReadOnlySpanCtor(LdLoca ldloca)
{
if (ldloca.Parent is not NewObj call)
{
return false;
}
return IsReadOnlySpanCharCtor(call.Method);
var method = call.Method;
return method.IsConstructor
&& method.Parameters.Count == 1
&& method.DeclaringType.IsKnownType(KnownTypeCode.ReadOnlySpanOfT);
}
internal static bool IsReadOnlySpanCharCtor(IMethod method)

13
ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs

@ -575,17 +575,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -575,17 +575,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
&& TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type);
}
internal static ILInstruction GetStatement(ILInstruction inst)
{
while (inst.Parent != null)
{
if (inst.Parent is Block b && b.Kind == BlockKind.ControlFlow)
return inst;
inst = inst.Parent;
}
return inst;
}
LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove)
{
int parametersToRemove = 0;
@ -747,7 +736,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -747,7 +736,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (variable.Kind == VariableKind.Parameter)
return null;
if (type.Kind == TypeKind.Struct)
return GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
return Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
else
return (StLoc)variable.StoreInstructions[0];
}

2
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -604,7 +604,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -604,7 +604,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct
&& variable.UsesInitialValue && IsPotentialClosure(context, closureType))
{
initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
initializer = Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
return true;
}
return false;

6
ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
public static class DecompilerVersionInfo
{
public const string Major = "9";
public const string Minor = "1";
public const string Major = "10";
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = null;
public const string VersionName = "preview1";
public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$";
public const string FullVersionWithShortCommitHash = FullVersion + "+$INSERTSHORTCOMMITHASH$";

11
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -138,12 +138,19 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -138,12 +138,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
RefReadOnlyParameters = 0x10000,
/// <summary>
/// If this option is active, [ParamCollectionAttribute] on parameters is removed
/// and parameters are marked as params.
/// Otherwise, the attribute is preserved but the parameters are not marked
/// as if it was a normal parameter without any attributes.
/// </summary>
ParamsCollections = 0x20000,
/// <summary>
/// Default settings: typical options for the decompiler, with all C# languages features enabled.
/// </summary>
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters
| RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods
| NativeIntegers | FunctionPointers | ScopedRef | NativeIntegersWithoutAttribute
| RefReadOnlyParameters
| RefReadOnlyParameters | ParamsCollections
}
/// <summary>
@ -185,6 +192,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -185,6 +192,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeSystemOptions |= TypeSystemOptions.NativeIntegersWithoutAttribute;
if (settings.RefReadOnlyParameters)
typeSystemOptions |= TypeSystemOptions.RefReadOnlyParameters;
if (settings.ParamsCollections)
typeSystemOptions |= TypeSystemOptions.ParamsCollections;
return typeSystemOptions;
}

3
ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

@ -258,6 +258,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -258,6 +258,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
case "RequiresLocationAttribute":
return (options & TypeSystemOptions.RefReadOnlyParameters) != 0
&& (target == SymbolKind.Parameter);
case "ParamCollectionAttribute":
return (options & TypeSystemOptions.ParamsCollections) != 0
&& (target == SymbolKind.Parameter);
default:
return false;
}

2
ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

@ -87,6 +87,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -87,6 +87,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
// Parameter attributes:
ParamArray,
ParamCollection,
In,
Out,
Optional,
@ -169,6 +170,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -169,6 +170,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(IndexerNameAttribute)),
// Parameter attributes:
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", "ParamCollectionAttribute"),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(InAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OutAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OptionalAttribute)),

18
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -125,6 +125,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -125,6 +125,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = module.metadata;
var parameterDef = metadata.GetParameter(handle);
if ((module.TypeSystemOptions & TypeSystemOptions.ParamsCollections) != 0
&& parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.ParamCollection))
{
// params collections are implicitly scoped
return default;
}
if (parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.ScopedRef))
{
return new LifetimeAnnotation { ScopedRef = true };
@ -135,11 +141,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -135,11 +141,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool IsParams {
get {
if (Type.Kind != TypeKind.Array)
return false;
var metadata = module.metadata;
var parameterDef = metadata.GetParameter(handle);
return parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.ParamArray);
if (Type.Kind == TypeKind.Array)
{
return parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.ParamArray);
}
if (module.TypeSystemOptions.HasFlag(TypeSystemOptions.ParamsCollections))
{
return parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.ParamCollection);
}
return false;
}
}

17
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -306,6 +306,23 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -306,6 +306,23 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
public static bool IsArrayInterfaceType(this IType type)
{
if (type == null || type.TypeParameterCount != 1)
return false;
switch (type.GetDefinition()?.KnownTypeCode)
{
case KnownTypeCode.IEnumerableOfT:
case KnownTypeCode.ICollectionOfT:
case KnownTypeCode.IListOfT:
case KnownTypeCode.IReadOnlyCollectionOfT:
case KnownTypeCode.IReadOnlyListOfT:
return true;
default:
return false;
}
}
public static bool IsInlineArrayType(this IType type)
{
if (type.Kind != TypeKind.Struct)

4
ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ServerGarbageCollection>true</ServerGarbageCollection>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPackable>true</IsPackable>
@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
<!-- https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/ -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(GITHUB_ACTIONS)' == 'true'">true</RestoreLockedMode>
<RestoreLockedMode>true</RestoreLockedMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

11
ICSharpCode.ILSpyCmd/packages.lock.json

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"net10.0": {
"McMaster.Extensions.Hosting.CommandLine": {
"type": "Direct",
"requested": "[4.1.1, )",
@ -425,8 +425,8 @@ @@ -425,8 +425,8 @@
"System.Collections.Immutable": {
"type": "CentralTransitive",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "wfm2NgK22MmBe5qJjp52qzpkeDZKb4l9LbdubhZSehY1z4LS+lld6R+B+UQNb2AZRHu/QJlHxEUcRst5hIEejg=="
"resolved": "8.0.0",
"contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
},
"System.Composition.AttributedModel": {
"type": "CentralTransitive",
@ -438,10 +438,7 @@ @@ -438,10 +438,7 @@
"type": "CentralTransitive",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ==",
"dependencies": {
"System.Collections.Immutable": "9.0.4"
}
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "CentralTransitive",

4
ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<WarningsAsErrors>nullable</WarningsAsErrors>
@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
<!-- https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/ -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(GITHUB_ACTIONS)' == 'true'">true</RestoreLockedMode>
<RestoreLockedMode>true</RestoreLockedMode>
</PropertyGroup>
<ItemGroup>

2
ICSharpCode.ILSpyX/MermaidDiagrammer/html/.vscode/tasks.json vendored

@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
"group": "build",
"type": "shell",
"command": [
"$folder = '../../../ICSharpCode.ILSpyCmd/bin/Debug/net8.0/';", // to avoid repetition
"$folder = '../../../ICSharpCode.ILSpyCmd/bin/Debug/net10.0/';", // to avoid repetition
"$exePath = $folder + 'ilspycmd.exe';",
"$assemblyPath = $folder + 'ICSharpCode.Decompiler.dll';", // comes with XML docs for testing the integration
"if (Test-Path $exePath) {",

14
ICSharpCode.ILSpyX/packages.lock.json

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"net10.0": {
"K4os.Compression.LZ4": {
"type": "Direct",
"requested": "[1.3.8, )",
@ -40,10 +40,7 @@ @@ -40,10 +40,7 @@
"type": "Direct",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ==",
"dependencies": {
"System.Collections.Immutable": "9.0.4"
}
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Direct",
@ -77,8 +74,11 @@ @@ -77,8 +74,11 @@
"System.Collections.Immutable": {
"type": "CentralTransitive",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "wfm2NgK22MmBe5qJjp52qzpkeDZKb4l9LbdubhZSehY1z4LS+lld6R+B+UQNb2AZRHu/QJlHxEUcRst5hIEejg=="
"resolved": "6.0.0",
"contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
}
}
}

2
ILSpy-tests

@ -1 +1 @@ @@ -1 +1 @@
Subproject commit 6f8860e420b54bdfd726ec3c58a4d178416f9156
Subproject commit 6cc4bb2942a1c6a134510ad4d916f77604d37b51

4
ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj

@ -75,8 +75,8 @@ @@ -75,8 +75,8 @@
</ItemGroup>
<PropertyGroup>
<ILSpyBuildPathX64>..\ILSpy\bin\$(Configuration)\net8.0-windows\win-x64\publish\fwdependent\</ILSpyBuildPathX64>
<ILSpyBuildPathArm64>..\ILSpy\bin\$(Configuration)\net8.0-windows\win-arm64\publish\fwdependent\</ILSpyBuildPathArm64>
<ILSpyBuildPathX64>..\ILSpy\bin\$(Configuration)\net10.0-windows\win-x64\publish\fwdependent\</ILSpyBuildPathX64>
<ILSpyBuildPathArm64>..\ILSpy\bin\$(Configuration)\net10.0-windows\win-arm64\publish\fwdependent\</ILSpyBuildPathArm64>
</PropertyGroup>
<Target Name="IncludeILSpyDistributionInVSIXSubFolder" AfterTargets="ResolveProjectReferences">

2
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -81,7 +81,7 @@ @@ -81,7 +81,7 @@
</ItemGroup>
<PropertyGroup>
<ILSpyBuildPath>..\ILSpy\bin\$(Configuration)\net8.0-windows\win-x64\publish\fwdependent\</ILSpyBuildPath>
<ILSpyBuildPath>..\ILSpy\bin\$(Configuration)\net10.0-windows\win-x64\publish\fwdependent\</ILSpyBuildPath>
</PropertyGroup>
<Target Name="IncludeILSpyDistributionInVSIXSubFolder" AfterTargets="ResolveProjectReferences">

2
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<RuntimeIdentifier Condition="$(IsWindowsX64) == true">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="$(IsWindowsARM64) == true">win-arm64</RuntimeIdentifier>

2
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>ILSpy.BamlDecompiler.Plugin</AssemblyName>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<IsPackable>false</IsPackable>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>

2
ILSpy.Installer/setup.cs

@ -25,7 +25,7 @@ namespace ILSpy.Installer @@ -25,7 +25,7 @@ namespace ILSpy.Installer
#else
var buildPlatform = "x64";
#endif
var buildOutputDir = $@"ILSpy\bin\{buildConfiguration}\net8.0-windows\win-{buildPlatform}\publish\fwdependent";
var buildOutputDir = $@"ILSpy\bin\{buildConfiguration}\net10.0-windows\win-{buildPlatform}\publish\fwdependent";
var project = new Project("ILSpy",
new InstallDir(@"%LocalAppData%\Programs\ILSpy",

2
ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
<PropertyGroup>
<AssemblyName>ILSpy.ReadyToRun.Plugin</AssemblyName>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<NeutralResourcesLanguage>en-US</NeutralResourcesLanguage>

2
ILSpy.Tests/ILSpy.Tests.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<IsPackable>false</IsPackable>
<StartupObject>AutoGeneratedProgram</StartupObject>

1
ILSpy.sln

@ -41,6 +41,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution @@ -41,6 +41,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
global.json = global.json
EndProjectSection
EndProject
Global

2
ILSpy/ILSpy.csproj

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<RollForward>major</RollForward>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>

1
ILSpy/Languages/CSharpLanguage.cs

@ -116,6 +116,7 @@ namespace ICSharpCode.ILSpy @@ -116,6 +116,7 @@ namespace ICSharpCode.ILSpy
new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp10_0.ToString(), "C# 10.0 / VS 2022"),
new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp11_0.ToString(), "C# 11.0 / VS 2022.4"),
new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp12_0.ToString(), "C# 12.0 / VS 2022.8"),
new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp13_0.ToString(), "C# 13.0 / VS 2022.12"),
};
}
return versions;

9
ILSpy/Properties/Resources.Designer.cs generated

@ -918,6 +918,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -918,6 +918,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Decompile params collections.
/// </summary>
public static string DecompilerSettings_DecompileParamsCollections {
get {
return ResourceManager.GetString("DecompilerSettings.DecompileParamsCollections", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile use of the &apos;dynamic&apos; type.
/// </summary>

3
ILSpy/Properties/Resources.resx

@ -327,6 +327,9 @@ Are you sure you want to continue?</value> @@ -327,6 +327,9 @@ Are you sure you want to continue?</value>
<data name="DecompilerSettings.DecompileForEachWithGetEnumeratorExtension" xml:space="preserve">
<value>Decompile foreach statements with GetEnumerator extension methods</value>
</data>
<data name="DecompilerSettings.DecompileParamsCollections" xml:space="preserve">
<value>Decompile params collections</value>
</data>
<data name="DecompilerSettings.DecompileUseOfTheDynamicType" xml:space="preserve">
<value>Decompile use of the 'dynamic' type</value>
</data>

3
ILSpy/Properties/Resources.zh-Hans.resx

@ -315,6 +315,9 @@ @@ -315,6 +315,9 @@
<data name="DecompilerSettings.DecompileForEachWithGetEnumeratorExtension" xml:space="preserve">
<value>反编译使用 GetEnumerator 扩展方法的 foreach 语句</value>
</data>
<data name="DecompilerSettings.DecompileParamsCollections" xml:space="preserve">
<value />
</data>
<data name="DecompilerSettings.DecompileUseOfTheDynamicType" xml:space="preserve">
<value>反编译 dynamic 类型</value>
</data>

2
TestPlugin/TestPlugin.csproj

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows</TargetFramework>
<AssemblyName>Test.Plugin</AssemblyName>
<UseWpf>true</UseWpf>
<EnableWindowsTargeting>true</EnableWindowsTargeting>

2
global.json

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.100",
"version": "10.0.0",
"rollForward": "major",
"allowPrerelease": true
}

6
publish.ps1

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
$output_arm64 = "./ILSpy/bin/Release/net8.0-windows/win-arm64/publish/fwdependent"
$output_x64 = "./ILSpy/bin/Release/net8.0-windows/win-x64/publish/fwdependent"
$output_x64_selfcontained = "./ILSpy/bin/Release/net8.0-windows/win-x64/publish/selfcontained"
$output_arm64 = "./ILSpy/bin/Release/net10.0-windows/win-arm64/publish/fwdependent"
$output_x64 = "./ILSpy/bin/Release/net10.0-windows/win-x64/publish/fwdependent"
$output_x64_selfcontained = "./ILSpy/bin/Release/net10.0-windows/win-x64/publish/selfcontained"
dotnet publish ./ILSpy/ILSpy.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64
dotnet publish ./ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64

4
publishlocaldev.ps1

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
# For local development of the VSIX package - build and publish (VS2022 also needs arm64)
$output_x64 = "./ILSpy/bin/Release/net8.0-windows/win-x64/publish/fwdependent"
$output_x64 = "./ILSpy/bin/Release/net10.0-windows/win-x64/publish/fwdependent"
dotnet publish ./ILSpy/ILSpy.csproj -c Release --no-restore --no-self-contained -r win-x64 -o $output_x64
dotnet publish ./ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj -c Release --no-restore --no-self-contained -r win-x64 -o $output_x64
dotnet publish ./ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj -c Release --no-restore --no-self-contained -r win-x64 -o $output_x64
$output_arm64 = "./ILSpy/bin/Release/net8.0-windows/win-arm64/publish/fwdependent"
$output_arm64 = "./ILSpy/bin/Release/net10.0-windows/win-arm64/publish/fwdependent"
dotnet publish ./ILSpy/ILSpy.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64
dotnet publish ./ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj -c Release --no-restore --no-self-contained -r win-arm64 -o $output_arm64

Loading…
Cancel
Save