From 648fe32aa00267406b1a00100fa154d823c1d891 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 13 Jul 2021 10:44:58 +0200 Subject: [PATCH 01/43] Reproducible builds, see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/ and https://github.com/dotnet/reproducible-builds (for Release only) --- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 085c7d4441..036ab87884 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -37,8 +37,14 @@ - portable - true + embedded + true + true + true + + + + true From b95f3aa1d2a8cabd658aef3a84d361945467063c Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 13 Jul 2021 11:00:19 +0200 Subject: [PATCH 02/43] Switch release and debug to embedded debug info --- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 11 ++++------- .../ICSharpCode.Decompiler.nuspec.template | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 036ab87884..d71ee8959f 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -19,28 +19,25 @@ True ICSharpCode.Decompiler.snk 1701;1702;1591;1573 + + embedded + true + true true - true ICSharpCode.Decompiler.nuspec Configuration=$(Configuration) - portable - true True $(DefineConstants);STEP - embedded - true - true - true diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template index 6c4d3d3c9f..d371363fb1 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template @@ -25,7 +25,6 @@ - From 6e4566d224c32e457ceb951e7284c2d47c4280d8 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 16 Jul 2021 14:26:21 +0200 Subject: [PATCH 03/43] Add back DebugSymbols to csproj --- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index d71ee8959f..b16589e629 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -21,6 +21,7 @@ 1701;1702;1591;1573 embedded + true true true From db81fb17e261e685a5b29064e01a87cda11bcbbf Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Wed, 14 Jul 2021 17:04:00 +0200 Subject: [PATCH 04/43] Fix #2446: Allow to open ILSpy on package references under "Dependencies" --- ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs | 6 ++++-- ILSpy.AddIn/Commands/OpenReferenceCommand.cs | 8 ++++---- ILSpy.AddIn/ILSpy.AddIn.csproj | 6 ++++++ ILSpy.AddIn/ILSpyAddIn.en-US.vsct | 15 ++++++++++----- ILSpy.AddIn/ILSpyAddIn.vsct | 10 ++++++++++ ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct | 16 +++++++++++++--- ILSpy.AddIn/ILSpyAddInPackage.cs | 3 ++- ILSpy.AddIn/PkgCmdID.cs | 1 + 8 files changed, 50 insertions(+), 15 deletions(-) diff --git a/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs b/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs index 45b183c4ba..bc61779f74 100644 --- a/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs +++ b/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs @@ -8,6 +8,8 @@ using Microsoft.VisualStudio.Shell; +using VSLangProj; + namespace ICSharpCode.ILSpy.AddIn.Commands { /// @@ -33,8 +35,8 @@ public static NuGetReferenceForILSpy Detect(object itemData) if (itemData is ProjectItem projectItem) { - var properties = Utils.GetProperties(projectItem.Properties, "Type"); - if ((properties[0] as string) == "Package") + var properties = Utils.GetProperties(projectItem.Properties, "Type", "ExtenderCATID"); + if (((properties[0] as string) == "Package") || ((properties[1] as string) == PrjBrowseObjectCATID.prjCATIDCSharpReferenceBrowseObject)) { return new NuGetReferenceForILSpy(projectItem); } diff --git a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs index fd4a9dc822..89ca397d46 100644 --- a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs +++ b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs @@ -13,8 +13,8 @@ class OpenReferenceCommand : ILSpyCommand { static OpenReferenceCommand instance; - public OpenReferenceCommand(ILSpyAddInPackage owner) - : base(owner, PkgCmdIDList.cmdidOpenReferenceInILSpy) + public OpenReferenceCommand(ILSpyAddInPackage owner, uint id) + : base(owner, id) { ThreadHelper.ThrowIfNotOnUIThread(); } @@ -98,11 +98,11 @@ protected override void OnExecute(object sender, EventArgs e) } } - internal static void Register(ILSpyAddInPackage owner) + internal static void Register(ILSpyAddInPackage owner, uint id) { ThreadHelper.ThrowIfNotOnUIThread(); - instance = new OpenReferenceCommand(owner); + instance = new OpenReferenceCommand(owner, id); } } diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index dd5da51763..270d8f3153 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -165,6 +165,12 @@ Designer + + Designer + + + Designer + true Always diff --git a/ILSpy.AddIn/ILSpyAddIn.en-US.vsct b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct index a6a3c69470..8258f6c041 100644 --- a/ILSpy.AddIn/ILSpyAddIn.en-US.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct @@ -56,6 +56,16 @@ Open in ILSpy + + - - - - - diff --git a/ILSpy.AddIn/ILSpyAddIn.vsct b/ILSpy.AddIn/ILSpyAddIn.vsct index 3d992eae76..a4a132b294 100644 --- a/ILSpy.AddIn/ILSpyAddIn.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.vsct @@ -52,6 +52,10 @@ + + + + @@ -75,10 +79,12 @@ + + @@ -89,6 +95,10 @@ + + + + diff --git a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct index d50bfb0625..1f654e3457 100644 --- a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct @@ -34,7 +34,7 @@ group; your package should define its own command set in order to avoid collisions with command ids defined by other packages. --> - + @@ -57,6 +57,16 @@ + + - + - + diff --git a/ILSpy.AddIn/ILSpyAddInPackage.cs b/ILSpy.AddIn/ILSpyAddInPackage.cs index 195940b68b..5f35a7d7a7 100644 --- a/ILSpy.AddIn/ILSpyAddInPackage.cs +++ b/ILSpy.AddIn/ILSpyAddInPackage.cs @@ -94,7 +94,8 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke OpenILSpyCommand.Register(this); OpenProjectOutputCommand.Register(this); - OpenReferenceCommand.Register(this); + OpenReferenceCommand.Register(this, PkgCmdIDList.cmdidOpenReferenceInILSpy); + OpenReferenceCommand.Register(this, PkgCmdIDList.cmdidOpenPackageReferenceInILSpy); OpenCodeItemCommand.Register(this); } #endregion diff --git a/ILSpy.AddIn/PkgCmdID.cs b/ILSpy.AddIn/PkgCmdID.cs index 841381a516..aa678e642f 100644 --- a/ILSpy.AddIn/PkgCmdID.cs +++ b/ILSpy.AddIn/PkgCmdID.cs @@ -9,5 +9,6 @@ static class PkgCmdIDList public const uint cmdidOpenReferenceInILSpy = 0x200; public const uint cmdidOpenProjectOutputInILSpy = 0x300; public const uint cmdidOpenCodeItemInILSpy = 0x0400; + public const uint cmdidOpenPackageReferenceInILSpy = 0x500; }; } \ No newline at end of file From 04a615a3f283f5ccb558129e2addcc0d8d681c84 Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Fri, 16 Jul 2021 00:45:48 +0200 Subject: [PATCH 05/43] Allow to open ILSpy on project references under "Dependencies" --- ILSpy.AddIn/Commands/OpenReferenceCommand.cs | 16 ++++++++-------- ILSpy.AddIn/ILSpyAddIn.en-US.vsct | 10 ++++++++++ ILSpy.AddIn/ILSpyAddIn.vsct | 7 +++++++ ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct | 10 ++++++++++ ILSpy.AddIn/ILSpyAddInPackage.cs | 1 + ILSpy.AddIn/PkgCmdID.cs | 1 + 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs index 89ca397d46..5a96751619 100644 --- a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs +++ b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs @@ -68,14 +68,6 @@ protected override void OnExecute(object sender, EventArgs e) return; } - // Handle NuGet references - var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject); - if (nugetRefItem != null) - { - OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters()); - return; - } - // Handle project references var projectRefItem = ProjectReferenceForILSpy.Detect(itemObject); if (projectRefItem != null) @@ -96,6 +88,14 @@ protected override void OnExecute(object sender, EventArgs e) OpenAssembliesInILSpy(projectRefItem.GetILSpyParameters()); return; } + + // Handle NuGet references + var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject); + if (nugetRefItem != null) + { + OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters()); + return; + } } internal static void Register(ILSpyAddInPackage owner, uint id) diff --git a/ILSpy.AddIn/ILSpyAddIn.en-US.vsct b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct index 8258f6c041..e3fc05868f 100644 --- a/ILSpy.AddIn/ILSpyAddIn.en-US.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct @@ -67,6 +67,16 @@ + + + + - - - - - - - - void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null) { - if (nugetPackagesToLoad.Count > 0) - { - var relevantPackages = nugetPackagesToLoad.ToArray(); - nugetPackagesToLoad.Clear(); - // Show the nuget package open dialog after the command line/window message was processed. - Dispatcher.BeginInvoke(new Action(() => LoadAssemblies(relevantPackages, commandLineLoadedAssemblies, focusNode: false)), DispatcherPriority.Normal); - } var relevantAssemblies = commandLineLoadedAssemblies.ToList(); commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); From 84101f804adc682fa5c15a202be1706e19ebe401 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 25 Jul 2021 18:50:03 +0200 Subject: [PATCH 11/43] Fix #2444: Ambiguous implicit conversions from null literals in decompiled code --- .../Correctness/OverloadResolution.cs | 33 +++++++++++++++++++ ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs index 69f703a427..edfbab5402 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs @@ -36,6 +36,7 @@ static void Main() Issue1747(); CallAmbiguousOutParam(); CallWithInParam(); + Issue2444.M2(); } #region ConstructorTest @@ -334,6 +335,38 @@ static void InVsRegularParam(int i) } #endif #endregion + + #region #2444 + public struct Issue2444 + { + public class X { } + public class Y { } + + public static implicit operator Issue2444(X x) + { + Console.WriteLine("#2444: op_Implicit(X)"); + return new Issue2444(); + } + + public static implicit operator Issue2444(Y y) + { + Console.WriteLine("#2444: op_Implicit(Y)"); + return new Issue2444(); + } + + public static void M1(Issue2444 z) + { + Console.WriteLine(string.Format("#2444: M1({0})", z)); + } + + public static void M2() + { + Console.WriteLine("#2444: before M1"); + M1((X)null); + Console.WriteLine("#2444: after M1"); + } + } + #endregion } class IndexerTests diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 7cf420ba73..e6e276a7a7 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -1148,7 +1148,7 @@ private ExpressionWithResolveResult HandleImplicitConversion(IMethod method, Tra var conversions = CSharpConversions.Get(expressionBuilder.compilation); IType targetType = method.ReturnType; var conv = conversions.ImplicitConversion(argument.Type, targetType); - if (!(conv.IsUserDefined && conv.Method.Equals(method))) + if (!(conv.IsUserDefined && conv.IsValid && conv.Method.Equals(method))) { // implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type argument = argument.ConvertTo(method.Parameters[0].Type, expressionBuilder); From a99a6a5fe380adaf54702206e4478533d21fc942 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 27 Jul 2021 13:04:33 +0200 Subject: [PATCH 12/43] Update NuGet packages --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 2 +- ILSpy/ILSpy.csproj | 6 +++--- SharpTreeView/ICSharpCode.TreeView.csproj | 2 +- packages.props | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index 86d29d6327..f8943198b6 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -38,7 +38,7 @@ - + 3.11.0-1.final - 0.11.3 + 0.11.4 6.1.1 - 3.12.0 - 3.13.0 - 4.14.1 + 3.13.2 + 4.0.0 + 4.16.1 2017.7.26.1241 1.1.0-beta2-20115-01 From e2e38b667dc82efbb20b20252573c7113b3434ae Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 27 Jul 2021 14:51:05 +0200 Subject: [PATCH 13/43] Move TomsToolbox.Wpf.Styles version to packages.props --- ILSpy/ILSpy.csproj | 2 +- SharpTreeView/ICSharpCode.TreeView.csproj | 4 +++- packages.props | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 24ee6c072d..5c606930f2 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -52,7 +52,7 @@ - + diff --git a/SharpTreeView/ICSharpCode.TreeView.csproj b/SharpTreeView/ICSharpCode.TreeView.csproj index 27671dbc79..5cec02258a 100644 --- a/SharpTreeView/ICSharpCode.TreeView.csproj +++ b/SharpTreeView/ICSharpCode.TreeView.csproj @@ -23,8 +23,10 @@ true + + - + diff --git a/packages.props b/packages.props index 09a46897e0..6f28c66f8e 100644 --- a/packages.props +++ b/packages.props @@ -13,6 +13,7 @@ 3.11.0-1.final 0.11.4 6.1.1 + 2.6.1 3.13.2 4.0.0 4.16.1 From 0d9005a5785d21f93c2fa9a93a6aaafe8b86b170 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 27 Jul 2021 15:55:30 +0200 Subject: [PATCH 14/43] Do not run analyzers for the .Addin project during build --- ILSpy.AddIn/ILSpy.AddIn.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index ffe8da06bf..1a849094c2 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -209,6 +209,8 @@ true + false + true From 84704a7452f23ba2d8def22e3a8157b177b825d7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 31 Jul 2021 22:42:49 +0200 Subject: [PATCH 15/43] Adds support for C# 9 covariant return types in methods and getter-only properties and indexers. --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../PrettyTestRunner.cs | 6 +++ .../TestCases/Pretty/CovariantReturns.cs | 50 +++++++++++++++++++ .../CSharp/CSharpDecompiler.cs | 23 +++++++++ ICSharpCode.Decompiler/DecompilerSettings.cs | 22 +++++++- .../Implementation/KnownAttributes.cs | 4 +- 6 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index e0334ffcbd..71edc5762d 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -107,6 +107,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 49d82222c2..30ee7b18d7 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -573,6 +573,12 @@ public void CS9_ExtensionGetEnumerator([ValueSource(nameof(dotnetCoreOnlyOptions RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); } + [Test] + public void CovariantReturns([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions) + { + RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); + } + void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) { Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs new file mode 100644 index 0000000000..11987dde5c --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CovariantReturns.cs @@ -0,0 +1,50 @@ +namespace ICSharpCode.Decompiler.Tests.TestCases.CovariantReturns +{ + public abstract class Base + { + public abstract Base Instance { get; } + + public abstract Base this[int index] { get; } + + public virtual Base Build() + { + throw null; + } + + protected abstract Base SetParent(object parent); + } + + public class Derived : Base + { + public override Derived Instance { get; } + + public override Derived this[int index] { + get { + throw null; + } + } + + public override Derived Build() + { + throw null; + } + + protected override Derived SetParent(object parent) + { + throw null; + } + } + + public class UseSites + { + public Base Test(Base x) + { + return x.Build(); + } + + public Derived Test(Derived x) + { + return x.Build(); + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 676c924d45..fe1ea0ee93 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1451,9 +1451,24 @@ EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeRe { SetNewModifier(methodDecl); } + if (IsCovariantReturnOverride(method)) + { + RemoveAttribute(methodDecl, KnownAttribute.PreserveBaseOverrides); + methodDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual); + methodDecl.Modifiers |= Modifiers.Override; + } return methodDecl; } + private bool IsCovariantReturnOverride(IEntity entity) + { + if (!settings.CovariantReturns) + return false; + if (!entity.HasAttribute(KnownAttribute.PreserveBaseOverrides)) + return false; + return true; + } + internal static bool IsWindowsFormsInitializeComponentMethod(IMethod method) { return method.ReturnType.Kind == TypeKind.Void && method.Name == "InitializeComponent" && method.DeclaringTypeDefinition.GetNonInterfaceBaseTypes().Any(t => t.FullName == "System.Windows.Forms.Control"); @@ -1766,7 +1781,15 @@ EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITy var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken; var accessor = metadata.GetMethodDefinition(accessorHandle); if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) + { SetNewModifier(propertyDecl); + } + if (IsCovariantReturnOverride(property.Getter)) + { + RemoveAttribute(getter, KnownAttribute.PreserveBaseOverrides); + propertyDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual); + propertyDecl.Modifiers |= Modifiers.Override; + } return propertyDecl; } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index b7c4672233..b456b32034 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -139,12 +139,14 @@ public void SetLanguageVersion(CSharp.LanguageVersion languageVersion) recordClasses = false; withExpressions = false; usePrimaryConstructorSyntax = false; + covariantReturns = false; } } public CSharp.LanguageVersion GetMinimumRequiredVersion() { - if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension || recordClasses) + if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension + || recordClasses || withExpressions || usePrimaryConstructorSyntax || covariantReturns) return CSharp.LanguageVersion.Preview; if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement || staticLocalFunctions || ranges || switchExpressions) @@ -193,6 +195,24 @@ public bool NativeIntegers { } } + bool covariantReturns = true; + + /// + /// Decompile C# 9 covariant return types. + /// + [Category("C# 9.0 / VS 2019.8")] + [Description("DecompilerSettings.CovariantReturns")] + public bool CovariantReturns { + get { return covariantReturns; } + set { + if (covariantReturns != value) + { + covariantReturns = value; + OnPropertyChanged(); + } + } + } + bool initAccessors = true; /// diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index aae66c064d..2ce7b2b62f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -102,11 +102,12 @@ public enum KnownAttribute // C# 9 attributes: NativeInteger, + PreserveBaseOverrides, } static class KnownAttributes { - internal const int Count = (int)KnownAttribute.NativeInteger + 1; + internal const int Count = (int)KnownAttribute.PreserveBaseOverrides + 1; static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{ default, @@ -167,6 +168,7 @@ static class KnownAttributes new TopLevelTypeName("System.Security.Permissions", "PermissionSetAttribute"), // C# 9 attributes: new TopLevelTypeName("System.Runtime.CompilerServices", "NativeIntegerAttribute"), + new TopLevelTypeName("System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute"), }; public static ref readonly TopLevelTypeName GetTypeName(this KnownAttribute attr) From 39d230f0221c7a02f4ec77a67576182621853047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Pr=C3=A4hauser?= Date: Sun, 1 Aug 2021 19:28:21 +0200 Subject: [PATCH 16/43] Support loading compressed Xamarin assemblies, see #2137 Extend class LoadedAssembly to detect and load compressed Xamarin assemblies if direct loading of assembly fails. Requires Nuget pkg K4os.Compression.LZ4 for LZ4 decompression. --- ILSpy/ILSpy.csproj | 1 + ILSpy/LoadedAssembly.cs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 4757e9ffe7..3d09cdfe4c 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -54,6 +54,7 @@ + diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index ad1dae9dcd..02b342f59a 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -35,6 +35,8 @@ using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.Options; +using K4os.Compression.LZ4; + #nullable enable namespace ICSharpCode.ILSpy @@ -323,6 +325,15 @@ async Task LoadAsync(Task? streamTask) { loadAssemblyException = ex; } + // Maybe its a compressed Xamarin/Mono assembly, see https://github.com/xamarin/xamarin-android/pull/4686 + try + { + return LoadCompressedAssembly(fileName); + } + catch (InvalidDataException) + { + // Not a compressed module, try other options below + } // If it's not a .NET module, maybe it's a single-file bundle var bundle = LoadedPackage.FromBundle(fileName); if (bundle != null) @@ -365,6 +376,31 @@ LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions) return new LoadResult(module); } + LoadResult LoadCompressedAssembly(string filename) + { + const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian) + using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) + using (var fileReader = new BinaryReader(fileStream)) + { + // Read compressed file header + var magic = fileReader.ReadUInt32(); + if (magic != CompressedDataMagic) + throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}"); + var descIdx = fileReader.ReadUInt32(); + var uncLen = fileReader.ReadUInt32(); + // fileReader stream position is now at compressed module data + var src = fileReader.ReadBytes((int)uncLen); // compressed length must be smaller than uncompressed length + var dst = new byte[(int)uncLen]; + // Decompress + LZ4Codec.Decode(src, 0, src.Length, dst, 0, dst.Length); + // Load module from decompressed data buffer + using (var modData = new MemoryStream(dst, writable: false)) + { + return LoadAssembly(modData, PEStreamOptions.PrefetchEntireImage); + } + } + } + IDebugInfoProvider? LoadDebugInfo(PEFile module) { if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) From 7bbad4a22fbf50e567eacaf83a8345df0584f41f Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 3 Aug 2021 16:30:25 +0200 Subject: [PATCH 17/43] Update DataGridExtensions to 2.5.6 --- ILSpy/ILSpy.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 5c606930f2..676349a80d 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -50,7 +50,7 @@ - + From d04c7fd3729b63e1a7bd2b8284fcf48619f253eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Pr=C3=A4hauser?= Date: Wed, 4 Aug 2021 20:04:31 +0200 Subject: [PATCH 18/43] Add license notice for pkg K4os.Compression.LZ4 --- doc/third-party-notices.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/third-party-notices.txt b/doc/third-party-notices.txt index 39961ecc99..3f54b3b86a 100644 --- a/doc/third-party-notices.txt +++ b/doc/third-party-notices.txt @@ -415,6 +415,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License Notice for K4os.Compression.LZ4 (part of ILSpy) +--------------------------- + +https://github.com/MiloszKrajewski/K4os.Compression.LZ4/blob/master/LICENSE + +MIT License + +Copyright (c) 2017 Milosz Krajewski + +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. + + License Notice for LightJson (part of ICSharpCode.Decompiler) --------------------------- From 95f9908823023f7266eb8abc5812486d56598fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Pr=C3=A4hauser?= Date: Wed, 4 Aug 2021 20:05:26 +0200 Subject: [PATCH 19/43] Ensure we read all of compressed data in LoadCompressedAssembly --- ILSpy/LoadedAssembly.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 02b342f59a..42361ed755 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -389,7 +389,7 @@ LoadResult LoadCompressedAssembly(string filename) var descIdx = fileReader.ReadUInt32(); var uncLen = fileReader.ReadUInt32(); // fileReader stream position is now at compressed module data - var src = fileReader.ReadBytes((int)uncLen); // compressed length must be smaller than uncompressed length + var src = fileReader.ReadBytes((int)fileStream.Length); // Ensure we read all of compressed data var dst = new byte[(int)uncLen]; // Decompress LZ4Codec.Decode(src, 0, src.Length, dst, 0, dst.Length); From 6cda7cceb1b9ec21c0efe4a87984d228b8dcaaab Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 4 Aug 2021 20:13:56 +0200 Subject: [PATCH 20/43] Use FileName parameter instead of LoadedAssembly.fileName --- ILSpy/LoadedAssembly.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 42361ed755..045b3816a9 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -376,7 +376,7 @@ LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions) return new LoadResult(module); } - LoadResult LoadCompressedAssembly(string filename) + LoadResult LoadCompressedAssembly(string fileName) { const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian) using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) From 27f56a9253b4b7f5934e9e1b15e451dc809da87b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 7 Aug 2021 20:22:03 +0200 Subject: [PATCH 21/43] Use ArrayPool.Shared for decompression. --- ILSpy/ILSpy.csproj | 1 + ILSpy/LoadedAssembly.cs | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 3d09cdfe4c..66bbb2c0d9 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -55,6 +55,7 @@ + diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 045b3816a9..320a7f581f 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -386,17 +387,28 @@ LoadResult LoadCompressedAssembly(string fileName) var magic = fileReader.ReadUInt32(); if (magic != CompressedDataMagic) throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}"); - var descIdx = fileReader.ReadUInt32(); - var uncLen = fileReader.ReadUInt32(); - // fileReader stream position is now at compressed module data - var src = fileReader.ReadBytes((int)fileStream.Length); // Ensure we read all of compressed data - var dst = new byte[(int)uncLen]; - // Decompress - LZ4Codec.Decode(src, 0, src.Length, dst, 0, dst.Length); - // Load module from decompressed data buffer - using (var modData = new MemoryStream(dst, writable: false)) + _ = fileReader.ReadUInt32(); // skip index into descriptor table, unused + int uncompressedLength = (int)fileReader.ReadUInt32(); + int compressedLength = (int)fileStream.Length; // Ensure we read all of compressed data + ArrayPool pool = ArrayPool.Shared; + var src = pool.Rent(compressedLength); + var dst = pool.Rent(uncompressedLength); + try + { + // fileReader stream position is now at compressed module data + fileStream.Read(src, 0, compressedLength); + // Decompress + LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength); + // Load module from decompressed data buffer + using (var uncompressedStream = new MemoryStream(dst, writable: false)) + { + return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage); + } + } + finally { - return LoadAssembly(modData, PEStreamOptions.PrefetchEntireImage); + pool.Return(dst); + pool.Return(src); } } } From 73c898664f8f2379f3ccdff00d3164ddb73d0957 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 Aug 2021 08:20:47 +0200 Subject: [PATCH 22/43] Fix #2484: Private modifier incorrectly applied to interface static constructors --- .../TestCases/Pretty/InterfaceTests.cs | 5 +++++ .../CSharp/Syntax/TypeSystemAstBuilder.cs | 12 +++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs index 05da939e37..622b1ee429 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs @@ -32,6 +32,11 @@ public interface IA void Method(); #if CS80 + static IA() + { + + } + void DefaultMethod() { Method(); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index c6fd018e8d..334ca0e6ad 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -2259,20 +2259,18 @@ bool NeedsAccessibility(IMember member) var declaringType = member.DeclaringType; if (member.IsExplicitInterfaceImplementation) return false; - if (declaringType != null && declaringType.Kind == TypeKind.Interface) - { - return member.Accessibility != Accessibility.Public; - } switch (member.SymbolKind) { case SymbolKind.Constructor: return !member.IsStatic; case SymbolKind.Destructor: return false; - case SymbolKind.Method: - return !((IMethod)member).IsLocalFunction; default: - return true; + if (declaringType?.Kind == TypeKind.Interface) + { + return member.Accessibility != Accessibility.Public; + } + return member is not IMethod method || !method.IsLocalFunction; } } From dd1621a811459da26b8fc2d993ec50c2f2b50704 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 Aug 2021 14:29:21 +0200 Subject: [PATCH 23/43] Fix #2481: Remove 4 characters length requirement in regex search. --- ILSpy/Search/AbstractSearchStrategy.cs | 36 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/ILSpy/Search/AbstractSearchStrategy.cs b/ILSpy/Search/AbstractSearchStrategy.cs index 74e6cd2c3f..dc1e23f5d4 100644 --- a/ILSpy/Search/AbstractSearchStrategy.cs +++ b/ILSpy/Search/AbstractSearchStrategy.cs @@ -25,14 +25,10 @@ protected AbstractSearchStrategy(IProducerConsumerCollection resul if (terms.Length == 1 && terms[0].Length > 2) { string search = terms[0]; - if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4) + if (TryParseRegex(search, out regex)) { - var regexString = search.Substring(1, search.Length - 1); fullNameSearch = search.Contains("\\."); omitGenerics = !search.Contains("<"); - if (regexString.EndsWith("/", StringComparison.Ordinal)) - regexString = regexString.Substring(0, regexString.Length - 1); - regex = SafeNewRegex(regexString); } else { @@ -129,15 +125,35 @@ protected void OnFoundResult(SearchResult result) resultQueue.TryAdd(result); } - Regex SafeNewRegex(string unsafePattern) + bool TryParseRegex(string input, out Regex pattern) { - try + pattern = null; + if (!input.StartsWith("/", StringComparison.Ordinal)) { - return new Regex(unsafePattern, RegexOptions.Compiled); + return false; + } + input = input.Substring(1); + if (input.EndsWith("/", StringComparison.Ordinal)) + { + input = input.Remove(input.Length - 1); } - catch (ArgumentException) + if (string.IsNullOrWhiteSpace(input)) { - return null; + return false; + } + pattern = SafeNewRegex(input); + return pattern != null; + + static Regex SafeNewRegex(string unsafePattern) + { + try + { + return new Regex(unsafePattern, RegexOptions.Compiled); + } + catch (ArgumentException) + { + return null; + } } } } From 41b9e3e787e45dc18e970f75dd7f1cddec0b149c Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 24 Aug 2021 15:01:54 -0700 Subject: [PATCH 24/43] Update ready to run --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 2 +- ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index f8943198b6..ebfd1b3010 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -39,7 +39,7 @@ - + - - - - + + + + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - - - - PerMonitorV2, PerMonitor - True - - - true - - + + + + PerMonitorV2, PerMonitor + True - - - - + True + + + + + + + - - + + From 11ec27c2bb0d6176e05011dfee695e37606394c7 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 7 Sep 2021 15:26:47 +0200 Subject: [PATCH 34/43] Set next version to 7.2-preview1 --- ILSpy.AddIn/ILSpy.AddIn.csproj | 2 +- ILSpy/Properties/AssemblyInfo.template.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 1a849094c2..af12ddabcd 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -48,7 +48,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs index bd8f807262..41233bc1d0 100644 --- a/ILSpy/Properties/AssemblyInfo.template.cs +++ b/ILSpy/Properties/AssemblyInfo.template.cs @@ -37,10 +37,10 @@ internal static class RevisionClass { public const string Major = "7"; - public const string Minor = "1"; + public const string Minor = "2"; 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$"; } From 19d5ea4095ae8d0567bc16d431a1336013e370c4 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 18 Sep 2021 12:32:20 +0200 Subject: [PATCH 35/43] Fix #2505: Do treat whole resource name as file name without directory at the start of GetFileNameForResource. --- .../CSharp/ProjectDecompiler/WholeProjectDecompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 7de382062b..25eadffaef 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -369,7 +369,7 @@ string GetFileNameForResource(string fullName) // 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. string[] splitName = fullName.Split(Path.DirectorySeparatorChar); - string fileName = fullName; + string fileName = string.Join(".", splitName); string separator = Path.DirectorySeparatorChar.ToString(); for (int i = splitName.Length - 1; i > 0; i--) { From 9a053d5e6c33fe516fdbdac478835be12cdb92b7 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 18 Sep 2021 20:42:17 +0200 Subject: [PATCH 36/43] nullable enable for CSharpOperators.cs --- .../CSharp/Resolver/CSharpOperators.cs | 138 +++++++++--------- ICSharpCode.Decompiler/Util/CacheManager.cs | 4 +- 2 files changed, 72 insertions(+), 70 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs index 1bfef1ecf4..868f7fe596 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -45,7 +47,7 @@ private CSharpOperators(ICompilation compilation) public static CSharpOperators Get(ICompilation compilation) { CacheManager cache = compilation.CacheManager; - CSharpOperators operators = (CSharpOperators)cache.GetShared(typeof(CSharpOperators)); + CSharpOperators? operators = (CSharpOperators?)cache.GetShared(typeof(CSharpOperators)); if (operators == null) { operators = (CSharpOperators)cache.GetOrAddShared(typeof(CSharpOperators), new CSharpOperators(compilation)); @@ -59,7 +61,7 @@ OperatorMethod[] Lift(params OperatorMethod[] methods) List result = new List(methods); foreach (OperatorMethod method in methods) { - OperatorMethod lifted = method.Lift(this); + OperatorMethod? lifted = method.Lift(this); if (lifted != null) result.Add(lifted); } @@ -111,20 +113,20 @@ public IReadOnlyList Parameters { get { return parameters; } } - public IType ReturnType { get; internal set; } + public IType ReturnType { get; internal set; } = null!; // initialized by derived class ctor public ICompilation Compilation { get { return compilation; } } - public virtual OperatorMethod Lift(CSharpOperators operators) + public virtual OperatorMethod? Lift(CSharpOperators operators) { return null; } public System.Reflection.Metadata.EntityHandle MetadataToken => default; - ITypeDefinition IEntity.DeclaringTypeDefinition { + ITypeDefinition? IEntity.DeclaringTypeDefinition { get { return null; } } @@ -226,7 +228,7 @@ public override string ToString() return b.ToString(); } - bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) + bool IMember.Equals(IMember? obj, TypeVisitor? typeNormalization) { return this == obj; } @@ -238,7 +240,7 @@ internal class UnaryOperatorMethod : OperatorMethod { public virtual bool CanEvaluateAtCompileTime { get { return false; } } - public virtual object Invoke(CSharpResolver resolver, object input) + public virtual object? Invoke(CSharpResolver resolver, object? input) { throw new NotSupportedException(); } @@ -265,7 +267,7 @@ public override bool CanEvaluateAtCompileTime { get { return true; } } - public override object Invoke(CSharpResolver resolver, object input) + public override object? Invoke(CSharpResolver resolver, object? input) { if (input == null) return null; @@ -296,11 +298,11 @@ public LiftedUnaryOperatorMethod(CSharpOperators operators, UnaryOperatorMethod #region Unary operator definitions // C# 4.0 spec: §7.7.1 Unary plus operator - OperatorMethod[] unaryPlusOperators; + OperatorMethod[]? unaryPlusOperators; public OperatorMethod[] UnaryPlusOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref unaryPlusOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref unaryPlusOperators); if (ops != null) { return ops; @@ -321,11 +323,11 @@ public OperatorMethod[] UnaryPlusOperators { } // C# 4.0 spec: §7.7.2 Unary minus operator - OperatorMethod[] uncheckedUnaryMinusOperators; + OperatorMethod[]? uncheckedUnaryMinusOperators; public OperatorMethod[] UncheckedUnaryMinusOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators); if (ops != null) { return ops; @@ -343,11 +345,11 @@ public OperatorMethod[] UncheckedUnaryMinusOperators { } } - OperatorMethod[] checkedUnaryMinusOperators; + OperatorMethod[]? checkedUnaryMinusOperators; public OperatorMethod[] CheckedUnaryMinusOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators); if (ops != null) { return ops; @@ -366,11 +368,11 @@ public OperatorMethod[] CheckedUnaryMinusOperators { } // C# 4.0 spec: §7.7.3 Logical negation operator - OperatorMethod[] logicalNegationOperators; + OperatorMethod[]? logicalNegationOperators; public OperatorMethod[] LogicalNegationOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalNegationOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalNegationOperators); if (ops != null) { return ops; @@ -385,11 +387,11 @@ public OperatorMethod[] LogicalNegationOperators { } // C# 4.0 spec: §7.7.4 Bitwise complement operator - OperatorMethod[] bitwiseComplementOperators; + OperatorMethod[]? bitwiseComplementOperators; public OperatorMethod[] BitwiseComplementOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseComplementOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseComplementOperators); if (ops != null) { return ops; @@ -411,7 +413,7 @@ public OperatorMethod[] BitwiseComplementOperators { internal class BinaryOperatorMethod : OperatorMethod { public virtual bool CanEvaluateAtCompileTime { get { return false; } } - public virtual object Invoke(CSharpResolver resolver, object lhs, object rhs) + public virtual object? Invoke(CSharpResolver resolver, object? lhs, object? rhs) { throw new NotSupportedException(); } @@ -444,7 +446,7 @@ public override bool CanEvaluateAtCompileTime { get { return true; } } - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + public override object? Invoke(CSharpResolver resolver, object? lhs, object? rhs) { if (lhs == null || rhs == null) return null; @@ -480,11 +482,11 @@ public LiftedBinaryOperatorMethod(CSharpOperators operators, BinaryOperatorMetho #region Arithmetic operators // C# 4.0 spec: §7.8.1 Multiplication operator - OperatorMethod[] multiplicationOperators; + OperatorMethod[]? multiplicationOperators; public OperatorMethod[] MultiplicationOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref multiplicationOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref multiplicationOperators); if (ops != null) { return ops; @@ -505,11 +507,11 @@ public OperatorMethod[] MultiplicationOperators { } // C# 4.0 spec: §7.8.2 Division operator - OperatorMethod[] divisionOperators; + OperatorMethod[]? divisionOperators; public OperatorMethod[] DivisionOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref divisionOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref divisionOperators); if (ops != null) { return ops; @@ -530,11 +532,11 @@ public OperatorMethod[] DivisionOperators { } // C# 4.0 spec: §7.8.3 Remainder operator - OperatorMethod[] remainderOperators; + OperatorMethod[]? remainderOperators; public OperatorMethod[] RemainderOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref remainderOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref remainderOperators); if (ops != null) { return ops; @@ -555,11 +557,11 @@ public OperatorMethod[] RemainderOperators { } // C# 4.0 spec: §7.8.3 Addition operator - OperatorMethod[] additionOperators; + OperatorMethod[]? additionOperators; public OperatorMethod[] AdditionOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref additionOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref additionOperators); if (ops != null) { return ops; @@ -600,18 +602,18 @@ public override bool CanEvaluateAtCompileTime { get { return canEvaluateAtCompileTime; } } - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + public override object? Invoke(CSharpResolver? resolver, object? lhs, object? rhs) { return string.Concat(lhs, rhs); } } // C# 4.0 spec: §7.8.4 Subtraction operator - OperatorMethod[] subtractionOperators; + OperatorMethod[]? subtractionOperators; public OperatorMethod[] SubtractionOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref subtractionOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref subtractionOperators); if (ops != null) { return ops; @@ -632,11 +634,11 @@ public OperatorMethod[] SubtractionOperators { } // C# 4.0 spec: §7.8.5 Shift operators - OperatorMethod[] shiftLeftOperators; + OperatorMethod[]? shiftLeftOperators; public OperatorMethod[] ShiftLeftOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftLeftOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref shiftLeftOperators); if (ops != null) { return ops; @@ -653,11 +655,11 @@ public OperatorMethod[] ShiftLeftOperators { } } - OperatorMethod[] shiftRightOperators; + OperatorMethod[]? shiftRightOperators; public OperatorMethod[] ShiftRightOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftRightOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref shiftRightOperators); if (ops != null) { return ops; @@ -695,7 +697,7 @@ public override bool CanEvaluateAtCompileTime { get { return Type != TypeCode.Object; } } - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + public override object Invoke(CSharpResolver resolver, object? lhs, object? rhs) { if (lhs == null && rhs == null) return !Negate; // ==: true; !=: false @@ -719,7 +721,7 @@ public override object Invoke(CSharpResolver resolver, object lhs, object rhs) return equal ^ Negate; } - public override OperatorMethod Lift(CSharpOperators operators) + public override OperatorMethod? Lift(CSharpOperators operators) { if (Type == TypeCode.Object || Type == TypeCode.String) return null; @@ -746,7 +748,7 @@ public override bool CanEvaluateAtCompileTime { get { return baseMethod.CanEvaluateAtCompileTime; } } - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + public override object Invoke(CSharpResolver resolver, object? lhs, object? rhs) { return baseMethod.Invoke(resolver, lhs, rhs); } @@ -764,11 +766,11 @@ public override object Invoke(CSharpResolver resolver, object lhs, object rhs) TypeCode.Boolean }; - OperatorMethod[] valueEqualityOperators; + OperatorMethod[]? valueEqualityOperators; public OperatorMethod[] ValueEqualityOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref valueEqualityOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref valueEqualityOperators); if (ops != null) { return ops; @@ -782,11 +784,11 @@ public OperatorMethod[] ValueEqualityOperators { } } - OperatorMethod[] valueInequalityOperators; + OperatorMethod[]? valueInequalityOperators; public OperatorMethod[] ValueInequalityOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref valueInequalityOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref valueInequalityOperators); if (ops != null) { return ops; @@ -800,11 +802,11 @@ public OperatorMethod[] ValueInequalityOperators { } } - OperatorMethod[] referenceEqualityOperators; + OperatorMethod[]? referenceEqualityOperators; public OperatorMethod[] ReferenceEqualityOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceEqualityOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref referenceEqualityOperators); if (ops != null) { return ops; @@ -819,11 +821,11 @@ public OperatorMethod[] ReferenceEqualityOperators { } } - OperatorMethod[] referenceInequalityOperators; + OperatorMethod[]? referenceInequalityOperators; public OperatorMethod[] ReferenceInequalityOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceInequalityOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref referenceInequalityOperators); if (ops != null) { return ops; @@ -857,7 +859,7 @@ public override bool CanEvaluateAtCompileTime { get { return true; } } - public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + public override object? Invoke(CSharpResolver resolver, object? lhs, object? rhs) { if (lhs == null || rhs == null) return null; @@ -873,11 +875,11 @@ public override OperatorMethod Lift(CSharpOperators operators) } } - OperatorMethod[] lessThanOperators; + OperatorMethod[]? lessThanOperators; public OperatorMethod[] LessThanOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref lessThanOperators); if (ops != null) { return ops; @@ -897,11 +899,11 @@ public OperatorMethod[] LessThanOperators { } } - OperatorMethod[] lessThanOrEqualOperators; + OperatorMethod[]? lessThanOrEqualOperators; public OperatorMethod[] LessThanOrEqualOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators); if (ops != null) { return ops; @@ -921,11 +923,11 @@ public OperatorMethod[] LessThanOrEqualOperators { } } - OperatorMethod[] greaterThanOperators; + OperatorMethod[]? greaterThanOperators; public OperatorMethod[] GreaterThanOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref greaterThanOperators); if (ops != null) { return ops; @@ -945,11 +947,11 @@ public OperatorMethod[] GreaterThanOperators { } } - OperatorMethod[] greaterThanOrEqualOperators; + OperatorMethod[]? greaterThanOrEqualOperators; public OperatorMethod[] GreaterThanOrEqualOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators); if (ops != null) { return ops; @@ -971,11 +973,11 @@ public OperatorMethod[] GreaterThanOrEqualOperators { #endregion #region Bitwise operators - OperatorMethod[] logicalAndOperators; + OperatorMethod[]? logicalAndOperators; public OperatorMethod[] LogicalAndOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalAndOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalAndOperators); if (ops != null) { return ops; @@ -990,11 +992,11 @@ public OperatorMethod[] LogicalAndOperators { } - OperatorMethod[] bitwiseAndOperators; + OperatorMethod[]? bitwiseAndOperators; public OperatorMethod[] BitwiseAndOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseAndOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseAndOperators); if (ops != null) { return ops; @@ -1013,11 +1015,11 @@ public OperatorMethod[] BitwiseAndOperators { } - OperatorMethod[] logicalOrOperators; + OperatorMethod[]? logicalOrOperators; public OperatorMethod[] LogicalOrOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalOrOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref logicalOrOperators); if (ops != null) { return ops; @@ -1031,11 +1033,11 @@ public OperatorMethod[] LogicalOrOperators { } } - OperatorMethod[] bitwiseOrOperators; + OperatorMethod[]? bitwiseOrOperators; public OperatorMethod[] BitwiseOrOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseOrOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseOrOperators); if (ops != null) { return ops; @@ -1057,11 +1059,11 @@ public OperatorMethod[] BitwiseOrOperators { // we produce "true | null" = "null" when it should be true. However, this is irrelevant // because bool? cannot be a compile-time type. - OperatorMethod[] bitwiseXorOperators; + OperatorMethod[]? bitwiseXorOperators; public OperatorMethod[] BitwiseXorOperators { get { - OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseXorOperators); + OperatorMethod[]? ops = LazyInit.VolatileRead(ref bitwiseXorOperators); if (ops != null) { return ops; @@ -1081,7 +1083,7 @@ public OperatorMethod[] BitwiseXorOperators { #endregion #region User-defined operators - public static IMethod LiftUserDefinedOperator(IMethod m) + public static IMethod? LiftUserDefinedOperator(IMethod m) { if (IsComparisonOperator(m)) { @@ -1129,9 +1131,9 @@ public LiftedUserDefinedOperator(IMethod nonLiftedMethod) public IReadOnlyList NonLiftedParameters => nonLiftedOperator.Parameters; public IType NonLiftedReturnType => nonLiftedOperator.ReturnType; - public override bool Equals(object obj) + public override bool Equals(object? obj) { - LiftedUserDefinedOperator op = obj as LiftedUserDefinedOperator; + LiftedUserDefinedOperator? op = obj as LiftedUserDefinedOperator; return op != null && this.nonLiftedOperator.Equals(op.nonLiftedOperator); } diff --git a/ICSharpCode.Decompiler/Util/CacheManager.cs b/ICSharpCode.Decompiler/Util/CacheManager.cs index 2c3bae3758..6ccb1e1414 100644 --- a/ICSharpCode.Decompiler/Util/CacheManager.cs +++ b/ICSharpCode.Decompiler/Util/CacheManager.cs @@ -34,9 +34,9 @@ public sealed class CacheManager // There used to be a thread-local dictionary here, but I removed it as it was causing memory // leaks in some use cases. - public object GetShared(object key) + public object? GetShared(object key) { - object value; + object? value; sharedDict.TryGetValue(key, out value); return value; } From cdff458648e70f53b8e6282b1608d9e1a3c6e464 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 19 Sep 2021 11:17:57 +0200 Subject: [PATCH 37/43] Fix test discovery with dotnet test. --- ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj | 1 + ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj | 1 + ILSpy.Tests/ILSpy.Tests.csproj | 1 + packages.props | 1 + 4 files changed, 4 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 71edc5762d..d043cccf53 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -52,6 +52,7 @@ + diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj index c31e409d64..986e28d298 100644 --- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj +++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -40,6 +40,7 @@ + diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj index 7ce61623a9..cda3327021 100644 --- a/ILSpy.Tests/ILSpy.Tests.csproj +++ b/ILSpy.Tests/ILSpy.Tests.csproj @@ -52,6 +52,7 @@ + diff --git a/packages.props b/packages.props index 6f28c66f8e..c6daebed2b 100644 --- a/packages.props +++ b/packages.props @@ -16,6 +16,7 @@ 2.6.1 3.13.2 4.0.0 + 16.11.0 4.16.1 2017.7.26.1241 1.1.0-beta2-20115-01 From 1568aeca3ed8ce0599142307326e357449ce62f3 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 19 Sep 2021 15:39:19 +0200 Subject: [PATCH 38/43] Fix #2506: NamedArgumentTransform loses information, if the original variable is of StackType.Ref --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 8 ++++---- ICSharpCode.Decompiler/IL/ILReader.cs | 2 +- .../IL/Transforms/CopyPropagation.cs | 2 +- .../IL/Transforms/ILExtraction.cs | 4 ++-- .../IL/Transforms/NamedArgumentTransform.cs | 2 +- .../IL/Transforms/NullableLiftingTransform.cs | 2 +- .../TypeSystem/ReflectionHelper.cs | 14 ++++++++++++++ 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index c5ebf5bf71..94d67b7c0d 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1618,7 +1618,7 @@ IType FindType(StackType stackType, Sign sign) } else { - return compilation.FindType(stackType.ToKnownTypeCode(sign)); + return compilation.FindType(stackType, sign); } } @@ -1644,7 +1644,7 @@ IType FindArithmeticType(StackType stackType, Sign sign) stackType = StackType.I8; } } - return compilation.FindType(stackType.ToKnownTypeCode(sign)); + return compilation.FindType(stackType, sign); } /// @@ -3568,7 +3568,7 @@ protected internal override TranslatedExpression VisitNullCoalescingInstruction( } else if (!value.Type.Equals(SpecialType.NullType) && !fallback.Type.Equals(SpecialType.NullType) && !value.Type.Equals(fallback.Type)) { - targetType = compilation.FindType(inst.UnderlyingResultType.ToKnownTypeCode()); + targetType = compilation.FindType(inst.UnderlyingResultType); } else { @@ -3731,7 +3731,7 @@ protected internal override TranslatedExpression VisitSwitchInstruction(SwitchIn } else { - resultType = compilation.FindType(inst.ResultType.ToKnownTypeCode()); + resultType = compilation.FindType(inst.ResultType); } foreach (var section in inst.Sections) diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 0f0a000dc6..83e78cb822 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -1170,7 +1170,7 @@ protected internal override ILInstruction VisitStLoc(StLoc inst) ILInstruction Push(ILInstruction inst) { Debug.Assert(inst.ResultType != StackType.Void); - IType type = compilation.FindType(inst.ResultType.ToKnownTypeCode()); + IType type = compilation.FindType(inst.ResultType); var v = new ILVariable(VariableKind.StackSlot, type, inst.ResultType); v.HasGeneratedName = true; currentStack = currentStack.Push(v); diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index 766da7b98a..1f3251fd2a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -148,7 +148,7 @@ static void DoPropagate(ILVariable v, ILInstruction copiedExpr, Block block, ref for (int j = 0; j < uninlinedArgs.Length; j++) { var arg = copiedExpr.Children[j]; - var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode()); + var type = context.TypeSystem.FindType(arg.ResultType); uninlinedArgs[j] = new ILVariable(VariableKind.StackSlot, type, arg.ResultType) { Name = "C_" + arg.StartILOffset, HasGeneratedName = true, diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs b/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs index 5840dffe17..55582a852f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs @@ -62,7 +62,7 @@ internal void RegisterMove(ILInstruction predecessor) { FlagsBeingMoved |= predecessor.Flags; MoveActions.Add(delegate { - var type = context.TypeSystem.FindType(predecessor.ResultType.ToKnownTypeCode()); + var type = context.TypeSystem.FindType(predecessor.ResultType); var v = Function.RegisterVariable(VariableKind.StackSlot, type); predecessor.ReplaceWith(new LdLoc(v)); return new StLoc(v, predecessor); @@ -119,7 +119,7 @@ public static ILVariable Extract(ILInstruction instToExtract, ILTransformContext { // We've reached the target block, and extraction is possible all the way. int insertIndex = inst.ChildIndex; - var type = context.TypeSystem.FindType(instToExtract.ResultType.ToKnownTypeCode()); + var type = context.TypeSystem.FindType(instToExtract.ResultType); // Move instToExtract itself: var v = function.RegisterVariable(VariableKind.StackSlot, type); instToExtract.ReplaceWith(new LdLoc(v)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs index 39bbfd4255..d2c5c400c0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs @@ -87,7 +87,7 @@ internal static void IntroduceNamedArgument(ILInstruction arg, ILTransformContex { var call = (CallInstruction)arg.Parent; Debug.Assert(context.Function == call.Ancestors.OfType().First()); - var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode()); + var type = context.TypeSystem.FindType(arg.ResultType); var v = context.Function.RegisterVariable(VariableKind.NamedArgument, type); context.Step($"Introduce named argument '{v.Name}'", arg); if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs) diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 45be721883..45429d8452 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -630,7 +630,7 @@ ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst) if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift)) { isNullCoalescingWithNonNullableFallback = true; - utype = context.TypeSystem.FindType(trueInst.ResultType.ToKnownTypeCode()); + utype = context.TypeSystem.FindType(trueInst.ResultType); exprToLift = trueInst; if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0])) { diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs index 4898ee5e1e..df8e396f12 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -66,6 +67,19 @@ public static IType FindType(this ICompilation compilation, Type type) { return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(compilation)); } + + public static IType FindType(this ICompilation compilation, StackType stackType, Sign sign = Sign.None) + { + switch (stackType) + { + case StackType.Unknown: + return SpecialType.UnknownType; + case StackType.Ref: + return new ByReferenceType(SpecialType.UnknownType); + default: + return compilation.FindType(stackType.ToKnownTypeCode(sign)); + } + } #endregion #region Type.ToTypeReference() From 47dcf0507fec0b39f99ae277c24711936114540d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 19 Sep 2021 19:48:10 +0200 Subject: [PATCH 39/43] #2500: nullable enable XmlDocumentationElement --- .../Documentation/XmlDocumentationElement.cs | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs index 61948f6ca3..ab1714e2a2 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#nullable enable + using System; using System.Collections.Generic; using System.Linq; @@ -40,10 +42,10 @@ static XmlDocumentationElement Create(string documentationComment, IEntity decla return new XmlDocumentationElement(XElement.Parse(documentationComment), declaringEntity, null); } - readonly XElement element; - readonly IEntity declaringEntity; - readonly Func crefResolver; - volatile string textContent; + readonly XElement? element; + readonly IEntity? declaringEntity; + readonly Func? crefResolver; + volatile string? textContent; /// /// Inheritance level; used to prevent cyclic doc inheritance. @@ -53,7 +55,7 @@ static XmlDocumentationElement Create(string documentationComment, IEntity decla /// /// Creates a new documentation element. /// - public XmlDocumentationElement(XElement element, IEntity declaringEntity, Func crefResolver) + public XmlDocumentationElement(XElement element, IEntity? declaringEntity, Func? crefResolver) { if (element == null) throw new ArgumentNullException(nameof(element)); @@ -65,7 +67,7 @@ public XmlDocumentationElement(XElement element, IEntity declaringEntity, Func /// Creates a new documentation element. /// - public XmlDocumentationElement(string text, IEntity declaringEntity) + public XmlDocumentationElement(string text, IEntity? declaringEntity) { if (text == null) throw new ArgumentNullException(nameof(text)); @@ -77,26 +79,26 @@ public XmlDocumentationElement(string text, IEntity declaringEntity) /// Gets the entity on which this documentation was originally declared. /// May return null. /// - public IEntity DeclaringEntity { + public IEntity? DeclaringEntity { get { return declaringEntity; } } - IEntity referencedEntity; + IEntity? referencedEntity; volatile bool referencedEntityInitialized; /// /// Gets the entity referenced by the 'cref' attribute. /// May return null. /// - public IEntity ReferencedEntity { + public IEntity? ReferencedEntity { get { if (!referencedEntityInitialized) { - string cref = GetAttribute("cref"); + string? cref = GetAttribute("cref"); try { if (!string.IsNullOrEmpty(cref) && crefResolver != null) - referencedEntity = crefResolver(cref); + referencedEntity = crefResolver(cref!); } catch { @@ -120,7 +122,7 @@ public string Name { /// /// Gets the attribute value. /// - public string GetAttribute(string name) + public string? GetAttribute(string? name) { return element?.Attribute(name)?.Value; } @@ -148,7 +150,7 @@ public string TextContent { } } - IList children; + IList? children; /// /// Gets the child elements. @@ -159,7 +161,7 @@ public IList Children { return EmptyList.Instance; return LazyInitializer.EnsureInitialized( ref this.children, - () => CreateElements(element.Nodes(), declaringEntity, crefResolver, nestingLevel)); + () => CreateElements(element.Nodes(), declaringEntity, crefResolver, nestingLevel))!; } } @@ -168,7 +170,7 @@ public IList Children { "remarks", "returns", "threadsafety", "value" }; - static List CreateElements(IEnumerable childObjects, IEntity declaringEntity, Func crefResolver, int nestingLevel) + static List CreateElements(IEnumerable childObjects, IEntity? declaringEntity, Func? crefResolver, int nestingLevel) { List list = new List(); foreach (var child in childObjects) @@ -189,9 +191,9 @@ static List CreateElements(IEnumerable childOb if (nestingLevel < 5 && childElement.Name == "inheritdoc") { string cref = childElement.Attribute("cref").Value; - IEntity inheritedFrom = null; - string inheritedDocumentation = null; - if (cref != null) + IEntity? inheritedFrom = null; + string? inheritedDocumentation = null; + if (cref != null && crefResolver != null) { inheritedFrom = crefResolver(cref); if (inheritedFrom != null) @@ -225,7 +227,7 @@ static List CreateElements(IEnumerable childOb var inheritedChildren = doc.Nodes().Where( inheritedObject => { - XElement inheritedElement = inheritedObject as XElement; + XElement? inheritedElement = inheritedObject as XElement; return !(inheritedElement != null && doNotInherit.Contains(inheritedElement.Name.LocalName)); }); @@ -244,14 +246,14 @@ static List CreateElements(IEnumerable childOb if (string.IsNullOrWhiteSpace(list[0].textContent)) list.RemoveAt(0); else - list[0].textContent = list[0].textContent.TrimStart(); + list[0].textContent = list[0].textContent!.TrimStart(); } if (list.Count > 0 && list[list.Count - 1].IsTextNode) { if (string.IsNullOrWhiteSpace(list[list.Count - 1].textContent)) list.RemoveAt(list.Count - 1); else - list[list.Count - 1].textContent = list[list.Count - 1].textContent.TrimEnd(); + list[list.Count - 1].textContent = list[list.Count - 1].textContent!.TrimEnd(); } return list; } From 6628e0a410f488b84ba0f0d1c2812dafe17a8c00 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 19 Sep 2021 19:50:17 +0200 Subject: [PATCH 40/43] Fix #2500: NRE and other bugs when hovering over symbol with . --- .../Documentation/XmlDocumentationElement.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs index ab1714e2a2..9b6b51ac00 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs @@ -190,23 +190,24 @@ static List CreateElements(IEnumerable childO { if (nestingLevel < 5 && childElement.Name == "inheritdoc") { - string cref = childElement.Attribute("cref").Value; + string? cref = childElement.Attribute("cref")?.Value; IEntity? inheritedFrom = null; string? inheritedDocumentation = null; if (cref != null && crefResolver != null) { inheritedFrom = crefResolver(cref); if (inheritedFrom != null) - inheritedDocumentation = inheritedFrom.GetDocumentation(); + inheritedDocumentation = "" + inheritedFrom.GetDocumentation() + ""; } else { - foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember)declaringEntity, includeImplementedInterfaces: true)) + foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember?)declaringEntity, includeImplementedInterfaces: true)) { inheritedDocumentation = baseMember.GetDocumentation(); if (inheritedDocumentation != null) { inheritedFrom = baseMember; + inheritedDocumentation = "" + inheritedDocumentation + ""; break; } } @@ -214,10 +215,10 @@ static List CreateElements(IEnumerable childO if (inheritedDocumentation != null) { - var doc = XDocument.Parse(inheritedDocumentation); + var doc = XDocument.Parse(inheritedDocumentation).Element("doc"); // XPath filter not yet implemented - if (childElement.Parent == null && childElement.Attribute("select").Value == null) + if (childElement.Parent?.Parent == null && childElement.Attribute("select")?.Value == null) { // Inheriting documentation at the root level List doNotInherit = new List(); From 6cc89378aa9f71ad39ed02ee7a53f4c8940fc493 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 19 Sep 2021 19:50:53 +0200 Subject: [PATCH 41/43] Remove unused code. --- .../Documentation/XmlDocumentationElement.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs index 9b6b51ac00..088f6808bb 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs @@ -25,7 +25,6 @@ using System.Threading; using System.Xml.Linq; -using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -37,11 +36,6 @@ namespace ICSharpCode.Decompiler.Documentation /// public class XmlDocumentationElement { - static XmlDocumentationElement Create(string documentationComment, IEntity declaringEntity) - { - return new XmlDocumentationElement(XElement.Parse(documentationComment), declaringEntity, null); - } - readonly XElement? element; readonly IEntity? declaringEntity; readonly Func? crefResolver; From a917690fdf503306b138184c7e1b7d30f7339419 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Mon, 27 Sep 2021 12:51:07 +0800 Subject: [PATCH 42/43] Fix null check in BamlDecompilerTypeSystem.HasType --- ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs b/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs index 7276bd047b..f43a2d28c5 100644 --- a/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs +++ b/ILSpy.BamlDecompiler/BamlDecompilerTypeSystem.cs @@ -128,11 +128,11 @@ public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyRes bool HasType(KnownTypeCode code) { TopLevelTypeName name = KnownTypeReference.Get(code).TypeName; - if (mainModule.GetTypeDefinition(name) != null) + if (!mainModule.GetTypeDefinition(name).IsNil) return true; foreach (var file in referencedAssemblies) { - if (file.GetTypeDefinition(name) != null) + if (!file.GetTypeDefinition(name).IsNil) return true; } return false; From 9d99ee86db979a441c96dd8b58c21a59afdcb5ba Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 2 Oct 2021 13:17:09 +0200 Subject: [PATCH 43/43] Fix #2503: Move correct branch in the case of swapped jump-table conditions. --- .../IL/ControlFlow/AwaitInFinallyTransform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs index d84dc5ee57..b6205914b5 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs @@ -157,7 +157,7 @@ public static void Run(ILFunction function, ILTransformContext context) { identifierValueTargets.Add(value, otherBranch.TargetBlock); block.Instructions.RemoveAt(statement.ChildIndex + 1); - statement.ReplaceWith(otherBranch); + statement.ReplaceWith(branchToTarget); } else {