From 488bf585da5c9041ca00804a1ee595580c395cdf Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Wed, 15 Jul 2020 23:54:40 +0800 Subject: [PATCH 01/92] All the new Chinese statements has been translated --- ILSpy-tests | 2 +- ILSpy.AddIn/ILSpy.AddIn.csproj | 1 + ILSpy.AddIn/VSPackage.zh-Hans.resx | 120 ++++++ ILSpy/Properties/Resources.Designer.cs | 541 ++++++++++++------------ ILSpy/Properties/Resources.zh-Hans.resx | 188 ++++++-- 5 files changed, 551 insertions(+), 301 deletions(-) create mode 100644 ILSpy.AddIn/VSPackage.zh-Hans.resx diff --git a/ILSpy-tests b/ILSpy-tests index aa8f1197e..e83c25d91 160000 --- a/ILSpy-tests +++ b/ILSpy-tests @@ -1 +1 @@ -Subproject commit aa8f1197e6a513bcc10bcc38ec7d2143d27a2246 +Subproject commit e83c25d910124986a42089055ecff70682c4fdb9 diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 5a96857ac..64fc6e596 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -89,6 +89,7 @@ true VSPackage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 50e640b22..ce852aecd 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace ICSharpCode.ILSpy.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _About. + /// 查找类似 _About 的本地化字符串。 /// public static string _About { get { @@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Add To Main List. + /// 查找类似 _Add To Main List 的本地化字符串。 /// public static string _AddMainList { get { @@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Check for Updates. + /// 查找类似 _Check for Updates 的本地化字符串。 /// public static string _CheckUpdates { get { @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Collapse all tree nodes. + /// 查找类似 _Collapse all tree nodes 的本地化字符串。 /// public static string _CollapseTreeNodes { get { @@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _File. + /// 查找类似 _File 的本地化字符串。 /// public static string _File { get { @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Help. + /// 查找类似 _Help 的本地化字符串。 /// public static string _Help { get { @@ -115,7 +115,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Load Dependencies. + /// 查找类似 _Load Dependencies 的本地化字符串。 /// public static string _LoadDependencies { get { @@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _New. + /// 查找类似 _New 的本地化字符串。 /// public static string _New { get { @@ -133,7 +133,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open.... + /// 查找类似 _Open... 的本地化字符串。 /// public static string _Open { get { @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open Command Line Here. + /// 查找类似 _Open Command Line Here 的本地化字符串。 /// public static string _OpenCommandLineHere { get { @@ -151,7 +151,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open Containing Folder. + /// 查找类似 _Open Containing Folder 的本地化字符串。 /// public static string _OpenContainingFolder { get { @@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Options.... + /// 查找类似 _Options... 的本地化字符串。 /// public static string _Options { get { @@ -169,7 +169,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Reload. + /// 查找类似 _Reload 的本地化字符串。 /// public static string _Reload { get { @@ -178,7 +178,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Remove. + /// 查找类似 _Remove 的本地化字符串。 /// public static string _Remove { get { @@ -187,7 +187,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Remove Assemblies with load errors. + /// 查找类似 _Remove Assemblies with load errors 的本地化字符串。 /// public static string _RemoveAssembliesWithLoadErrors { get { @@ -196,7 +196,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Reset. + /// 查找类似 _Reset 的本地化字符串。 /// public static string _Reset { get { @@ -205,7 +205,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Resources. + /// 查找类似 Resources 的本地化字符串。 /// public static string _Resources { get { @@ -214,7 +214,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Save Code.... + /// 查找类似 _Save Code... 的本地化字符串。 /// public static string _SaveCode { get { @@ -223,7 +223,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Search:. + /// 查找类似 _Search: 的本地化字符串。 /// public static string _Search { get { @@ -232,7 +232,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Search for:. + /// 查找类似 _Search for: 的本地化字符串。 /// public static string _SearchFor { get { @@ -241,7 +241,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Show debug steps. + /// 查找类似 _Show debug steps 的本地化字符串。 /// public static string _ShowDebugSteps { get { @@ -250,7 +250,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Toggle Folding. + /// 查找类似 Toggle Folding 的本地化字符串。 /// public static string _ToggleFolding { get { @@ -259,7 +259,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _View. + /// 查找类似 _View 的本地化字符串。 /// public static string _View { get { @@ -268,7 +268,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Window. + /// 查找类似 _Window 的本地化字符串。 /// public static string _Window { get { @@ -277,7 +277,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to About. + /// 查找类似 About 的本地化字符串。 /// public static string About { get { @@ -286,7 +286,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Add preconfigured list.... + /// 查找类似 Add preconfigured list... 的本地化字符串。 /// public static string AddPreconfiguredList { get { @@ -295,7 +295,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Add shell integration. + /// 查找类似 Add shell integration 的本地化字符串。 /// public static string AddShellIntegration { get { @@ -304,9 +304,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. + /// 查找类似 This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. /// - ///Do you want to continue?. + ///Do you want to continue? 的本地化字符串。 /// public static string AddShellIntegrationMessage { get { @@ -315,7 +315,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to |All Files|*.*. + /// 查找类似 |All Files|*.* 的本地化字符串。 /// public static string AllFiles { get { @@ -324,7 +324,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Allow multiple instances. + /// 查找类似 Allow multiple instances 的本地化字符串。 /// public static string AllowMultipleInstances { get { @@ -333,7 +333,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always use braces. + /// 查找类似 Always use braces 的本地化字符串。 /// public static string AlwaysBraces { get { @@ -342,7 +342,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Analyze. + /// 查找类似 Analyze 的本地化字符串。 /// public static string Analyze { get { @@ -351,7 +351,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Assemblies. + /// 查找类似 Assemblies 的本地化字符串。 /// public static string Assemblies { get { @@ -360,7 +360,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Assembly. + /// 查找类似 Assembly 的本地化字符串。 /// public static string Assembly { get { @@ -369,8 +369,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to The directory is not empty. File will be overwritten. - ///Are you sure you want to continue?. + /// 查找类似 The directory is not empty. File will be overwritten. + ///Are you sure you want to continue? 的本地化字符串。 /// public static string AssemblySaveCodeDirectoryNotEmpty { get { @@ -379,7 +379,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Project Directory not empty. + /// 查找类似 Project Directory not empty 的本地化字符串。 /// public static string AssemblySaveCodeDirectoryNotEmptyTitle { get { @@ -388,7 +388,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Automatically check for updates every week. + /// 查找类似 Automatically check for updates every week 的本地化字符串。 /// public static string AutomaticallyCheckUpdatesEveryWeek { get { @@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Back. + /// 查找类似 Back 的本地化字符串。 /// public static string Back { get { @@ -406,7 +406,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to C_lone. + /// 查找类似 C_lone 的本地化字符串。 /// public static string C_lone { get { @@ -415,7 +415,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Cancel. + /// 查找类似 Cancel 的本地化字符串。 /// public static string Cancel { get { @@ -424,7 +424,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again.. + /// 查找类似 Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. 的本地化字符串。 /// public static string CannotAnalyzeMissingRef { get { @@ -433,7 +433,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Check again. + /// 查找类似 Check again 的本地化字符串。 /// public static string CheckAgain { get { @@ -442,7 +442,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Checking.... + /// 查找类似 Checking... 的本地化字符串。 /// public static string Checking { get { @@ -451,7 +451,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Check for updates. + /// 查找类似 Check for updates 的本地化字符串。 /// public static string CheckUpdates { get { @@ -460,7 +460,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Close. + /// 查找类似 Close 的本地化字符串。 /// public static string Close { get { @@ -469,7 +469,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Collapse all tree nodes. + /// 查找类似 Collapse all tree nodes 的本地化字符串。 /// public static string CollapseTreeNodes { get { @@ -478,7 +478,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy. + /// 查找类似 Copy 的本地化字符串。 /// public static string Copy { get { @@ -487,7 +487,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy error message. + /// 查找类似 Copy error message 的本地化字符串。 /// public static string CopyErrorMessage { get { @@ -496,7 +496,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy FQ Name. + /// 查找类似 Copy FQ Name 的本地化字符串。 /// public static string CopyName { get { @@ -505,7 +505,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Create. + /// 查找类似 Create 的本地化字符串。 /// public static string Create { get { @@ -514,7 +514,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Culture. + /// 查找类似 Culture 的本地化字符串。 /// public static string CultureLabel { get { @@ -523,7 +523,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Decompile All. + /// 查找类似 DEBUG -- Decompile All 的本地化字符串。 /// public static string DEBUGDecompile { get { @@ -532,7 +532,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Decompile 100x. + /// 查找类似 DEBUG -- Decompile 100x 的本地化字符串。 /// public static string DEBUGDecompile100x { get { @@ -541,7 +541,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Disassemble All. + /// 查找类似 DEBUG -- Disassemble All 的本地化字符串。 /// public static string DEBUGDisassemble { get { @@ -550,7 +550,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Debug Steps. + /// 查找类似 Debug Steps 的本地化字符串。 /// public static string DebugSteps { get { @@ -559,7 +559,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Debug this step. + /// 查找类似 Debug this step 的本地化字符串。 /// public static string DebugThisStep { get { @@ -568,7 +568,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompiler. + /// 查找类似 Decompiler 的本地化字符串。 /// public static string Decompiler { get { @@ -577,16 +577,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Aggressively perform Scalar Replacement Of Aggregates (SROA). - /// - public static string DecompilerSettings_AggressiveScalarReplacementOfAggregates { - get { - return ResourceManager.GetString("DecompilerSettings.AggressiveScalarReplacementOfAggregates", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Allow extension 'Add' methods in collection initializer expressions. + /// 查找类似 Allow extension 'Add' methods in collection initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_AllowExtensionAddMethodsInCollectionInitializerExpressions { get { @@ -595,7 +586,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use 'ref' extension methods. + /// 查找类似 Use 'ref' extension methods 的本地化字符串。 /// public static string DecompilerSettings_AllowExtensionMethodSyntaxOnRef { get { @@ -604,7 +595,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always cast targets of explicit interface implementation calls. + /// 查找类似 Always cast targets of explicit interface implementation calls 的本地化字符串。 /// public static string DecompilerSettings_AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { get { @@ -613,7 +604,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always show enum member values. + /// 查找类似 Always show enum member values 的本地化字符串。 /// public static string DecompilerSettings_AlwaysShowEnumMemberValues { get { @@ -622,7 +613,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always use braces. + /// 查找类似 Always use braces 的本地化字符串。 /// public static string DecompilerSettings_AlwaysUseBraces { get { @@ -631,7 +622,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Apply Windows Runtime projections on loaded assemblies. + /// 查找类似 Apply Windows Runtime projections on loaded assemblies 的本地化字符串。 /// public static string DecompilerSettings_ApplyWindowsRuntimeProjectionsOnLoadedAssemblies { get { @@ -640,7 +631,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Array initializer expressions. + /// 查找类似 Array initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_ArrayInitializerExpressions { get { @@ -649,7 +640,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile async IAsyncEnumerator methods. + /// 查找类似 Decompile async IAsyncEnumerator methods 的本地化字符串。 /// public static string DecompilerSettings_AsyncEnumerator { get { @@ -658,7 +649,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile ?. and ?[] operators. + /// 查找类似 Decompile ?. and ?[] operators 的本地化字符串。 /// public static string DecompilerSettings_DecompileAndOperators { get { @@ -667,7 +658,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile anonymous methods/lambdas. + /// 查找类似 Decompile anonymous methods/lambdas 的本地化字符串。 /// public static string DecompilerSettings_DecompileAnonymousMethodsLambdas { get { @@ -676,7 +667,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile anonymous types. + /// 查找类似 Decompile anonymous types 的本地化字符串。 /// public static string DecompilerSettings_DecompileAnonymousTypes { get { @@ -685,7 +676,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile async methods. + /// 查找类似 Decompile async methods 的本地化字符串。 /// public static string DecompilerSettings_DecompileAsyncMethods { get { @@ -694,7 +685,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile automatic events. + /// 查找类似 Decompile automatic events 的本地化字符串。 /// public static string DecompilerSettings_DecompileAutomaticEvents { get { @@ -703,7 +694,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile automatic properties. + /// 查找类似 Decompile automatic properties 的本地化字符串。 /// public static string DecompilerSettings_DecompileAutomaticProperties { get { @@ -712,7 +703,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile await in catch/finally blocks. + /// 查找类似 Decompile await in catch/finally blocks 的本地化字符串。 /// public static string DecompilerSettings_DecompileAwaitInCatchFinallyBlocks { get { @@ -721,7 +712,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile C# 1.0 'public unsafe fixed int arr[10];' members. + /// 查找类似 Decompile C# 1.0 'public unsafe fixed int arr[10];' members 的本地化字符串。 /// public static string DecompilerSettings_DecompileC10PublicUnsafeFixedIntArr10Members { get { @@ -730,7 +721,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile [DecimalConstant(...)] as simple literal values. + /// 查找类似 Decompile [DecimalConstant(...)] as simple literal values 的本地化字符串。 /// public static string DecompilerSettings_DecompileDecimalConstantAsSimpleLiteralValues { get { @@ -739,7 +730,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile enumerators (yield return). + /// 查找类似 Decompile enumerators (yield return) 的本地化字符串。 /// public static string DecompilerSettings_DecompileEnumeratorsYieldReturn { get { @@ -748,7 +739,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile expression trees. + /// 查找类似 Decompile expression trees 的本地化字符串。 /// public static string DecompilerSettings_DecompileExpressionTrees { get { @@ -757,7 +748,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile use of the 'dynamic' type. + /// 查找类似 Decompile use of the 'dynamic' type 的本地化字符串。 /// public static string DecompilerSettings_DecompileUseOfTheDynamicType { get { @@ -766,7 +757,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect awaited using and foreach statements. + /// 查找类似 Detect awaited using and foreach statements 的本地化字符串。 /// public static string DecompilerSettings_DetectAsyncUsingAndForeachStatements { get { @@ -775,7 +766,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect foreach statements. + /// 查找类似 Detect foreach statements 的本地化字符串。 /// public static string DecompilerSettings_DetectForeachStatements { get { @@ -784,7 +775,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect lock statements. + /// 查找类似 Detect lock statements 的本地化字符串。 /// public static string DecompilerSettings_DetectLockStatements { get { @@ -793,7 +784,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect switch on string. + /// 查找类似 Detect switch on string 的本地化字符串。 /// public static string DecompilerSettings_DetectSwitchOnString { get { @@ -802,7 +793,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect tuple comparisons. + /// 查找类似 Detect tuple comparisons 的本地化字符串。 /// public static string DecompilerSettings_DetectTupleComparisons { get { @@ -811,7 +802,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect using statements. + /// 查找类似 Detect using statements 的本地化字符串。 /// public static string DecompilerSettings_DetectUsingStatements { get { @@ -820,7 +811,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Dictionary initializer expressions. + /// 查找类似 Dictionary initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_DictionaryInitializerExpressions { get { @@ -829,7 +820,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Transform to do-while, if possible.. + /// 查找类似 Transform to do-while, if possible. 的本地化字符串。 /// public static string DecompilerSettings_DoWhileStatement { get { @@ -838,7 +829,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Transform to for, if possible.. + /// 查找类似 Transform to for, if possible. 的本地化字符串。 /// public static string DecompilerSettings_ForStatement { get { @@ -847,7 +838,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to F#-specific options. + /// 查找类似 F#-specific options 的本地化字符串。 /// public static string DecompilerSettings_FSpecificOptions { get { @@ -856,7 +847,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Include XML documentation comments in the decompiled code. + /// 查找类似 Include XML documentation comments in the decompiled code 的本地化字符串。 /// public static string DecompilerSettings_IncludeXMLDocumentationCommentsInTheDecompiledCode { get { @@ -865,7 +856,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Insert using declarations. + /// 查找类似 Insert using declarations 的本地化字符串。 /// public static string DecompilerSettings_InsertUsingDeclarations { get { @@ -874,7 +865,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Introduce local functions. + /// 查找类似 Introduce local functions 的本地化字符串。 /// public static string DecompilerSettings_IntroduceLocalFunctions { get { @@ -883,7 +874,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Introduce static local functions. + /// 查找类似 Introduce static local functions 的本地化字符串。 /// public static string DecompilerSettings_IntroduceStaticLocalFunctions { get { @@ -892,7 +883,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs. + /// 查找类似 IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs 的本地化字符串。 /// public static string DecompilerSettings_IsByRefLikeAttributeShouldBeReplacedWithRefModifiersOnStructs { get { @@ -901,7 +892,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters. + /// 查找类似 IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters 的本地化字符串。 /// public static string DecompilerSettings_IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters { get { @@ -911,7 +902,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints. + /// 查找类似 IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints 的本地化字符串。 /// public static string DecompilerSettings_IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints { get { @@ -921,7 +912,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Nullable reference types. + /// 查找类似 Nullable reference types 的本地化字符串。 /// public static string DecompilerSettings_NullableReferenceTypes { get { @@ -930,7 +921,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Object/collection initializer expressions. + /// 查找类似 Object/collection initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_ObjectCollectionInitializerExpressions { get { @@ -939,7 +930,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other. + /// 查找类似 Other 的本地化字符串。 /// public static string DecompilerSettings_Other { get { @@ -948,7 +939,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Ranges. + /// 查找类似 Ranges 的本地化字符串。 /// public static string DecompilerSettings_Ranges { get { @@ -957,7 +948,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Read-only methods. + /// 查找类似 Read-only methods 的本地化字符串。 /// public static string DecompilerSettings_ReadOnlyMethods { get { @@ -966,7 +957,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead and side effect free code (use with caution!). + /// 查找类似 Remove dead and side effect free code (use with caution!) 的本地化字符串。 /// public static string DecompilerSettings_RemoveDeadAndSideEffectFreeCodeUseWithCaution { get { @@ -975,7 +966,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead stores (use with caution!). + /// 查找类似 Remove dead stores (use with caution!) 的本地化字符串。 /// public static string DecompilerSettings_RemoveDeadStores { get { @@ -984,7 +975,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove optional arguments, if possible. + /// 查找类似 Remove optional arguments, if possible 的本地化字符串。 /// public static string DecompilerSettings_RemoveOptionalArgumentsIfPossible { get { @@ -993,7 +984,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible.. + /// 查找类似 Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible. 的本地化字符串。 /// public static string DecompilerSettings_SeparateLocalVariableDeclarations { get { @@ -1002,7 +993,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show info from debug symbols, if available. + /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 /// public static string DecompilerSettings_ShowInfoFromDebugSymbolsIfAvailable { get { @@ -1011,7 +1002,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use discards. + /// 查找类似 Use discards 的本地化字符串。 /// public static string DecompilerSettings_UseDiscards { get { @@ -1020,7 +1011,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use expression-bodied member syntax for get-only properties. + /// 查找类似 Use expression-bodied member syntax for get-only properties 的本地化字符串。 /// public static string DecompilerSettings_UseExpressionBodiedMemberSyntaxForGetOnlyProperties { get { @@ -1029,7 +1020,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use extension method syntax. + /// 查找类似 Use extension method syntax 的本地化字符串。 /// public static string DecompilerSettings_UseExtensionMethodSyntax { get { @@ -1038,7 +1029,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use implicit conversions between tuple types. + /// 查找类似 Use implicit conversions between tuple types 的本地化字符串。 /// public static string DecompilerSettings_UseImplicitConversionsBetweenTupleTypes { get { @@ -1047,7 +1038,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use implicit method group conversions. + /// 查找类似 Use implicit method group conversions 的本地化字符串。 /// public static string DecompilerSettings_UseImplicitMethodGroupConversions { get { @@ -1056,7 +1047,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use lambda syntax, if possible. + /// 查找类似 Use lambda syntax, if possible 的本地化字符串。 /// public static string DecompilerSettings_UseLambdaSyntaxIfPossible { get { @@ -1065,7 +1056,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use lifted operators for nullables. + /// 查找类似 Use lifted operators for nullables 的本地化字符串。 /// public static string DecompilerSettings_UseLiftedOperatorsForNullables { get { @@ -1074,7 +1065,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use LINQ expression syntax. + /// 查找类似 Use LINQ expression syntax 的本地化字符串。 /// public static string DecompilerSettings_UseLINQExpressionSyntax { get { @@ -1083,7 +1074,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use named arguments. + /// 查找类似 Use named arguments 的本地化字符串。 /// public static string DecompilerSettings_UseNamedArguments { get { @@ -1092,7 +1083,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use non-trailing named arguments. + /// 查找类似 Use non-trailing named arguments 的本地化字符串。 /// public static string DecompilerSettings_UseNonTrailingNamedArguments { get { @@ -1101,7 +1092,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use out variable declarations. + /// 查找类似 Use out variable declarations 的本地化字符串。 /// public static string DecompilerSettings_UseOutVariableDeclarations { get { @@ -1110,7 +1101,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use pattern-based fixed statement. + /// 查找类似 Use pattern-based fixed statement 的本地化字符串。 /// public static string DecompilerSettings_UsePatternBasedFixedStatement { get { @@ -1119,7 +1110,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use new SDK style format for generated project files (*.csproj). + /// 查找类似 Use new SDK style format for generated project files (*.csproj) 的本地化字符串。 /// public static string DecompilerSettings_UseSdkStyleProjectFormat { get { @@ -1128,7 +1119,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use stackalloc initializer syntax. + /// 查找类似 Use stackalloc initializer syntax 的本地化字符串。 /// public static string DecompilerSettings_UseStackallocInitializerSyntax { get { @@ -1137,7 +1128,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use string interpolation. + /// 查找类似 Use string interpolation 的本地化字符串。 /// public static string DecompilerSettings_UseStringInterpolation { get { @@ -1146,7 +1137,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use throw expressions. + /// 查找类似 Use throw expressions 的本地化字符串。 /// public static string DecompilerSettings_UseThrowExpressions { get { @@ -1155,7 +1146,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use tuple type syntax. + /// 查找类似 Use tuple type syntax 的本地化字符串。 /// public static string DecompilerSettings_UseTupleTypeSyntax { get { @@ -1164,7 +1155,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use variable names from debug symbols, if available. + /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 /// public static string DecompilerSettings_UseVariableNamesFromDebugSymbolsIfAvailable { get { @@ -1173,7 +1164,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to VB-specific options. + /// 查找类似 VB-specific options 的本地化字符串。 /// public static string DecompilerSettings_VBSpecificOptions { get { @@ -1182,7 +1173,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls.. + /// 查找类似 The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls. 的本地化字符串。 /// public static string DecompilerSettingsPanelLongText { get { @@ -1191,7 +1182,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile to new tab. + /// 查找类似 Decompile to new tab 的本地化字符串。 /// public static string DecompileToNewPanel { get { @@ -1200,7 +1191,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompiling.... + /// 查找类似 Decompiling... 的本地化字符串。 /// public static string Decompiling { get { @@ -1209,7 +1200,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Dependencies. + /// 查找类似 Dependencies 的本地化字符串。 /// public static string Dependencies { get { @@ -1218,7 +1209,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Derived Types. + /// 查找类似 Derived Types 的本地化字符串。 /// public static string DerivedTypes { get { @@ -1227,7 +1218,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Display. + /// 查找类似 Display 的本地化字符串。 /// public static string Display { get { @@ -1236,7 +1227,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Display Code. + /// 查找类似 Display Code 的本地化字符串。 /// public static string DisplayCode { get { @@ -1245,7 +1236,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Font:. + /// 查找类似 Font: 的本地化字符串。 /// public static string DisplaySettingsPanel_Font { get { @@ -1254,7 +1245,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Download. + /// 查找类似 Download 的本地化字符串。 /// public static string Download { get { @@ -1263,7 +1254,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to E_xit. + /// 查找类似 E_xit 的本地化字符串。 /// public static string E_xit { get { @@ -1272,7 +1263,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Editor. + /// 查找类似 Editor 的本地化字符串。 /// public static string Editor { get { @@ -1281,7 +1272,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enable folding on all blocks in braces. + /// 查找类似 Enable folding on all blocks in braces 的本地化字符串。 /// public static string EnableFoldingBlocksBraces { get { @@ -1290,7 +1281,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enable word wrap. + /// 查找类似 Enable word wrap 的本地化字符串。 /// public static string EnableWordWrap { get { @@ -1299,7 +1290,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enter a list name:. + /// 查找类似 Enter a list name: 的本地化字符串。 /// public static string EnterListName { get { @@ -1308,7 +1299,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Exit. + /// 查找类似 Exit 的本地化字符串。 /// public static string Exit { get { @@ -1317,7 +1308,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Expand member definitions after decompilation. + /// 查找类似 Expand member definitions after decompilation 的本地化字符串。 /// public static string ExpandMemberDefinitionsAfterDecompilation { get { @@ -1326,7 +1317,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Expand using declarations after decompilation. + /// 查找类似 Expand using declarations after decompilation 的本地化字符串。 /// public static string ExpandUsingDeclarationsAfterDecompilation { get { @@ -1335,7 +1326,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Folding. + /// 查找类似 Folding 的本地化字符串。 /// public static string Folding { get { @@ -1344,7 +1335,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Font. + /// 查找类似 Font 的本地化字符串。 /// public static string Font { get { @@ -1353,7 +1344,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Forward. + /// 查找类似 Forward 的本地化字符串。 /// public static string Forward { get { @@ -1362,7 +1353,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Generate portable PDB. + /// 查找类似 Generate portable PDB 的本地化字符串。 /// public static string GeneratePortable { get { @@ -1371,7 +1362,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Hide empty metadata tables from tree view. + /// 查找类似 Hide empty metadata tables from tree view 的本地化字符串。 /// public static string HideEmptyMetadataTables { get { @@ -1380,7 +1371,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Highlight matching braces. + /// 查找类似 Highlight matching braces 的本地化字符串。 /// public static string HighlightMatchingBraces { get { @@ -1389,7 +1380,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ILSpy version . + /// 查找类似 ILSpy version 的本地化字符串。 /// public static string ILSpyVersion { get { @@ -1398,7 +1389,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to A new ILSpy version is available.. + /// 查找类似 A new ILSpy version is available. 的本地化字符串。 /// public static string ILSpyVersionAvailable { get { @@ -1407,7 +1398,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Indentation. + /// 查找类似 Indentation 的本地化字符串。 /// public static string Indentation { get { @@ -1416,7 +1407,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Indent size:. + /// 查找类似 Indent size: 的本地化字符串。 /// public static string IndentSize { get { @@ -1425,7 +1416,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Insert using declarations. + /// 查找类似 Insert using declarations 的本地化字符串。 /// public static string InsertUsingDeclarations { get { @@ -1434,7 +1425,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Are you sure that you want to delete the selected assembly list?. + /// 查找类似 Are you sure that you want to delete the selected assembly list? 的本地化字符串。 /// public static string ListDeleteConfirmation { get { @@ -1443,7 +1434,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to A list with the same name was found.. + /// 查找类似 A list with the same name was found. 的本地化字符串。 /// public static string ListExistsAlready { get { @@ -1452,7 +1443,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Are you sure that you want to remove all assembly lists and recreate the default assembly lists?. + /// 查找类似 Are you sure that you want to remove all assembly lists and recreate the default assembly lists? 的本地化字符串。 /// public static string ListsResetConfirmation { get { @@ -1461,7 +1452,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Load assemblies that were loaded in the last instance.. + /// 查找类似 Load assemblies that were loaded in the last instance. 的本地化字符串。 /// public static string LoadAssembliesThatWereLoadedInTheLastInstance { get { @@ -1470,7 +1461,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Loading.... + /// 查找类似 Loading... 的本地化字符串。 /// public static string Loading { get { @@ -1479,7 +1470,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Location. + /// 查找类似 Location 的本地化字符串。 /// public static string Location { get { @@ -1488,7 +1479,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Manage assembly _lists.... + /// 查找类似 Manage assembly _lists... 的本地化字符串。 /// public static string ManageAssembly_Lists { get { @@ -1497,7 +1488,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Manage Assembly Lists. + /// 查找类似 Manage Assembly Lists 的本地化字符串。 /// public static string ManageAssemblyLists { get { @@ -1506,7 +1497,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Misc. + /// 查找类似 Misc 的本地化字符串。 /// public static string Misc { get { @@ -1515,7 +1506,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Name. + /// 查找类似 Name 的本地化字符串。 /// public static string Name { get { @@ -1524,7 +1515,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Navigation. + /// 查找类似 Navigation 的本地化字符串。 /// public static string Navigation { get { @@ -1533,8 +1524,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Navigation failed because the target is hidden or a compiler-generated class.\n - ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again.. + /// 查找类似 Navigation failed because the target is hidden or a compiler-generated class.\n + ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again. 的本地化字符串。 /// public static string NavigationFailed { get { @@ -1543,7 +1534,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to New list. + /// 查找类似 New list 的本地化字符串。 /// public static string NewList { get { @@ -1552,7 +1543,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to New Tab. + /// 查找类似 New Tab 的本地化字符串。 /// public static string NewTab { get { @@ -1561,7 +1552,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Nuget Package Browser. + /// 查找类似 Nuget Package Browser 的本地化字符串。 /// public static string NugetPackageBrowser { get { @@ -1570,7 +1561,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to OK. + /// 查找类似 OK 的本地化字符串。 /// public static string OK { get { @@ -1579,7 +1570,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open. + /// 查找类似 Open 的本地化字符串。 /// public static string Open { get { @@ -1588,7 +1579,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open Explorer. + /// 查找类似 Open Explorer 的本地化字符串。 /// public static string OpenExplorer { get { @@ -1597,7 +1588,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open From GAC. + /// 查找类似 Open From GAC 的本地化字符串。 /// public static string OpenFrom { get { @@ -1606,7 +1597,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open from _GAC.... + /// 查找类似 Open from _GAC... 的本地化字符串。 /// public static string OpenFrom_GAC { get { @@ -1615,7 +1606,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Delete. + /// 查找类似 _Delete 的本地化字符串。 /// public static string OpenListDialog__Delete { get { @@ -1624,7 +1615,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open. + /// 查找类似 _Open 的本地化字符串。 /// public static string OpenListDialog__Open { get { @@ -1633,7 +1624,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Options. + /// 查找类似 Options 的本地化字符串。 /// public static string Options { get { @@ -1642,7 +1633,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other. + /// 查找类似 Other 的本地化字符串。 /// public static string Other { get { @@ -1651,7 +1642,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other options. + /// 查找类似 Other options 的本地化字符串。 /// public static string OtherOptions { get { @@ -1660,7 +1651,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other Resources. + /// 查找类似 Other Resources 的本地化字符串。 /// public static string OtherResources { get { @@ -1669,7 +1660,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.. + /// 查找类似 for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. 的本地化字符串。 /// public static string PropertyManuallyMissingReferencesListLoadedAssemblies { get { @@ -1678,7 +1669,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Public Key Token. + /// 查找类似 Public Key Token 的本地化字符串。 /// public static string PublicToken { get { @@ -1687,7 +1678,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to R_ename. + /// 查找类似 R_ename 的本地化字符串。 /// public static string R_ename { get { @@ -1696,7 +1687,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reference Name. + /// 查找类似 Reference Name 的本地化字符串。 /// public static string ReferenceName { get { @@ -1705,7 +1696,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to References. + /// 查找类似 References 的本地化字符串。 /// public static string References { get { @@ -1714,7 +1705,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reload all assemblies. + /// 查找类似 Reload all assemblies 的本地化字符串。 /// public static string RefreshCommand_ReloadAssemblies { get { @@ -1723,7 +1714,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reload all assemblies. + /// 查找类似 Reload all assemblies 的本地化字符串。 /// public static string ReloadAssemblies { get { @@ -1732,7 +1723,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove. + /// 查找类似 Remove 的本地化字符串。 /// public static string Remove { get { @@ -1741,7 +1732,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead and side effect free code. + /// 查找类似 Remove dead and side effect free code 的本地化字符串。 /// public static string RemoveDeadSideEffectFreeCode { get { @@ -1750,7 +1741,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove shell integration. + /// 查找类似 Remove shell integration 的本地化字符串。 /// public static string RemoveShellIntegration { get { @@ -1759,9 +1750,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". + /// 查找类似 This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". /// - ///Do you want to continue?. + ///Do you want to continue? 的本地化字符串。 /// public static string RemoveShellIntegrationMessage { get { @@ -1770,7 +1761,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Rename list. + /// 查找类似 Rename list 的本地化字符串。 /// public static string RenameList { get { @@ -1779,7 +1770,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reset to defaults. + /// 查找类似 Reset to defaults 的本地化字符串。 /// public static string ResetToDefaults { get { @@ -1788,7 +1779,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Do you really want to load the default settings for the active page?. + /// 查找类似 Do you really want to load the default settings for the active page? 的本地化字符串。 /// public static string ResetToDefaultsConfirmationMessage { get { @@ -1797,7 +1788,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Resources file (*.resources)|*.resources|Resource XML file|*.resx. + /// 查找类似 Resources file (*.resources)|*.resources|Resource XML file|*.resx 的本地化字符串。 /// public static string ResourcesFileFilter { get { @@ -1806,7 +1797,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Save. + /// 查找类似 Save 的本地化字符串。 /// public static string Save { get { @@ -1815,7 +1806,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Save Code. + /// 查找类似 Save Code 的本地化字符串。 /// public static string SaveCode { get { @@ -1824,7 +1815,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search.... + /// 查找类似 Search... 的本地化字符串。 /// public static string Search { get { @@ -1833,7 +1824,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search aborted, more than 1000 results found.. + /// 查找类似 Search aborted, more than 1000 results found. 的本地化字符串。 /// public static string SearchAbortedMoreThan1000ResultsFound { get { @@ -1842,7 +1833,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search (Ctrl+Shift+F or Ctrl+E). + /// 查找类似 Search (Ctrl+Shift+F or Ctrl+E) 的本地化字符串。 /// public static string SearchCtrlShiftFOrCtrlE { get { @@ -1851,7 +1842,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Searching.... + /// 查找类似 Searching... 的本地化字符串。 /// public static string Searching { get { @@ -1860,7 +1851,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search Microsoft Docs.... + /// 查找类似 Search Microsoft Docs... 的本地化字符串。 /// public static string SearchMSDN { get { @@ -1869,7 +1860,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search. + /// 查找类似 Search 的本地化字符串。 /// public static string SearchPane_Search { get { @@ -1878,7 +1869,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select All. + /// 查找类似 Select All 的本地化字符串。 /// public static string Select { get { @@ -1887,7 +1878,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select assemblies to open:. + /// 查找类似 Select assemblies to open: 的本地化字符串。 /// public static string SelectAssembliesOpen { get { @@ -1896,7 +1887,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select a list of assemblies. + /// 查找类似 Select a list of assemblies 的本地化字符串。 /// public static string SelectAssemblyListDropdownTooltip { get { @@ -1905,7 +1896,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select language to decompile to. + /// 查找类似 Select language to decompile to 的本地化字符串。 /// public static string SelectLanguageDropdownTooltip { get { @@ -1914,7 +1905,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select a list:. + /// 查找类似 Select a list: 的本地化字符串。 /// public static string SelectList { get { @@ -1923,7 +1914,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select version of language to output. + /// 查找类似 Select version of language to output 的本地化字符串。 /// public static string SelectVersionDropdownTooltip { get { @@ -1932,7 +1923,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Shell. + /// 查找类似 Shell 的本地化字符串。 /// public static string Shell { get { @@ -1941,7 +1932,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show _all types and members. + /// 查找类似 Show _all types and members 的本地化字符串。 /// public static string Show_allTypesAndMembers { get { @@ -1950,7 +1941,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show public, private and internal. + /// 查找类似 Show public, private and internal 的本地化字符串。 /// public static string Show_internalTypesMembers { get { @@ -1959,7 +1950,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show only _public types and members. + /// 查找类似 Show only _public types and members 的本地化字符串。 /// public static string Show_publiconlyTypesMembers { get { @@ -1968,7 +1959,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show all types and members. + /// 查找类似 Show all types and members 的本地化字符串。 /// public static string ShowAllTypesAndMembers { get { @@ -1977,7 +1968,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show assembly load log. + /// 查找类似 Show assembly load log 的本地化字符串。 /// public static string ShowAssemblyLoad { get { @@ -1986,7 +1977,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ShowChildIndexInBlock. + /// 查找类似 ShowChildIndexInBlock 的本地化字符串。 /// public static string ShowChildIndexInBlock { get { @@ -1995,7 +1986,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show XML documentation in decompiled code. + /// 查找类似 Show XML documentation in decompiled code 的本地化字符串。 /// public static string ShowDocumentationDecompiledCode { get { @@ -2004,7 +1995,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ShowILRanges. + /// 查找类似 ShowILRanges 的本地化字符串。 /// public static string ShowILRanges { get { @@ -2013,7 +2004,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show info from debug symbols, if available. + /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 /// public static string ShowInfoFromDebugSymbolsAvailable { get { @@ -2022,7 +2013,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show public, private and internal. + /// 查找类似 Show public, private and internal 的本地化字符串。 /// public static string ShowInternalTypesMembers { get { @@ -2031,7 +2022,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show line numbers. + /// 查找类似 Show line numbers 的本地化字符串。 /// public static string ShowLineNumbers { get { @@ -2040,7 +2031,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show metadata tokens. + /// 查找类似 Show metadata tokens 的本地化字符串。 /// public static string ShowMetadataTokens { get { @@ -2049,7 +2040,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show metadata tokens in base 10. + /// 查找类似 Show metadata tokens in base 10 的本地化字符串。 /// public static string ShowMetadataTokensInBase10 { get { @@ -2058,7 +2049,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show only public types and members. + /// 查找类似 Show only public types and members 的本地化字符串。 /// public static string ShowPublicOnlyTypesMembers { get { @@ -2067,7 +2058,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show state after this step. + /// 查找类似 Show state after this step 的本地化字符串。 /// public static string ShowStateAfterThisStep { get { @@ -2076,7 +2067,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show state before this step. + /// 查找类似 Show state before this step 的本地化字符串。 /// public static string ShowStateBeforeThisStep { get { @@ -2085,7 +2076,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Size:. + /// 查找类似 Size: 的本地化字符串。 /// public static string Size { get { @@ -2094,7 +2085,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort assembly _list by name. + /// 查找类似 Sort assembly _list by name 的本地化字符串。 /// public static string SortAssembly_listName { get { @@ -2103,7 +2094,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort assembly list by name. + /// 查找类似 Sort assembly list by name 的本地化字符串。 /// public static string SortAssemblyListName { get { @@ -2112,7 +2103,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort results by fitness. + /// 查找类似 Sort results by fitness 的本地化字符串。 /// public static string SortResultsFitness { get { @@ -2121,7 +2112,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Stand by.... + /// 查找类似 Stand by... 的本地化字符串。 /// public static string StandBy { get { @@ -2130,7 +2121,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Status. + /// 查找类似 Status 的本地化字符串。 /// public static string Status { get { @@ -2139,7 +2130,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to String Table. + /// 查找类似 String Table 的本地化字符串。 /// public static string StringTable { get { @@ -2148,7 +2139,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Tab size:. + /// 查找类似 Tab size: 的本地化字符串。 /// public static string TabSize { get { @@ -2157,7 +2148,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Toggle All Folding. + /// 查找类似 Toggle All Folding 的本地化字符串。 /// public static string ToggleFolding { get { @@ -2166,7 +2157,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Type. + /// 查找类似 Type 的本地化字符串。 /// public static string Type { get { @@ -2175,7 +2166,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to No update for ILSpy found.. + /// 查找类似 No update for ILSpy found. 的本地化字符串。 /// public static string UpdateILSpyFound { get { @@ -2184,7 +2175,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to UseFieldSugar. + /// 查找类似 UseFieldSugar 的本地化字符串。 /// public static string UseFieldSugar { get { @@ -2193,7 +2184,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to UseLogicOperationSugar. + /// 查找类似 UseLogicOperationSugar 的本地化字符串。 /// public static string UseLogicOperationSugar { get { @@ -2202,7 +2193,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use tabs instead of spaces. + /// 查找类似 Use tabs instead of spaces 的本地化字符串。 /// public static string UseTabsInsteadOfSpaces { get { @@ -2211,7 +2202,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to You are using the latest release.. + /// 查找类似 You are using the latest release. 的本地化字符串。 /// public static string UsingLatestRelease { get { @@ -2220,7 +2211,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to You are using a nightly build newer than the latest release.. + /// 查找类似 You are using a nightly build newer than the latest release. 的本地化字符串。 /// public static string UsingNightlyBuildNewerThanLatestRelease { get { @@ -2229,7 +2220,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Value. + /// 查找类似 Value 的本地化字符串。 /// public static string Value { get { @@ -2238,7 +2229,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Value (as string). + /// 查找类似 Value (as string) 的本地化字符串。 /// public static string ValueString { get { @@ -2247,7 +2238,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use variable names from debug symbols, if available. + /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 /// public static string VariableNamesFromDebugSymbolsAvailable { get { @@ -2256,7 +2247,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Version. + /// 查找类似 Version 的本地化字符串。 /// public static string Version { get { @@ -2265,7 +2256,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Version {0} is available.. + /// 查找类似 Version {0} is available. 的本地化字符串。 /// public static string VersionAvailable { get { @@ -2274,7 +2265,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to View. + /// 查找类似 View 的本地化字符串。 /// public static string View { get { @@ -2283,7 +2274,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code.. + /// 查找类似 Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. 的本地化字符串。 /// public static string WarningAsmMarkedRef { get { @@ -2292,7 +2283,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,. + /// 查找类似 Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, 的本地化字符串。 /// public static string WarningSomeAssemblyReference { get { @@ -2301,7 +2292,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/.... + /// 查找类似 Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/... 的本地化字符串。 /// public static string WatermarkText { get { @@ -2310,7 +2301,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Close all documents. + /// 查找类似 Close all documents 的本地化字符串。 /// public static string Window_CloseAllDocuments { get { @@ -2319,7 +2310,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reset layout. + /// 查找类似 Reset layout 的本地化字符串。 /// public static string Window_ResetLayout { get { diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 980fec4c7..4cf41e4ea 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -154,10 +154,7 @@ 打开(_O)... - 从_GAC中打开...... - - - 打开列表(_L) + 从_GAC打开... 重新加载全部程序集 @@ -184,7 +181,7 @@ 移除 - 保存代码(_S) + 保存代码(_S)... 显示调试步骤(_S) @@ -244,7 +241,7 @@ 引用 - ILSpy版本 + ILSpy 版本 正在反编译... @@ -352,7 +349,7 @@ 派生类型 - 资源文件 (*.resources)|*.resources|XML资源文件|*.resx + 资源文件 (*.resources)|*.resources|XML资源文件|*.resx 排序结果自适应 @@ -366,24 +363,15 @@ 打开(_O) - - 创建(_C) - 引用名称 版本 - - 区域 - 公钥标记 - - 打开列表 - 选择一个列表: @@ -396,9 +384,6 @@ Nuget 包浏览器 - - 新建列表 - 选择要打开的程序集: @@ -469,7 +454,7 @@ 每周自动检查更新 - 搜索 t:TypeName, m:Member 或c:Constant; 使用完全匹配 (=term), '不应包含' (-term) 或 '必须包含' (+term); 使用 /reg(ular)?Ex(pressions)?/或两者 - t:/Type(Name)?/... + 搜索 t:TypeName, m:Member 或c:Constant; 使用完全匹配 (=term), '不应包含' (-term) 或 '必须包含' (+term); 使用 /reg(ular)?Ex(pressions)?/或两者 - t:/Type(Name)?/... 选项 @@ -703,10 +688,7 @@ 如果可能, 删除可选参数 - 引入本地功能 - - - C# 7.0 本地函数未实现! + 引入本地函数 可空引用类型 @@ -721,7 +703,7 @@ F # 特定选项 - 删除死的和副作用免费的代码 (请谨慎使用) + 删除废弃和副作用免费的代码 (请谨慎使用!) 在已加载的程序集上应用 Windows 运行时投影 @@ -735,4 +717,160 @@ 使用新的 SDK 格式 (*.csproj) 生成项目文件 + + 新建(_N) + + + 窗口(_W) + + + 添加预配置列表... + + + 添加外部集成 + + + 将要向注册表中的"HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" 和"HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" 添加"{0}"以便通过Windows资源管理器的右键菜单打开.dll 和 .exe 文件. + +你想继续吗? + + + 程序集 + + + 程序集 + + + 该目录不为空。文件将被覆盖。 +您确定要继续吗? + + + 项目目录不为空 + + + 克隆(_L) + + + 无法解析对象。无法从缺少程序集引用分析对接。添加缺少的引用,然后重试。 + + + 关闭 + + + 区域 + + + 使用'ref'扩展方法 + + + 允许显示枚举成员值 + + + 反编译异步IAsyncEnumerator方法 + + + 检测 awaited using 和 foreach 语句 + + + 如果可能,转换为do-while. + + + 如果可能,转换为for. + + + 引入静态本地函数 + + + 范围 + + + 只读方法 + + + 删除废弃的储存 (请慎重使用!) + + + 如果可能, 拆分局部变量定义和初始化器(int x = 5; -> int x; x = 5;). + + + 使用基于模式的 fixed 语句 + + + 使用throw表达式 + + + 反编译到新选项卡 + + + 从树视图中隐藏空元数据表 + + + 突出显示匹配的大括号 + + + 重置布局 + + + 关闭所有文档 + + + 仅显示public类型和成员 + + + 仅显示 _public 类型和成员 + + + 选择输出的语言版本 + + + 选择程序集列表 + + + 选择语言以反编译 + + + 重命名列表 + + + 重置为默认值 + + + 从注册表的 "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" 和HKCU\Software\Classes\exefile\shell\Open with ILSpy\command"删除"{0}". + +您要继续吗? + + + 删除外部集成 + + + 你的想要为当前页面加载默认设置吗? + + + 重命名(_E) + + + 新建列表 + + + 新建选项卡 + + + 管理程序集列表(_L)... + + + 管理程序集列表 + + + 导航失败,因为目标是隐藏的或者是一个编译器生成的类.\n +请禁止可能隐藏目标的所有过滤器(比如: 激活 "视图 > 显示内部类型和成员")并且重试. + + + 你确定要删除选定的程序集列表吗? + + + 找到同名程序集列表. + + + 你确定要删除所有程序集列表并且重新创建默认的程序集列表? + \ No newline at end of file From 8863f977c5bdcd309f143d1489e8124449a771bc Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 16 Jul 2020 01:29:48 +0800 Subject: [PATCH 02/92] ILSpy.ReadyToRun and more statements is Translated --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 15 ++ .../Properties/Resources.Designer.cs | 99 +++++++++++++ ILSpy.ReadyToRun/Properties/Resources.resx | 132 ++++++++++++++++++ .../Properties/Resources.zh-Hans.resx | 132 ++++++++++++++++++ ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 3 +- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 7 +- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 4 +- ILSpy/AboutPage.cs | 2 +- ILSpy/Commands/Pdb2XmlCommand.cs | 5 +- ILSpy/ILSpy.csproj | 1 + ILSpy/Properties/Resources.Designer.cs | 18 +++ ILSpy/Properties/Resources.resx | 6 + ILSpy/Properties/Resources.zh-Hans.resx | 16 ++- doc/ILSpyAboutPage.zh-Hans.txt | 13 ++ 14 files changed, 439 insertions(+), 14 deletions(-) create mode 100644 ILSpy.ReadyToRun/Properties/Resources.Designer.cs create mode 100644 ILSpy.ReadyToRun/Properties/Resources.resx create mode 100644 ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx create mode 100644 doc/ILSpyAboutPage.zh-Hans.txt diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index dddbbb74c..13d40df8a 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -44,6 +44,11 @@ + + True + True + Resources.resx + ReadyToRunOptionPage.xaml @@ -51,6 +56,16 @@ + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + + diff --git a/ILSpy.ReadyToRun/Properties/Resources.Designer.cs b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs new file mode 100644 index 000000000..56cf7ac1f --- /dev/null +++ b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace ILSpy.ReadyToRun.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILSpy.ReadyToRun.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 Disassembly Format 的本地化字符串。 + /// + public static string DisassemblyFormat { + get { + return ResourceManager.GetString("DisassemblyFormat", resourceCulture); + } + } + + /// + /// 查找类似 ReadyToRun 的本地化字符串。 + /// + public static string ReadyToRun { + get { + return ResourceManager.GetString("ReadyToRun", resourceCulture); + } + } + + /// + /// 查找类似 Show Debug Info 的本地化字符串。 + /// + public static string ShowDebugInfo { + get { + return ResourceManager.GetString("ShowDebugInfo", resourceCulture); + } + } + + /// + /// 查找类似 Show Unwind Info 的本地化字符串。 + /// + public static string ShowUnwindInfo { + get { + return ResourceManager.GetString("ShowUnwindInfo", resourceCulture); + } + } + } +} diff --git a/ILSpy.ReadyToRun/Properties/Resources.resx b/ILSpy.ReadyToRun/Properties/Resources.resx new file mode 100644 index 000000000..67b36ef54 --- /dev/null +++ b/ILSpy.ReadyToRun/Properties/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ReadyToRun + + + Disassembly Format + + + Show Unwind Info + + + Show Debug Info + + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx new file mode 100644 index 000000000..f13237c18 --- /dev/null +++ b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ReadyToRun + + + 反汇编格式 + + + 显示调试信息 + + + 显示展开信息 + + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index f29c5ce73..b244a5b43 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -24,6 +24,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Resources; using System.Runtime.CompilerServices; using Iced.Intel; @@ -35,7 +36,7 @@ using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ILCompiler.Reflection.ReadyToRun; using ILCompiler.Reflection.ReadyToRun.Amd64; - +[assembly: NeutralResourcesLanguage("en-US")] namespace ICSharpCode.ILSpy.ReadyToRun { [Export(typeof(Language))] diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 188f52994..c3e28eaf0 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -1,5 +1,6 @@  @@ -11,11 +12,11 @@ - Disassembly Format + - Show Unwind Info + - Show Debug Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 3e81b1c7c..59ee6d734 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -20,10 +20,10 @@ using System.ComponentModel; using System.Windows.Controls; using System.Xml.Linq; using ICSharpCode.ILSpy.Options; - +using ILSpy.ReadyToRun; namespace ICSharpCode.ILSpy.ReadyToRun { - [ExportOptionPage(Title = "ReadyToRun", Order = 40)] + [ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)] partial class ReadyToRunOptionPage : UserControl, IOptionPage { public ReadyToRunOptionPage() diff --git a/ILSpy/AboutPage.cs b/ILSpy/AboutPage.cs index e904de4a8..1916abee5 100644 --- a/ILSpy/AboutPage.cs +++ b/ILSpy/AboutPage.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy plugin.Write(output); output.WriteLine(); output.Address = new Uri("resource://AboutPage"); - using (Stream s = typeof(AboutPage).Assembly.GetManifestResourceStream(typeof(AboutPage), "ILSpyAboutPage.txt")) { + using (Stream s = typeof(AboutPage).Assembly.GetManifestResourceStream(typeof(AboutPage), Resources.ILSpyAboutPageTxt)) { using (StreamReader r = new StreamReader(s)) { string line; while ((line = r.ReadLine()) != null) { diff --git a/ILSpy/Commands/Pdb2XmlCommand.cs b/ILSpy/Commands/Pdb2XmlCommand.cs index 91b481f7b..13856e8b0 100644 --- a/ILSpy/Commands/Pdb2XmlCommand.cs +++ b/ILSpy/Commands/Pdb2XmlCommand.cs @@ -24,13 +24,14 @@ using System.Linq; using System.Threading.Tasks; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; using Microsoft.DiaSymReader.Tools; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Dump PDB as XML", MenuCategory = "Open", MenuOrder = 2.6)] + [ExportMainMenuCommand(Menu = nameof(Resources._File) , Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)] sealed class Pdb2XmlCommand : SimpleCommand { public override bool CanExecute(object parameter) @@ -64,7 +65,7 @@ namespace ICSharpCode.ILSpy } } - [ExportContextMenuEntry(Header = "DEBUG -- Dump PDB as XML")] + [ExportContextMenuEntry(Header = nameof(Resources.DEBUGDumpPDBAsXML))] class Pdb2XmlCommandContextMenuEntry : IContextMenuEntry { public void Execute(TextViewContext context) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index c47538ca4..1abc6c53e 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -456,6 +456,7 @@ + license.txt diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index ce852aecd..5b55dfdfc 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -549,6 +549,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 DEBUG -- Dump PDB as XML 的本地化字符串。 + /// + public static string DEBUGDumpPDBAsXML { + get { + return ResourceManager.GetString("DEBUGDumpPDBAsXML", resourceCulture); + } + } + /// /// 查找类似 Debug Steps 的本地化字符串。 /// @@ -1379,6 +1388,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 ILSpyAboutPage.txt 的本地化字符串。 + /// + public static string ILSpyAboutPageTxt { + get { + return ResourceManager.GetString("ILSpyAboutPageTxt", resourceCulture); + } + } + /// /// 查找类似 ILSpy version 的本地化字符串。 /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 4fb242324..cc292085b 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -873,4 +873,10 @@ Do you want to continue? Use new SDK style format for generated project files (*.csproj) + + DEBUG -- Dump PDB as XML + + + ILSpyAboutPage.txt + \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 4cf41e4ea..164844b44 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -481,16 +481,16 @@ 调试步骤 - UseFieldSugar + 使用变量语法糖 - UseLogicOperationSugar + 使用逻辑操作符语法糖 - ShowILRanges + 显示IL范围 - ShowChildIndexInBlock + 在块中显示子索引 在此步骤之前显示状态 @@ -817,7 +817,7 @@ 仅显示public类型和成员 - 仅显示 _public 类型和成员 + 仅显示公共类型和成员(_P) 选择输出的语言版本 @@ -873,4 +873,10 @@ 你确定要删除所有程序集列表并且重新创建默认的程序集列表? + + ILSpyAboutPage.zh-Hans.txt + + + DEBUG --转存PDB为XML + \ No newline at end of file diff --git a/doc/ILSpyAboutPage.zh-Hans.txt b/doc/ILSpyAboutPage.zh-Hans.txt new file mode 100644 index 000000000..859f9a8e1 --- /dev/null +++ b/doc/ILSpyAboutPage.zh-Hans.txt @@ -0,0 +1,13 @@ +ILSpy ǿԴ.NETͷ. + +վ: https://ilspy.net/ +BUG: https://github.com/icsharpcode/ILSpy/issues/new/choose +ķ뷴:https://github.com/maikebing/ILSpy/issues + +Copyright 2011-2020 AlphaSierraPapa for the ILSpy team +ǰ͹ȥĹ: https://github.com/icsharpcode/ILSpy/graphs/contributors + +ILSpy MIT License . + +ILSpy ʹԴħʵ֣ ڴͬʱлΪЩǣ +ǸԵɺͰȨϢ鿴third-partyע. \ No newline at end of file From 09dea5b3a571fc1b99c646770d53633c6b6dc4a4 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 16 Jul 2020 01:46:43 +0800 Subject: [PATCH 03/92] fix for about page --- ILSpy/ILSpy.csproj | 2 +- ILSpy/Properties/Resources.zh-Hans.resx | 2 +- doc/ILSpyAboutPage.zh-Hans.txt | 13 ------------- doc/ILSpyAboutPage_zh_Hans.txt | 13 +++++++++++++ 4 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 doc/ILSpyAboutPage.zh-Hans.txt create mode 100644 doc/ILSpyAboutPage_zh_Hans.txt diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 1abc6c53e..ad1517e5d 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -456,7 +456,7 @@ - + license.txt diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 164844b44..fcdfe3750 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -874,7 +874,7 @@ 你确定要删除所有程序集列表并且重新创建默认的程序集列表? - ILSpyAboutPage.zh-Hans.txt + ILSpyAboutPage_zh_Hans.txt DEBUG --转存PDB为XML diff --git a/doc/ILSpyAboutPage.zh-Hans.txt b/doc/ILSpyAboutPage.zh-Hans.txt deleted file mode 100644 index 859f9a8e1..000000000 --- a/doc/ILSpyAboutPage.zh-Hans.txt +++ /dev/null @@ -1,13 +0,0 @@ -ILSpy ǿԴ.NETͷ. - -վ: https://ilspy.net/ -BUG: https://github.com/icsharpcode/ILSpy/issues/new/choose -ķ뷴:https://github.com/maikebing/ILSpy/issues - -Copyright 2011-2020 AlphaSierraPapa for the ILSpy team -ǰ͹ȥĹ: https://github.com/icsharpcode/ILSpy/graphs/contributors - -ILSpy MIT License . - -ILSpy ʹԴħʵ֣ ڴͬʱлΪЩǣ -ǸԵɺͰȨϢ鿴third-partyע. \ No newline at end of file diff --git a/doc/ILSpyAboutPage_zh_Hans.txt b/doc/ILSpyAboutPage_zh_Hans.txt new file mode 100644 index 000000000..ed771b2e5 --- /dev/null +++ b/doc/ILSpyAboutPage_zh_Hans.txt @@ -0,0 +1,13 @@ +ILSpy 是开源的.NET程序集浏览器和反编译器. + +网站: https://ilspy.net/ +反馈BUG: https://github.com/icsharpcode/ILSpy/issues/new/choose +中文翻译反馈:https://github.com/maikebing/ILSpy/issues + +Copyright 2011-2020 AlphaSierraPapa for the ILSpy team +当前和过去的贡献者: https://github.com/icsharpcode/ILSpy/graphs/contributors + +ILSpy 基于 MIT License 发行. + +ILSpy 使用了其他开源库才能魔术般的实现, 于此同时我们想感谢他们为那些组件付出的人们! +它们各自的许可和版权信息请查看third-party注意事项. \ No newline at end of file From 782e4dfb42ac5793246720e8443def9ef5cb69b2 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 17 Jul 2020 15:10:43 +0800 Subject: [PATCH 04/92] fix some words --- ILSpy/Properties/Resources.Designer.cs | 8 +++----- ILSpy/Properties/Resources.zh-Hans.resx | 6 ++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 1f5287733..d3c5eea8c 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -406,7 +406,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Base Types. + /// 查找类似 Base Types 的本地化字符串。 /// public static string BaseTypes { get { @@ -415,7 +415,6 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to C_lone. /// 查找类似 C_lone 的本地化字符串。 /// public static string C_lone { @@ -596,7 +595,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Allow extension 'Add' methods in collection initializer expressions. + /// 查找类似 Allow extension 'Add' methods in collection initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_AllowExtensionAddMethodsInCollectionInitializerExpressions { get { @@ -931,7 +930,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use nint/nuint types. + /// 查找类似 Use nint/nuint types 的本地化字符串。 /// public static string DecompilerSettings_NativeIntegers { get { @@ -940,7 +939,6 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Nullable reference types. /// 查找类似 Nullable reference types 的本地化字符串。 /// public static string DecompilerSettings_NullableReferenceTypes { diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index fcdfe3750..fe673cca7 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -879,4 +879,10 @@ DEBUG --转存PDB为XML + + 使用 nint/nuint 类型 + + + 基础类型 + \ No newline at end of file From ba367032d6883ba255dc737dd96a8224f4d96c0a Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 17 Jul 2020 15:12:29 +0800 Subject: [PATCH 05/92] https://github.com/icsharpcode/ILSpy/pull/2066 --- ILSpy/Properties/Resources.zh-Hans.resx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index fe673cca7..462b62bb7 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -139,7 +139,7 @@ 打开 - DEBUG -- 反编译全部 + DEBUG -- 全部反汇编 退出(_X) @@ -877,7 +877,7 @@ ILSpyAboutPage_zh_Hans.txt - DEBUG --转存PDB为XML + DEBUG -- 转存PDB为XML 使用 nint/nuint 类型 From a2312f594d8f69186767e1eadba98fe4740fa554 Mon Sep 17 00:00:00 2001 From: plupiman Date: Fri, 17 Jul 2020 15:30:20 -0700 Subject: [PATCH 06/92] Decorate ReadyToRun dissassembly with NativeVarInfo --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 4 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 180 +++++++++++++++++++-- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 2 - ILSpy/ILSpy.csproj | 4 +- 4 files changed, 172 insertions(+), 18 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index dddbbb74c..a31d53184 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -37,6 +37,9 @@ False + + ..\..\..\Desktop\r2r\ILCompiler.Reflection.ReadyToRun\bin\Debug\netstandard2.0\ILCompiler.Reflection.ReadyToRun.dll + @@ -57,7 +60,6 @@ - diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index f29c5ce73..1437df604 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -86,6 +86,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun .GroupBy(m => m.MethodHandle) .ToDictionary(g => g.Key, g => g.ToArray()); } + + bool showMetadataTokens = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens; bool showMetadataTokensInBase10 = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10; if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) { @@ -103,12 +105,92 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine("; " + comment); } + private Dictionary>> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + { + Dictionary>> debugInfoDict = new Dictionary>>(); + IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; + foreach (RuntimeFunction runtimeFunction in runTimeList) { + DebugInfo debugInfo = runtimeFunction.DebugInfo; + if (debugInfo != null && debugInfo.BoundsList.Count > 0) { + for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { + var varLoc = debugInfo.VariablesList[i]; + try { + HashSet > typeSet = new HashSet>(); + bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); + if (found) { + typeSet.Add(new Tuple(debugInfo, varLoc)); + } else { + typeSet = new HashSet>(); + debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); + typeSet.Add(new Tuple(debugInfo, varLoc)); + } + + } catch (ArgumentNullException) { + output.WriteLine("Failed to find hash set of Debug info type"); + } + + if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK + && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) { + //debugInfoDict.Add(varLoc.VariableLocation.VarLocType, ) + output.WriteLine($" Variable Number: {varLoc.VariableNumber}"); + output.WriteLine($" Start Offset: 0x{varLoc.StartOffset:X}"); + output.WriteLine($" End Offset: 0x{varLoc.EndOffset:X}"); + output.WriteLine($" Loc Type: {varLoc.VariableLocation.VarLocType}"); + switch (varLoc.VariableLocation.VarLocType) { + case VarLocType.VLT_REG: + case VarLocType.VLT_REG_FP: + case VarLocType.VLT_REG_BYREF: + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + + case VarLocType.VLT_STK: + case VarLocType.VLT_STK_BYREF: + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data2}"); + break; + case VarLocType.VLT_REG_REG: + output.WriteLine($" Register 1: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Register 2: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + break; + case VarLocType.VLT_REG_STK: + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data3}"); + break; + case VarLocType.VLT_STK_REG: + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data1}"); + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data3)}"); + break; + case VarLocType.VLT_STK2: + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data2}"); + break; + case VarLocType.VLT_FPSTK: + output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + case VarLocType.VLT_FIXED_VA: + output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + + default: + throw new BadImageFormatException("Unexpected var loc type"); + } + + output.WriteLine(""); + } + } + } + } + return debugInfoDict; + } - private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) + + private Dictionary> WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) { - Dictionary unwindCodes = new Dictionary(); + Dictionary> unwindCodes = new Dictionary>(); if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { @@ -128,8 +210,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun WriteCommentLine(output, $"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}"); WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString())}"); for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) { - unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - + if (unwindCodes.ContainsKey((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset))) { + unwindCodes[(ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset)].Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); + } else { + HashSet codeSet = new HashSet(); + codeSet.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); + unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), codeSet); + } } } return unwindCodes; @@ -137,19 +224,19 @@ namespace ICSharpCode.ILSpy.ReadyToRun private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) { + WriteCommentLine(output, readyToRunMethod.SignatureString); - Dictionary unwindInfo = null; + Dictionary> unwindInfo = null; if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { unwindInfo = WriteUnwindInfo(runtimeFunction, output); } - - + Dictionary>> debugInfo = WriteDebugInfo(readyToRunMethod, output); byte[] codeBytes = new byte[runtimeFunction.Size]; for (int i = 0; i < runtimeFunction.Size; i++) { codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i]; } - // TODO: Decorate the disassembly with GC and debug info + // TODO: Decorate the disassembly with GC var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; @@ -172,7 +259,10 @@ namespace ICSharpCode.ILSpy.ReadyToRun formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; + int counter = -1; foreach (var instr in instructions) { + counter++; + int byteBaseIndex = (int)(instr.IP - address); if (runtimeFunction.DebugInfo != null) { foreach (var bound in runtimeFunction.DebugInfo.BoundsList) { @@ -187,32 +277,98 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } } + formatter.Format(instr, tempOutput); output.Write(instr.IP.ToString("X16")); output.Write(" "); int instrLen = instr.Length; - for (int i = 0; i < instrLen; i++) + for (int i = 0; i < instrLen; i++) { output.Write(codeBytes[byteBaseIndex + i].ToString("X2")); + } int missingBytes = 10 - instrLen; for (int i = 0; i < missingBytes; i++) output.Write(" "); output.Write(" "); output.Write(tempOutput.ToStringAndReset()); DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); + DecorateDebugInfo(output, instr, debugInfo, baseInstrIP); DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr); } output.WriteLine(); } - private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) + private static void DecorateUnwindInfo(ITextOutput output, Dictionary> unwindInfo, ulong baseInstrIP, Instruction instr) { ulong nextInstructionOffset = instr.NextIP - baseInstrIP; if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) { - UnwindCode unwindCode = unwindInfo[nextInstructionOffset]; - output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); + foreach (var unwindCode in unwindInfo[nextInstructionOffset]) { + output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); + } } } + private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary>> debugInfoDict, ulong baseInstrIP) + { + if (debugInfoDict != null) { + InstructionInfoFactory factory = new InstructionInfoFactory(); + InstructionInfo info = factory.GetInfo(instr); + HashSet> stkSet = new HashSet>(); + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) { + stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK_BYREF)) { + stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK_BYREF]); + } + if (stkSet != null) { + foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) { //for each time a [register +- value] is used + foreach (Tuple tuple in stkSet) { //for each VLT_STK variable + var debugInfo = tuple.Item1; + var varInfo = tuple.Item2; + int stackOffset = varInfo.VariableLocation.Data2; + ulong adjOffset; + bool negativeOffset; + if (stackOffset < 0) { + int absValue = -1 * stackOffset; + adjOffset = ulong.MaxValue - (ulong)absValue + 1; + negativeOffset = true; + } else { + adjOffset = (ulong)stackOffset; + negativeOffset = false; + } + if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && + DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Base.ToString() && + adjOffset == usedMemInfo.Displacement) { + + output.Write($"; [{usedMemInfo.Base.ToString()}{(negativeOffset ? '-' : '+')}{Math.Abs(stackOffset)}] = {varInfo.Variable.Type} {varInfo.Variable.Index}"); + } + } + } + } + HashSet> regSet = new HashSet>(); + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_BYREF)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_BYREF]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_FP)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_FP]); + } + if (regSet != null) { + foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) { + foreach (Tuple tuple in regSet) { + var debugInfo = tuple.Item1; + var varInfo = tuple.Item2; + if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && + DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { + + output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); + } + } + } + } + } + } private static void DecorateCallSite(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, bool showMetadataTokens, bool showMetadataTokensInBase10, Instruction instr) { int importCellAddress = (int)instr.IPRelativeMemoryAddress; diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 188f52994..55fcf2fb6 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -15,7 +15,5 @@ Show Unwind Info - Show Debug Info - \ No newline at end of file diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 71414747b..4d4ee4e3a 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -128,9 +128,7 @@ - - Form - + From 3409ffca25ddb53cc4377128ae1ba8d7e91a550c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Jul 2020 20:48:31 +0200 Subject: [PATCH 07/92] Fix #2073: Ensure the startOffsetVar actually appears in the expected instruction, not somewhere else. --- ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs index 22e62edf0..651113ce6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs @@ -205,6 +205,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind)) { return; } + if (!call.IsDescendantOf(block.Instructions[pos])) + return; // startOffsetVar might be used deep inside a complex statement, ensure we can inline up to that point: for (int i = startPos; i < pos; i++) { if (!ILInlining.CanInlineInto(block.Instructions[pos], startOffsetVar, block.Instructions[i])) @@ -275,6 +277,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (!(sliceLengthVar.LoadInstructions.Single().Parent is CallInstruction call)) return; + if (!call.IsDescendantOf(block.Instructions[pos])) + return; if (!IsSlicingMethod(call.Method)) return; if (call.Arguments.Count != 3) From bd059dfb599d2337c06b4123737090b5f14b9930 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Jul 2020 20:53:29 +0200 Subject: [PATCH 08/92] Fix #2075: IndexOutOfRange exception in PEFile.GetRuntime() --- ICSharpCode.Decompiler/Metadata/PEFile.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs index c261dbb5e..9b69c8a9a 100644 --- a/ICSharpCode.Decompiler/Metadata/PEFile.cs +++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs @@ -75,8 +75,12 @@ namespace ICSharpCode.Decompiler.Metadata public TargetRuntime GetRuntime() { string version = Metadata.MetadataVersion; + if (version == null || version.Length <= 1) + return TargetRuntime.Unknown; switch (version[1]) { case '1': + if (version.Length <= 3) + return TargetRuntime.Unknown; if (version[3] == 1) return TargetRuntime.Net_1_0; else From 2acc4339dfa10d82a57cf7bf410ec2f86e4df4ee Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Jul 2020 21:25:22 +0200 Subject: [PATCH 09/92] #2058: Mark most transforms as public to help users that use the ILAst directly without decompiling to C#. --- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 6 +++--- ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs | 2 +- .../IL/ControlFlow/YieldReturnDecompiler.cs | 2 +- .../IL/Transforms/DelegateConstruction.cs | 4 ++-- .../IL/Transforms/EarlyExpressionTransforms.cs | 2 +- ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs | 2 +- .../IL/Transforms/IntroduceDynamicTypeOnLocals.cs | 2 +- .../IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs | 2 +- .../IL/Transforms/LocalFunctionDecompiler.cs | 2 +- ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs | 2 +- .../IL/Transforms/NamedArgumentTransform.cs | 4 ++-- .../IL/Transforms/NullCoalescingTransform.cs | 2 +- .../IL/Transforms/NullPropagationTransform.cs | 2 +- .../IL/Transforms/NullableLiftingTransform.cs | 2 +- .../IL/Transforms/SwitchOnNullableTransform.cs | 2 +- .../IL/Transforms/SwitchOnStringTransform.cs | 2 +- .../IL/Transforms/TransformDisplayClassUsage.cs | 2 +- .../IL/Transforms/UserDefinedLogicTransform.cs | 2 +- ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index e22109e70..e290f4d95 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -33,9 +33,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// /// Decompiler step for C# 5 async/await. /// - class AsyncAwaitDecompiler : IILTransform + public class AsyncAwaitDecompiler : IILTransform { - public static bool IsCompilerGeneratedStateMachine(TypeDefinitionHandle type, MetadataReader metadata) + internal static bool IsCompilerGeneratedStateMachine(TypeDefinitionHandle type, MetadataReader metadata) { TypeDefinition td; if (type.IsNil || (td = metadata.GetTypeDefinition(type)).GetDeclaringType().IsNil) @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; } - public static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, MethodDefinitionHandle method) + internal static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, MethodDefinitionHandle method) { var metadata = module.Metadata; var definition = metadata.GetMethodDefinition(method); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index 9ae80f766..9eb2d3701 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Detect sequences of conditional branches that all test a single integer value, /// and simplify them into a ILAst switch instruction (which like C# does not require contiguous values). /// - class SwitchDetection : IILTransform + public class SwitchDetection : IILTransform { private readonly SwitchAnalysis analysis = new SwitchAnalysis(); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index 268891509..ca6314a74 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -28,7 +28,7 @@ using System.Reflection.Metadata; namespace ICSharpCode.Decompiler.IL.ControlFlow { - class YieldReturnDecompiler : IILTransform + public class YieldReturnDecompiler : IILTransform { // For a description on the code generated by the C# compiler for yield return: // http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index b5dc0423f..27143e9b3 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -25,9 +25,9 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms { /// - /// + /// Transforms anonymous methods and lambdas by creating nested ILFunctions. /// - class DelegateConstruction : IILTransform + public class DelegateConstruction : IILTransform { ILTransformContext context; ITypeResolveContext decompilationContext; diff --git a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs index 8b5b3c6e7..8bba5a9a0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms { - class EarlyExpressionTransforms : ILVisitor, IILTransform + public class EarlyExpressionTransforms : ILVisitor, IILTransform { ILTransformContext context; diff --git a/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs b/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs index 3b270f62b..6d5367e75 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// This transform un-inlines the argument of `isinst` instructions that can't be directly translated to C#, /// thus allowing the emulation via "expr is T ? (T)expr : null". /// - class FixLoneIsInst : IILTransform + public class FixLoneIsInst : IILTransform { void IILTransform.Run(ILFunction function, ILTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs index 08e90f086..a16786ea1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs @@ -24,7 +24,7 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL { - class IntroduceDynamicTypeOnLocals : IILTransform + public class IntroduceDynamicTypeOnLocals : IILTransform { public void Run(ILFunction function, ILTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs index d75d3096b..233bf87ef 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL { - class IntroduceRefReadOnlyModifierOnLocals : IILTransform + public class IntroduceRefReadOnlyModifierOnLocals : IILTransform { public void Run(ILFunction function, ILTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index 0a553839c..de7e36c48 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// Decompiler step for C# 7.0 local functions /// - class LocalFunctionDecompiler : IILTransform + public class LocalFunctionDecompiler : IILTransform { ILTransformContext context; ITypeResolveContext resolveContext; diff --git a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs index 1c273dd76..ab7a4bb83 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms { - class LockTransform : IBlockTransform + public class LockTransform : IBlockTransform { BlockTransformContext context; diff --git a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs index fb9bb125a..a1b74147a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs @@ -10,9 +10,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms using FindResult = ILInlining.FindResult; using FindResultType = ILInlining.FindResultType; - class NamedArgumentTransform : IStatementTransform + public class NamedArgumentTransform : IStatementTransform { - public static FindResult CanIntroduceNamedArgument(CallInstruction call, ILInstruction child, ILVariable v, ILInstruction expressionBeingMoved) + internal static FindResult CanIntroduceNamedArgument(CallInstruction call, ILInstruction child, ILVariable v, ILInstruction expressionBeingMoved) { Debug.Assert(child.Parent == call); if (call.IsInstanceCall && child.ChildIndex == 0) diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs index 2a0780636..e251c23cd 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// The ?? operator for nullable value types is handled by NullableLiftingTransform. /// - class NullCoalescingTransform : IStatementTransform + public class NullCoalescingTransform : IStatementTransform { public void Run(Block block, int pos, StatementTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs index 93d7f90f5..798c03f19 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs @@ -489,7 +489,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - class NullPropagationStatementTransform : IStatementTransform + public class NullPropagationStatementTransform : IStatementTransform { public void Run(Block block, int pos, StatementTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 38b8bb942..80775465c 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -908,7 +908,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms #endregion } - class NullableLiftingStatementTransform : IStatementTransform + public class NullableLiftingStatementTransform : IStatementTransform { public void Run(Block block, int pos, StatementTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs index b63ba77d9..9d022a3c8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// Detects switch-on-nullable patterns employed by the C# compiler and transforms them to an ILAst-switch-instruction. /// - class SwitchOnNullableTransform : IILTransform + public class SwitchOnNullableTransform : IILTransform { public void Run(ILFunction function, ILTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index 6385ee159..bab175088 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// Detects switch-on-string patterns employed by the C# compiler and transforms them to an ILAst-switch-instruction. /// - class SwitchOnStringTransform : IILTransform + public class SwitchOnStringTransform : IILTransform { ILTransformContext context; diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index d33d9d0f9..ab9aaae28 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// Note that 2) and 3) apply because declarations and uses of lambdas and local functions /// are already transformed by the time this transform is applied. /// - class TransformDisplayClassUsage : ILVisitor, IILTransform + public class TransformDisplayClassUsage : ILVisitor, IILTransform { class VariableToDeclare { diff --git a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs index 826228b99..ec6eeaf91 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs @@ -26,7 +26,7 @@ using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.Transforms { - class UserDefinedLogicTransform : IStatementTransform + public class UserDefinedLogicTransform : IStatementTransform { void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs index 31c8c91d5..06375f71c 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs @@ -25,7 +25,7 @@ using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms { - class UsingTransform : IBlockTransform + public class UsingTransform : IBlockTransform { BlockTransformContext context; From 7476ae8f40cd50cda1641d19c3b44fc95b191d8d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Jul 2020 21:30:01 +0200 Subject: [PATCH 10/92] #2074: Don't open multiple crash dialogs at the same time. --- ILSpy/App.xaml.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index 5d5f5e36b..0f578dc69 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -165,6 +165,9 @@ namespace ICSharpCode.ILSpy } } + [ThreadStatic] + static bool showingError; + static void UnhandledException(Exception exception) { Debug.WriteLine(exception.ToString()); @@ -176,7 +179,17 @@ namespace ICSharpCode.ILSpy break; } } - MessageBox.Show(exception.ToString(), "Sorry, we crashed"); + if (showingError) { + // Ignore re-entrant calls + // We run the risk of opening an infinite number of exception dialogs. + return; + } + showingError = true; + try { + MessageBox.Show(exception.ToString(), "Sorry, we crashed"); + } finally { + showingError = false; + } } #endregion From c647016bfb19358099d163a8ede213f475257a41 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Jul 2020 23:02:30 +0200 Subject: [PATCH 11/92] #2070: Allow `PickExitPoint` heuristic to choose a `return;`/`yield break;` that is part of a condition block. --- .../TestCases/Pretty/YieldReturn.cs | 13 +++++++++++ .../IL/ControlFlow/LoopDetection.cs | 22 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs index 0306343d3..880428737 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs @@ -356,5 +356,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } Console.WriteLine("normal exit"); } + + internal IEnumerable ForLoopWithYieldReturn(int end, int evil) + { + // This loop needs to pick the implicit "yield break;" as exit point + // in order to produce pretty code; not the "throw" which would + // be a less-pretty option. + for (int i = 0; i < end; i++) { + if (i == evil) { + throw new InvalidOperationException("Found evil number"); + } + yield return i; + } + } } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs index 1ba3a1437..b9d6345f4 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs @@ -315,6 +315,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } ControlFlowNode exitPoint = null; int exitPointILOffset = -1; + ConsiderReturnAsExitPoint((Block)loopHead.UserData, ref exitPoint, ref exitPointILOffset); foreach (var node in loopHead.DominatorTreeChildren) { PickExitPoint(node, ref exitPoint, ref exitPointILOffset); } @@ -457,12 +458,31 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow exitPoint = node; exitPointILOffset = block.StartILOffset; return; // don't visit children, they are likely to have even later IL offsets and we'd end up - // moving almost all of the code into the loop. + // moving almost all of the code into the loop. } + ConsiderReturnAsExitPoint(block, ref exitPoint, ref exitPointILOffset); foreach (var child in node.DominatorTreeChildren) { PickExitPoint(child, ref exitPoint, ref exitPointILOffset); } } + + private static void ConsiderReturnAsExitPoint(Block block, ref ControlFlowNode exitPoint, ref int exitPointILOffset) + { + // It's possible that the real exit point of the loop is a "return;" that has been combined (by ControlFlowSimplification) + // with the condition block. + if (!block.MatchIfAtEndOfBlock(out _, out var trueInst, out var falseInst)) + return; + if (trueInst.StartILOffset > exitPointILOffset && trueInst is Leave { IsLeavingFunction: true, Value: Nop _ }) { + // By using NoExitPoint, everything (including the "return;") becomes part of the loop body + // Then DetectExitPoint will move the "return;" out of the loop body. + exitPoint = NoExitPoint; + exitPointILOffset = trueInst.StartILOffset; + } + if (falseInst.StartILOffset > exitPointILOffset && falseInst is Leave { IsLeavingFunction: true, Value: Nop _ }) { + exitPoint = NoExitPoint; + exitPointILOffset = falseInst.StartILOffset; + } + } /// /// Constructs a new control flow graph. From 27fa43912fb3de45907e2fbd217bb507cf8ab2ad Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 23 Jul 2020 14:05:18 +0800 Subject: [PATCH 12/92] fix for https://github.com/icsharpcode/ILSpy/pull/2066#discussion_r459021092 --- ILSpy/ILSpy.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index ba7e14394..6a00ead25 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -457,7 +457,7 @@ - + license.txt From 4308ab3073ec1cd582873f5ab164eb50db157796 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:30:11 +0200 Subject: [PATCH 13/92] Fix WPF binding error in Metadata Explorer --- ILSpy/Metadata/Helpers.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ILSpy/Metadata/Helpers.cs b/ILSpy/Metadata/Helpers.cs index 38f69d30d..6321f8ee3 100644 --- a/ILSpy/Metadata/Helpers.cs +++ b/ILSpy/Metadata/Helpers.cs @@ -113,6 +113,7 @@ namespace ICSharpCode.ILSpy.Metadata }; switch (e.PropertyName) { case "RID": + case "Meaning": e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["DefaultFilter"]); ((DataGridCustomTextColumn)e.Column).ToolTipBinding = null; break; From 6613f100f184305becf213741e29f23ff490d0d8 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:30:59 +0200 Subject: [PATCH 14/92] Upgrade ILSpy.ReadyToRun.csproj to use MSBuild.Sdk.Extras + UseWpf --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index dddbbb74c..82e170fe8 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -1,6 +1,5 @@  - - + net472 @@ -10,6 +9,9 @@ False false + true + false + false @@ -60,8 +62,6 @@ - - From 4f8c588c7b6b932b4341f699fb42f1f0783f6e02 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:32:43 +0200 Subject: [PATCH 15/92] Fix #2068: ILSpy can't find referenced library even though it's open --- .../Metadata/DotNetCorePathFinder.cs | 45 ++++++++++--------- .../Metadata/UniversalAssemblyResolver.cs | 10 +++-- ILSpy/LoadedAssembly.cs | 38 +++++++++++++++- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs index 740ecc0d4..e118bd05b 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs @@ -61,29 +61,30 @@ namespace ICSharpCode.Decompiler.Metadata }; readonly DotNetCorePackageInfo[] packages; - ISet packageBasePaths = new HashSet(StringComparer.Ordinal); - readonly Version version; + readonly List searchPaths = new List(); + readonly List packageBasePaths = new List(); + readonly Version targetFrameworkVersion; readonly string dotnetBasePath = FindDotNetExeDirectory(); - public DotNetCorePathFinder(Version version) + public DotNetCorePathFinder(Version targetFrameworkVersion) { - this.version = version; + this.targetFrameworkVersion = targetFrameworkVersion; } - public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, TargetFrameworkIdentifier targetFramework, Version version, ReferenceLoadInfo loadInfo = null) + public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion, ReferenceLoadInfo loadInfo = null) { string assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName); string basePath = Path.GetDirectoryName(parentAssemblyFileName); - this.version = version; + this.targetFrameworkVersion = targetFrameworkVersion; if (targetFramework == TargetFrameworkIdentifier.NETStandard) { // .NET Standard 2.1 is implemented by .NET Core 3.0 or higher - if (version.Major == 2 && version.Minor == 1) { - this.version = new Version(3, 0, 0); + if (targetFrameworkVersion.Major == 2 && targetFrameworkVersion.Minor == 1) { + this.targetFrameworkVersion = new Version(3, 0, 0); } } - packageBasePaths.Add(basePath); + searchPaths.Add(basePath); var depsJsonFileName = Path.Combine(basePath, $"{assemblyName}.deps.json"); if (File.Exists(depsJsonFileName)) { @@ -106,17 +107,17 @@ namespace ICSharpCode.Decompiler.Metadata public void AddSearchDirectory(string path) { - this.packageBasePaths.Add(path); + this.searchPaths.Add(path); } public void RemoveSearchDirectory(string path) { - this.packageBasePaths.Remove(path); + this.searchPaths.Remove(path); } public string TryResolveDotNetCore(IAssemblyReference name) { - foreach (var basePath in packageBasePaths) { + foreach (var basePath in searchPaths.Concat(packageBasePaths)) { if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) { return Path.Combine(basePath, name.Name + ".dll"); } else if (File.Exists(Path.Combine(basePath, name.Name + ".exe"))) { @@ -124,7 +125,7 @@ namespace ICSharpCode.Decompiler.Metadata } } - return FallbackToDotNetSharedDirectory(name, version); + return FallbackToDotNetSharedDirectory(name); } internal string GetReferenceAssemblyPath(string targetFramework) @@ -169,7 +170,7 @@ namespace ICSharpCode.Decompiler.Metadata } } - string FallbackToDotNetSharedDirectory(IAssemblyReference name, Version version) + string FallbackToDotNetSharedDirectory(IAssemblyReference name) { if (dotnetBasePath == null) return null; @@ -177,7 +178,7 @@ namespace ICSharpCode.Decompiler.Metadata foreach (var basePath in basePaths) { if (!Directory.Exists(basePath)) continue; - var closestVersion = GetClosestVersionFolder(basePath, version); + var closestVersion = GetClosestVersionFolder(basePath, targetFrameworkVersion); if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".dll"))) { return Path.Combine(basePath, closestVersion, name.Name + ".dll"); } else if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".exe"))) { @@ -189,15 +190,17 @@ namespace ICSharpCode.Decompiler.Metadata static string GetClosestVersionFolder(string basePath, Version version) { - string result = null; - foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(d => ConvertToVersion(d.Name)).Where(v => v.Item1 != null).OrderByDescending(v => v.Item1)) { - if (folder.Item1 >= version) - result = folder.Item2; + var foundVersions = new DirectoryInfo(basePath).GetDirectories() + .Select(d => ConvertToVersion(d.Name)) + .Where(v => v.version != null); + foreach (var folder in foundVersions.OrderBy(v => v.Item1)) { + if (folder.version >= version) + return folder.directoryName; } - return result ?? version.ToString(); + return version.ToString(); } - internal static (Version, string) ConvertToVersion(string name) + internal static (Version version, string directoryName) ConvertToVersion(string name) { string RemoveTrailingVersionInfo() { diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 3186fa3d3..1f4108302 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -327,9 +327,13 @@ namespace ICSharpCode.Decompiler.Metadata if (assembly != null) return assembly; - assembly = SearchDirectory(name, framework_dirs); - if (assembly != null) - return assembly; + // when decompiling assemblies that target frameworks prior to 4.0, we can fall back to the 4.0 assemblies in case the target framework is not installed. + // but when looking for Microsoft.Build.Framework, Version=15.0.0.0 we should not use the version 4.0 assembly here so that the LoadedAssembly logic can instead fall back to version 15.1.0.0 + if (name.Version <= new Version(4, 0, 0, 0)) { + assembly = SearchDirectory(name, framework_dirs); + if (assembly != null) + return assembly; + } if (throwOnError) throw new AssemblyResolutionException(name); diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index fc0e1bcdc..8f48a19e2 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; @@ -31,6 +32,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.PdbProvider; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; +using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.Options; namespace ICSharpCode.ILSpy @@ -318,6 +320,17 @@ namespace ICSharpCode.ILSpy static readonly Dictionary loadingAssemblies = new Dictionary(); MyUniversalResolver universalResolver; + /// + /// 1) try to find exact match by tfm + full asm name in loaded assemblies + /// 2) try to find match in search paths + /// 3) if a.deps.json is found: search %USERPROFILE%/.nuget/packages/* as well + /// 4) look in /dotnet/shared/{runtime-pack}/{closest-version} + /// 5) if the version is retargetable or all zeros or ones, search C:\Windows\Microsoft.NET\Framework64\v4.0.30319 + /// 6) For "mscorlib.dll" we use the exact same assembly with which ILSpy runs + /// 7) Search the GAC + /// 8) search C:\Windows\Microsoft.NET\Framework64\v4.0.30319 + /// 9) try to find match by asm name (no tfm/version) in loaded assemblies + /// LoadedAssembly LookupReferencedAssemblyInternal(IAssemblyReference fullName, bool isWinRT, string tfm) { string key = tfm + ";" + (isWinRT ? fullName.Name : fullName.FullName); @@ -359,8 +372,29 @@ namespace ICSharpCode.ILSpy LoadedAssemblyReferencesInfo.AddMessage(fullName.ToString(), MessageKind.Info, "Success - Loading from: " + file); asm = new LoadedAssembly(assemblyList, file) { IsAutoLoaded = true }; } else { - LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.ToString(), MessageKind.Error, "Could not find reference: " + fullName); - return null; + var candidates = new List<(LoadedAssembly assembly, Version version)>(); + + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { + var module = loaded.GetPEFileOrNull(); + var reader = module?.Metadata; + if (reader == null || !reader.IsAssembly) continue; + var asmDef = reader.GetAssemblyDefinition(); + var asmDefName = reader.GetString(asmDef.Name); + if (fullName.Name.Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) { + candidates.Add((loaded, asmDef.Version)); + } + } + + if (candidates.Count == 0) { + LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.ToString(), MessageKind.Error, "Could not find reference: " + fullName); + return null; + } + + candidates.SortBy(c => c.version); + + var bestCandidate = candidates.FirstOrDefault(c => c.version >= fullName.Version).assembly ?? candidates.Last().assembly; + LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.ToString(), MessageKind.Info, "Success - Found in Assembly List with different TFM or version: " + bestCandidate.fileName); + return bestCandidate; } loadingAssemblies.Add(file, asm); } From 3108f7eba6eae8296d05802c0ec8382f012026fc Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:32:56 +0200 Subject: [PATCH 16/92] ILSpy.AddIn: Remove unused code. --- ILSpy.AddIn/Commands/OpenCodeItemCommand.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs index c98481363..d4aa3a30f 100644 --- a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs +++ b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs @@ -51,7 +51,6 @@ namespace ICSharpCode.ILSpy.AddIn.Commands ThreadHelper.ThrowIfNotOnUIThread(); var document = owner.DTE.ActiveDocument; - var selection = (EnvDTE.TextPoint)((EnvDTE.TextSelection)document.Selection).ActivePoint; var id = owner.Workspace.CurrentSolution.GetDocumentIdsWithFilePath(document.FullName).FirstOrDefault(); if (id == null) return null; @@ -59,14 +58,6 @@ namespace ICSharpCode.ILSpy.AddIn.Commands return owner.Workspace.CurrentSolution.GetDocument(id); } - EnvDTE.TextPoint GetEditorSelection() - { - ThreadHelper.ThrowIfNotOnUIThread(); - - var document = owner.DTE.ActiveDocument; - return ((EnvDTE.TextSelection)document.Selection).ActivePoint; - } - protected override async void OnExecute(object sender, EventArgs e) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); From 75783054dc3c38c5ca407382ca8fc8c588f60184 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:39:19 +0200 Subject: [PATCH 17/92] Move ILSpy distribution to subfolder inside VSIX. --- ILSpy.AddIn/Commands/OpenILSpyCommand.cs | 2 +- ILSpy.AddIn/ILSpy.AddIn.csproj | 40 ++++++++---------------- ILSpy.AddIn/ILSpyInstance.cs | 2 +- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs index 1d569193a..cf2d65768 100644 --- a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs +++ b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands protected string GetILSpyPath() { var basePath = Path.GetDirectoryName(typeof(ILSpyAddInPackage).Assembly.Location); - return Path.Combine(basePath, "ILSpy.exe"); + return Path.Combine(basePath, "ILSpy", "ILSpy.exe"); } protected void OpenAssembliesInILSpy(ILSpyParameters parameters) diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 1cf8c6a09..b4d2288bf 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -51,10 +51,15 @@ - + + + false + false + + @@ -101,38 +106,19 @@ - - - - - - - - - - - - - - - - - - - - - - - + + true + \ + + - + true - \ + \ILSpy - diff --git a/ILSpy.AddIn/ILSpyInstance.cs b/ILSpy.AddIn/ILSpyInstance.cs index adf922328..b8c04bd14 100644 --- a/ILSpy.AddIn/ILSpyInstance.cs +++ b/ILSpy.AddIn/ILSpyInstance.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.AddIn static string GetILSpyPath() { var basePath = Path.GetDirectoryName(typeof(ILSpyAddInPackage).Assembly.Location); - return Path.Combine(basePath, "ILSpy.exe"); + return Path.Combine(basePath, "ILSpy", "ILSpy.exe"); } public void Start() From 5eaaf610319f51224a3cf12581048bd2c82260b0 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 14:39:53 +0200 Subject: [PATCH 18/92] VSIX: use elvis --- ILSpy.AddIn/Commands/OpenCodeItemCommand.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs index d4aa3a30f..07cdd9989 100644 --- a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs +++ b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs @@ -38,10 +38,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands var document = owner.DTE.ActiveDocument; menuItem.Visible = - (document != null) && - (document.ProjectItem != null) && - (document.ProjectItem.ContainingProject != null) && - (document.ProjectItem.ContainingProject.ConfigurationManager != null) && + (document?.ProjectItem?.ContainingProject?.ConfigurationManager != null) && !string.IsNullOrEmpty(document.ProjectItem.ContainingProject.FileName); } } From fc51dd17a5d4a498ec67371832488aef9d22c682 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 23 Jul 2020 11:50:33 +0200 Subject: [PATCH 19/92] Remove outdated comment. The `PickExitPoint` heuristic is no longer using "amount of code" but the IL block order. --- ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs index b9d6345f4..36632f739 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs @@ -200,11 +200,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// * use only a single exit point if at all possible /// * minimize the amount of code in the in-loop partition /// (thus: maximize the amount of code in the out-of-loop partition) - /// "amount of code" could be measured as: - /// * number of basic blocks - /// * number of instructions directly in those basic blocks (~= number of statements) - /// * number of instructions in those basic blocks (~= number of expressions) - /// (we currently use the number of statements) /// /// Observations: /// * If a node is in-loop, so are all its ancestors in the dominator tree (up to the loop entry point) From bdea1950a84cdc4b74cdd74b2c4e1c04e7d08368 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 6 Jun 2020 15:48:26 +0200 Subject: [PATCH 20/92] Add `#if !NETCORE` around extension methods that are included with .NET Core 3 --- ICSharpCode.Decompiler/IL/ILReader.cs | 8 ++++---- .../IL/Instructions/DynamicInstructions.cs | 1 + ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs | 2 +- ICSharpCode.Decompiler/Util/CollectionExtensions.cs | 8 ++++++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index e86597bd9..c85375d2d 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -515,10 +515,10 @@ namespace ICSharpCode.Decompiler.IL var blockBuilder = new BlockBuilder(body, variableByExceptionHandler); blockBuilder.CreateBlocks(mainContainer, instructionBuilder, isBranchTarget, cancellationToken); var function = new ILFunction(this.method, body.GetCodeSize(), this.genericContext, mainContainer, kind); - CollectionExtensions.AddRange(function.Variables, parameterVariables); - CollectionExtensions.AddRange(function.Variables, localVariables); - CollectionExtensions.AddRange(function.Variables, stackVariables); - CollectionExtensions.AddRange(function.Variables, variableByExceptionHandler.Values); + function.Variables.AddRange(parameterVariables); + function.Variables.AddRange(localVariables); + function.Variables.AddRange(stackVariables); + function.Variables.AddRange(variableByExceptionHandler.Values); function.AddRef(); // mark the root node var removedBlocks = new List(); foreach (var c in function.Descendants.OfType()) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs index 5a3b64b54..d11c69171 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using ICSharpCode.Decompiler.IL.Patterns; using ICSharpCode.Decompiler.TypeSystem; diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index b96909efc..4c5fe176d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -138,7 +138,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms }; block.Instructions.Insert(i++, new StLoc(uninlinedArgs[j], arg)); } - CollectionExtensions.AddRange(v.Function.Variables, uninlinedArgs); + v.Function.Variables.AddRange(uninlinedArgs); // perform copy propagation: foreach (var expr in v.LoadInstructions.ToArray()) { var clone = copiedExpr.Clone(); diff --git a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs index 4c01285df..df585d159 100644 --- a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs +++ b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs @@ -12,10 +12,12 @@ namespace ICSharpCode.Decompiler.Util value = pair.Value; } +#if !NETCORE public static IEnumerable<(A, B)> Zip(this IEnumerable input1, IEnumerable input2) { return input1.Zip(input2, (a, b) => (a, b)); } +#endif public static IEnumerable<(A, B)> ZipLongest(this IEnumerable input1, IEnumerable input2) { @@ -51,10 +53,12 @@ namespace ICSharpCode.Decompiler.Util } } +#if !NETCORE public static HashSet ToHashSet(this IEnumerable input) { return new HashSet(input); } +#endif public static IEnumerable SkipLast(this IReadOnlyCollection input, int count) { @@ -323,7 +327,7 @@ namespace ICSharpCode.Decompiler.Util return first; } - #region Aliases/shortcuts for Enumerable extension methods +#region Aliases/shortcuts for Enumerable extension methods public static bool Any(this ICollection list) => list.Count > 0; public static bool Any(this T[] array, Predicate match) => Array.Exists(array, match); public static bool Any(this List list, Predicate match) => list.Exists(match); @@ -335,6 +339,6 @@ namespace ICSharpCode.Decompiler.Util public static T FirstOrDefault(this List list, Predicate predicate) => list.Find(predicate); public static T Last(this IList list) => list[list.Count - 1]; - #endregion +#endregion } } From a231ab54d4a16e0db88e279b112fddb594a1368c Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 21:02:43 +0200 Subject: [PATCH 21/92] Add test cases --- ICSharpCode.Decompiler.Tests/Helpers/Tester.cs | 3 +++ .../PrettyTestRunner.cs | 2 +- .../TestCases/Pretty/LocalFunctions.cs | 18 +++++++++++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index 1dc72a59f..f3c9536d0 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -257,6 +257,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers preprocessorSymbols.Add("LEGACY_CSC"); preprocessorSymbols.Add("LEGACY_VBC"); } + if (flags.HasFlag(CompilerOptions.Preview)) { + preprocessorSymbols.Add("CS90"); + } return preprocessorSymbols; } diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index c5687aa85..b657ad839 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void LocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) { - RunForLibrary(cscOptions: cscOptions); + RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs index 1f73795e2..10308cbbd 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs @@ -23,6 +23,12 @@ namespace LocalFunctions { internal class LocalFunctions { + [AttributeUsage(AttributeTargets.All)] + internal class MyAttribute : Attribute + { + + } + public class Generic where T1 : struct, ICloneable, IConvertible { public int MixedLocalFunction() where T2 : ICloneable, IConvertible @@ -31,15 +37,21 @@ namespace LocalFunctions object z = this; for (int j = 0; j < 10; j++) { int i = 0; - i += NonStaticMethod6(); - int NonStaticMethod6() + i += NonStaticMethod6(0); +#if CS90 + [My] + [return: My] + int NonStaticMethod6([My] int unused) +#else + int NonStaticMethod6(int unused) +#endif { t2 = default(T2); int l = 0; return NonStaticMethod6_1() + NonStaticMethod6_1() + z.GetHashCode(); int NonStaticMethod6_1() { - return i + l + NonStaticMethod6() + StaticMethod1(); + return i + l + NonStaticMethod6(0) + StaticMethod1(); } } } From 431bbaa489debf048809d155d6bb2f6b6333838d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 21:05:16 +0200 Subject: [PATCH 22/92] RequiredNamespaceCollector: properly handle parts of methods --- .../CSharp/RequiredNamespaceCollector.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index 878edf8fe..2aa5dd8f7 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -93,17 +93,18 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(field.ReturnType); break; case IMethod method: - HandleAttributes(method.GetAttributes()); - HandleAttributes(method.GetReturnTypeAttributes()); - CollectNamespacesForTypeReference(method.ReturnType); - foreach (var param in method.Parameters) { - HandleAttributes(param.GetAttributes()); - CollectNamespacesForTypeReference(param.Type); - } - HandleTypeParameters(method.TypeParameters); var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); foreach (var part in parts) { + var partMethod = module.ResolveMethod(part, genericContext); + HandleAttributes(partMethod.GetAttributes()); + HandleAttributes(partMethod.GetReturnTypeAttributes()); + CollectNamespacesForTypeReference(partMethod.ReturnType); + foreach (var param in partMethod.Parameters) { + HandleAttributes(param.GetAttributes()); + CollectNamespacesForTypeReference(param.Type); + } + HandleTypeParameters(partMethod.TypeParameters); HandleOverrides(part.GetMethodImplementations(module.metadata), module); var methodDef = module.metadata.GetMethodDefinition(part); if (method.HasBody) { From 18ace002662dfb203f415165a964ff2e1d10d0b7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 21:07:35 +0200 Subject: [PATCH 23/92] Refactor LocalFunctionDeclarationStatement + LocalFunctionMethod --- .../CSharp/CSharpDecompiler.cs | 41 +++++++----- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 12 +--- .../CSharp/ExpressionBuilder.cs | 6 +- .../OutputVisitor/CSharpOutputVisitor.cs | 14 +--- .../CSharp/StatementBuilder.cs | 29 ++------ .../LocalFunctionDeclarationStatement.cs | 67 ++----------------- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 8 ++- .../Transforms/ContextTrackingVisitor.cs | 20 +++--- .../IL/Transforms/LocalFunctionDecompiler.cs | 2 +- .../Implementation/LocalFunctionMethod.cs | 31 +++++++-- 10 files changed, 85 insertions(+), 145 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 70358a8bc..0c18b39a3 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1345,30 +1345,35 @@ namespace ICSharpCode.Decompiler.CSharp } entityDecl.AddAnnotation(function); - if (function.IsIterator) { - if (localSettings.DecompileMemberBodies && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) { - body.Add(new YieldBreakStatement()); - } - if (function.IsAsync) { - RemoveAttribute(entityDecl, KnownAttribute.AsyncIteratorStateMachine); - } else { - RemoveAttribute(entityDecl, KnownAttribute.IteratorStateMachine); - } - if (function.StateMachineCompiledWithMono) { - RemoveAttribute(entityDecl, KnownAttribute.DebuggerHidden); - } + CleanUpMethodDeclaration(entityDecl, body, function, localSettings.DecompileMemberBodies); + } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + throw new DecompilerException(module, method, innerException); + } + } + + internal static void CleanUpMethodDeclaration(EntityDeclaration entityDecl, BlockStatement body, ILFunction function, bool decompileBody = true) + { + if (function.IsIterator) { + if (decompileBody && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) { + body.Add(new YieldBreakStatement()); } if (function.IsAsync) { - entityDecl.Modifiers |= Modifiers.Async; - RemoveAttribute(entityDecl, KnownAttribute.AsyncStateMachine); - RemoveAttribute(entityDecl, KnownAttribute.DebuggerStepThrough); + RemoveAttribute(entityDecl, KnownAttribute.AsyncIteratorStateMachine); + } else { + RemoveAttribute(entityDecl, KnownAttribute.IteratorStateMachine); } - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { - throw new DecompilerException(module, method, innerException); + if (function.StateMachineCompiledWithMono) { + RemoveAttribute(entityDecl, KnownAttribute.DebuggerHidden); + } + } + if (function.IsAsync) { + entityDecl.Modifiers |= Modifiers.Async; + RemoveAttribute(entityDecl, KnownAttribute.AsyncStateMachine); + RemoveAttribute(entityDecl, KnownAttribute.DebuggerStepThrough); } } - bool RemoveAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType) + internal static bool RemoveAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType) { bool found = false; foreach (var section in entityDecl.Attributes) { diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 9eeec424c..d1d633a0c 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -197,8 +197,7 @@ namespace ICSharpCode.Decompiler.CSharp } else if (localFunction != null) { var ide = new IdentifierExpression(localFunction.Name); if (method.TypeArguments.Count > 0) { - int skipCount = localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters; - ide.TypeArguments.AddRange(method.TypeArguments.Skip(skipCount).Select(expressionBuilder.ConvertType)); + ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } ide.AddAnnotation(localFunction); target = ide.WithoutILInstruction() @@ -1327,7 +1326,6 @@ namespace ICSharpCode.Decompiler.CSharp target = default; targetType = default; methodName = localFunction.Name; - // TODO : think about how to handle generic local functions } else if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { step = 5; targetType = method.Parameters[0].Type; @@ -1406,11 +1404,7 @@ namespace ICSharpCode.Decompiler.CSharp } else { var ide = new IdentifierExpression(methodName); if ((step & 2) != 0) { - int skipCount = 0; - if (localFunction != null && method.TypeArguments.Count > 0) { - skipCount = localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters; - } - ide.TypeArguments.AddRange(method.TypeArguments.Skip(skipCount).Select(expressionBuilder.ConvertType)); + ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } targetExpression = ide.WithRR(result); } @@ -1469,7 +1463,7 @@ namespace ICSharpCode.Decompiler.CSharp method.DeclaringType, new IParameterizedMember[] { method } ) - }, method.TypeArguments.Skip(localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters).ToArray() + }, method.TypeArguments ); } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index c0c583b00..140329dcd 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -92,6 +92,7 @@ namespace ICSharpCode.Decompiler.CSharp this.astBuilder = new TypeSystemAstBuilder(resolver); this.astBuilder.AlwaysUseShortTypeNames = true; this.astBuilder.AddResolveResultAnnotations = true; + this.astBuilder.ShowAttributes = true; this.astBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables; this.typeInference = new TypeInference(compilation) { Algorithm = TypeInferenceAlgorithm.Improved }; } @@ -1983,7 +1984,7 @@ namespace ICSharpCode.Decompiler.CSharp return SpecialType.UnknownType; } - internal IEnumerable MakeParameters(IReadOnlyList parameters, ILFunction function) + IEnumerable MakeParameters(IReadOnlyList parameters, ILFunction function) { var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index); int i = 0; @@ -1992,9 +1993,6 @@ namespace ICSharpCode.Decompiler.CSharp if (string.IsNullOrEmpty(pd.Name) && !pd.Type.IsArgList()) { // needs to be consistent with logic in ILReader.CreateILVarable(ParameterDefinition) pd.Name = "P_" + i; - // if this is a local function, we have to skip the parameters for closure references - if (settings.LocalFunctions && function.Kind == ILFunctionKind.LocalFunction && IL.Transforms.LocalFunctionDecompiler.IsClosureParameter(parameter, decompilationContext)) - break; } if (settings.AnonymousTypes && parameter.Type.ContainsAnonymousType()) pd.Type = null; diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index e9b3a90cd..81f3f0c6e 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1876,19 +1876,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitLocalFunctionDeclarationStatement(LocalFunctionDeclarationStatement localFunctionDeclarationStatement) { StartNode(localFunctionDeclarationStatement); - - WriteModifiers(localFunctionDeclarationStatement.ModifierTokens); - localFunctionDeclarationStatement.ReturnType.AcceptVisitor(this); - Space(); - WriteIdentifier(localFunctionDeclarationStatement.NameToken); - WriteTypeParameters(localFunctionDeclarationStatement.TypeParameters); - Space(policy.SpaceBeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(localFunctionDeclarationStatement.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - foreach (Constraint constraint in localFunctionDeclarationStatement.Constraints) { - constraint.AcceptVisitor(this); - } - WriteMethodBody(localFunctionDeclarationStatement.Body, policy.MethodBraceStyle); - + localFunctionDeclarationStatement.Declaration.AcceptVisitor(this); EndNode(localFunctionDeclarationStatement); } diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index c84b2850b..052ab9a59 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -1002,34 +1002,19 @@ namespace ICSharpCode.Decompiler.CSharp LocalFunctionDeclarationStatement TranslateFunction(ILFunction function) { - var stmt = new LocalFunctionDeclarationStatement(); var nestedBuilder = new StatementBuilder(typeSystem, exprBuilder.decompilationContext, function, settings, cancellationToken); - stmt.Name = function.Name; - stmt.Parameters.AddRange(exprBuilder.MakeParameters(function.Parameters, function)); - stmt.ReturnType = exprBuilder.ConvertType(function.Method.ReturnType); - stmt.Body = nestedBuilder.ConvertAsBlock(function.Body); + var astBuilder = exprBuilder.astBuilder; + var method = (MethodDeclaration)astBuilder.ConvertEntity(function.ReducedMethod); + method.Body = nestedBuilder.ConvertAsBlock(function.Body); Comment prev = null; foreach (string warning in function.Warnings) { - stmt.Body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment); + method.Body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment); } - if (function.Method.TypeParameters.Count > 0) { - var astBuilder = exprBuilder.astBuilder; - if (astBuilder.ShowTypeParameters) { - int skipCount = function.ReducedMethod.NumberOfCompilerGeneratedTypeParameters; - stmt.TypeParameters.AddRange(function.Method.TypeParameters.Skip(skipCount).Select(t => astBuilder.ConvertTypeParameter(t))); - if (astBuilder.ShowTypeParameterConstraints) { - stmt.Constraints.AddRange(function.Method.TypeParameters.Skip(skipCount).Select(t => astBuilder.ConvertTypeParameterConstraint(t)).Where(c => c != null)); - } - } - } - if (function.IsAsync) { - stmt.Modifiers |= Modifiers.Async; - } - if (settings.StaticLocalFunctions && function.ReducedMethod.IsStaticLocalFunction) { - stmt.Modifiers |= Modifiers.Static; - } + CSharpDecompiler.CleanUpMethodDeclaration(method, method.Body, function); + CSharpDecompiler.RemoveAttribute(method, KnownAttribute.CompilerGenerated); + var stmt = new LocalFunctionDeclarationStatement(method); stmt.AddAnnotation(new MemberResolveResult(null, function.ReducedMethod)); stmt.WithILInstruction(function); return stmt; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs index 47ff1641c..105789bb3 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs @@ -16,69 +16,22 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Collections.Generic; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; namespace ICSharpCode.Decompiler.CSharp.Syntax { public class LocalFunctionDeclarationStatement : Statement { - public AstNodeCollection TypeParameters { - get { return GetChildrenByRole(Roles.TypeParameter); } - } - - public CSharpTokenNode LParToken { - get { return GetChildByRole(Roles.LPar); } - } - - public AstNodeCollection Parameters { - get { return GetChildrenByRole(Roles.Parameter); } - } + public static readonly Role MethodDeclarationRole = new Role("Method"); - public CSharpTokenNode RParToken { - get { return GetChildByRole(Roles.RPar); } + public MethodDeclaration Declaration { + get { return GetChildByRole(MethodDeclarationRole); } + set { SetChildByRole(MethodDeclarationRole, value); } } - public AstNodeCollection Constraints { - get { return GetChildrenByRole(Roles.Constraint); } - } - - public BlockStatement Body { - get { return GetChildByRole(Roles.Body); } - set { SetChildByRole(Roles.Body, value); } - } - - public Modifiers Modifiers { - get { return EntityDeclaration.GetModifiers(this); } - set { EntityDeclaration.SetModifiers(this, value); } - } - - public bool HasModifier(Modifiers mod) + public LocalFunctionDeclarationStatement(MethodDeclaration methodDeclaration) { - return (Modifiers & mod) == mod; - } - - public IEnumerable ModifierTokens { - get { return GetChildrenByRole(EntityDeclaration.ModifierRole); } - } - - public virtual string Name { - get { - return GetChildByRole(Roles.Identifier).Name; - } - set { - SetChildByRole(Roles.Identifier, Identifier.Create(value, TextLocation.Empty)); - } - } - - public virtual Identifier NameToken { - get { return GetChildByRole(Roles.Identifier); } - set { SetChildByRole(Roles.Identifier, value); } - } - - public virtual AstType ReturnType { - get { return GetChildByRole(Roles.Type); } - set { SetChildByRole(Roles.Type, value); } + AddChild(methodDeclaration, MethodDeclarationRole); } public override void AcceptVisitor(IAstVisitor visitor) @@ -98,13 +51,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax protected internal override bool DoMatch(AstNode other, Match match) { - LocalFunctionDeclarationStatement o = other as LocalFunctionDeclarationStatement; - return o != null && MatchString(this.Name, o.Name) - && (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) - && this.ReturnType.DoMatch(o.ReturnType, match) - && this.TypeParameters.DoMatch(o.TypeParameters, match) - && this.Parameters.DoMatch(o.Parameters, match) && this.Constraints.DoMatch(o.Constraints, match) - && this.Body.DoMatch(o.Body, match); + return other is LocalFunctionDeclarationStatement o && Declaration.DoMatch(o.Declaration, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 3fe6a5f02..33464c99a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -1799,6 +1799,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return !member.IsStatic; case SymbolKind.Destructor: return false; + case SymbolKind.Method: + return !((IMethod)member).IsLocalFunction; default: return true; } @@ -1811,7 +1813,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax m |= ModifierFromAccessibility (member.Accessibility); } if (this.ShowModifiers) { - if (member.IsStatic) { + if (member is LocalFunctionMethod localFunction) { + if (localFunction.IsStaticLocalFunction) { + m |= Modifiers.Static; + } + } else if (member.IsStatic) { m |= Modifiers.Static; } else { var declaringType = member.DeclaringType; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs index adf6e3f22..3f3015a33 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs @@ -55,56 +55,56 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration) { - Debug.Assert(currentMethod == null); + var oldMethod = currentMethod; try { currentMethod = methodDeclaration.GetSymbol() as IMethod; return base.VisitMethodDeclaration(methodDeclaration); } finally { - currentMethod = null; + currentMethod = oldMethod; } } public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { - Debug.Assert(currentMethod == null); + var oldMethod = currentMethod; try { currentMethod = constructorDeclaration.GetSymbol() as IMethod; return base.VisitConstructorDeclaration(constructorDeclaration); } finally { - currentMethod = null; + currentMethod = oldMethod; } } public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) { - Debug.Assert(currentMethod == null); + var oldMethod = currentMethod; try { currentMethod = destructorDeclaration.GetSymbol() as IMethod; return base.VisitDestructorDeclaration(destructorDeclaration); } finally { - currentMethod = null; + currentMethod = oldMethod; } } public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { - Debug.Assert(currentMethod == null); + var oldMethod = currentMethod; try { currentMethod = operatorDeclaration.GetSymbol() as IMethod; return base.VisitOperatorDeclaration(operatorDeclaration); } finally { - currentMethod = null; + currentMethod = oldMethod; } } public override TResult VisitAccessor(Accessor accessor) { - Debug.Assert(currentMethod == null); + var oldMethod = currentMethod; try { currentMethod = accessor.GetSymbol() as IMethod; return base.VisitAccessor(accessor); } finally { - currentMethod = null; + currentMethod = oldMethod; } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index de7e36c48..0b9ae651e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -484,7 +484,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; parametersToRemove++; } - return new LocalFunctionMethod(method, parametersToRemove, typeParametersToRemove); + return new LocalFunctionMethod(method, method.Name, parametersToRemove, typeParametersToRemove); } static void TransformToLocalFunctionReference(ILFunction function, CallInstruction useSite) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs index 242b6b193..57cce32dd 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs @@ -31,11 +31,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { readonly IMethod baseMethod; - public LocalFunctionMethod(IMethod baseMethod, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) + public LocalFunctionMethod(IMethod baseMethod, string name, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) { if (baseMethod == null) throw new ArgumentNullException(nameof(baseMethod)); this.baseMethod = baseMethod; + this.Name = name; this.NumberOfCompilerGeneratedParameters = numberOfCompilerGeneratedParameters; this.NumberOfCompilerGeneratedTypeParameters = numberOfCompilerGeneratedTypeParameters; } @@ -65,7 +66,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override string ToString() { - return string.Format("[LocalFunctionMethod: ReducedFrom={0}, NumberOfGeneratedParameters={1}, NumberOfCompilerGeneratedTypeParameters={2}]", ReducedFrom, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + return string.Format("[LocalFunctionMethod: ReducedFrom={0}, Name={1}, NumberOfGeneratedParameters={2}, NumberOfCompilerGeneratedTypeParameters={3}]", ReducedFrom, Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); } internal int NumberOfCompilerGeneratedParameters { get; } @@ -88,7 +89,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return new LocalFunctionMethod( baseMethod.Specialize(substitution), - NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); } IMember IMember.Specialize(TypeParameterSubstitution substitution) @@ -96,7 +97,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return Specialize(substitution); } - public IReadOnlyList TypeParameters => baseMethod.TypeParameters; public bool IsExtensionMethod => baseMethod.IsExtensionMethod; public bool IsLocalFunction => true; public bool IsConstructor => baseMethod.IsConstructor; @@ -107,7 +107,24 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IMember AccessorOwner => baseMethod.AccessorOwner; public MethodSemanticsAttributes AccessorKind => baseMethod.AccessorKind; public IMethod ReducedFrom => baseMethod; - public IReadOnlyList TypeArguments => baseMethod.TypeArguments; + + List typeParameters; + public IReadOnlyList TypeParameters { + get { + if (typeParameters == null) + typeParameters = new List(baseMethod.TypeParameters.Skip(NumberOfCompilerGeneratedTypeParameters)); + return typeParameters; + } + } + + List typeArguments; + public IReadOnlyList TypeArguments { + get { + if (typeArguments == null) + typeArguments = new List(baseMethod.TypeArguments.Skip(NumberOfCompilerGeneratedTypeParameters)); + return typeArguments; + } + } List parameters; public IReadOnlyList Parameters { @@ -137,8 +154,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public Accessibility Accessibility => baseMethod.Accessibility; - public string FullName => baseMethod.FullName; - public string Name => baseMethod.Name; + public string FullName => Name; + public string Name { get; set; } public string ReflectionName => baseMethod.ReflectionName; public string Namespace => baseMethod.Namespace; From acea95d0a153f96ebb8fbbcacfbc404038d3d223 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 21:08:53 +0200 Subject: [PATCH 24/92] Properly rename LocalFunctionMethod.Name on all instructions --- .../IL/Transforms/AssignVariableNames.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index d95cc63da..86541e59a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -20,6 +20,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; + using Humanizer; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.TypeSystem; @@ -51,6 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILTransformContext context; string[] currentFieldNames; Dictionary reservedVariableNames; + Dictionary localFunctionMapping; HashSet loopCounters; const char maxLoopVariableName = 'n'; @@ -59,6 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms this.context = context; currentFieldNames = function.Method.DeclaringTypeDefinition.Fields.Select(f => f.Name).ToArray(); reservedVariableNames = new Dictionary(); + localFunctionMapping = new Dictionary(); loopCounters = CollectLoopCounters(function); foreach (var f in function.Descendants.OfType()) { if (f.Method != null) { @@ -180,6 +184,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!LocalFunctionDecompiler.ParseLocalFunctionName(localFunction.Name, out _, out var newName) || !IsValidName(newName)) newName = null; localFunction.Name = newName; + localFunction.ReducedMethod.Name = newName; } // Now generate names: var mapping = new Dictionary(ILVariableEqualityComparer.Instance); @@ -199,6 +204,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms newName = GetAlternativeName("f"); } localFunction.Name = newName; + localFunction.ReducedMethod.Name = newName; + localFunctionMapping[(MethodDefinitionHandle)localFunction.ReducedMethod.MetadataToken] = newName; + } + foreach (var inst in function.Descendants) { + LocalFunctionMethod localFunction; + switch (inst) { + case Call call: + localFunction = call.Method as LocalFunctionMethod; + break; + case LdFtn ldftn: + localFunction = ldftn.Method as LocalFunctionMethod; + break; + default: + localFunction = null; + break; + } + if (localFunction == null || !localFunctionMapping.TryGetValue((MethodDefinitionHandle)localFunction.MetadataToken, out var name)) + continue; + localFunction.Name = name; } } From 67b2a45292f141b78b95f5753c32ed95ff483e63 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Jul 2020 21:09:24 +0200 Subject: [PATCH 25/92] Improve tooltips and highlighting of local functions --- .../CSharp/OutputVisitor/CSharpAmbience.cs | 3 +- .../Output/TextTokenWriter.cs | 63 ++++++++++--------- ILSpy/Languages/CSharpLanguage.cs | 3 + 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs index c6b09f079..dab35cace 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs @@ -24,6 +24,7 @@ using System.Linq; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { @@ -103,7 +104,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (symbol is ITypeDefinition) WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy); - else if (symbol is IMember) + else if (symbol is IMember && !(symbol is LocalFunctionMethod)) WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy); else writer.WriteIdentifier(Identifier.Create(symbol.Name)); diff --git a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs index 1ca9a792a..82730d64f 100644 --- a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Resolver; @@ -26,6 +27,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler { @@ -39,7 +41,7 @@ namespace ICSharpCode.Decompiler bool inDocumentationComment = false; bool firstUsingDeclaration; bool lastUsingDeclaration; - + public TextTokenWriter(ITextOutput output, DecompilerSettings settings, IDecompilerTypeSystem typeSystem) { if (output == null) @@ -52,13 +54,13 @@ namespace ICSharpCode.Decompiler this.settings = settings; this.typeSystem = typeSystem; } - + public override void WriteIdentifier(Identifier identifier) { if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { output.Write('@'); } - + var definition = GetCurrentDefinition(); string name = TextWriterTokenWriter.EscapeIdentifier(identifier.Name); switch (definition) { @@ -69,7 +71,7 @@ namespace ICSharpCode.Decompiler output.WriteReference(m, name, true); return; } - + var member = GetCurrentMemberReference(); switch (member) { case IType t: @@ -110,6 +112,7 @@ namespace ICSharpCode.Decompiler if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) { symbol = node.Parent.GetSymbol(); } + if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { var declaringType = member.DeclaringType; if (declaringType != null && declaringType.Kind == TypeKind.Delegate) @@ -123,10 +126,8 @@ namespace ICSharpCode.Decompiler if (symbol == null) return null; - //if (settings.AutomaticEvents && member is FieldDefinition) { - // var field = (FieldDefinition)member; - // return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? member; - //} + if (symbol is LocalFunctionMethod) + return null; return symbol; } @@ -142,14 +143,18 @@ namespace ICSharpCode.Decompiler if (letClauseVariable != null) return letClauseVariable; - var gotoStatement = node as GotoStatement; - if (gotoStatement != null) - { + if (node is GotoStatement gotoStatement) { var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).FirstOrDefault(mr => mr != null); if (method != null) return method + gotoStatement.Label; } + if (node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) { + var symbol = node.Parent.GetSymbol(); + if (symbol is LocalFunctionMethod) + return symbol; + } + return null; } @@ -177,29 +182,29 @@ namespace ICSharpCode.Decompiler return method + label.Label; } - if (node is LocalFunctionDeclarationStatement) { - var localFunction = node.GetResolveResult() as MemberResolveResult; + if (node is MethodDeclaration && node.Parent is LocalFunctionDeclarationStatement) { + var localFunction = node.Parent.GetResolveResult() as MemberResolveResult; if (localFunction != null) return localFunction.Member; } return null; } - + ISymbol GetCurrentDefinition() { if (nodeStack == null || nodeStack.Count == 0) return null; - + var node = nodeStack.Peek(); if (node is Identifier) node = node.Parent; if (IsDefinition(ref node)) return node.GetSymbol(); - + return null; } - + public override void WriteKeyword(Role role, string keyword) { //To make reference for 'this' and 'base' keywords in the ClassName():this() expression @@ -211,7 +216,7 @@ namespace ICSharpCode.Decompiler } output.Write(keyword); } - + public override void WriteToken(Role role, string token) { switch (token) { @@ -253,22 +258,22 @@ namespace ICSharpCode.Decompiler break; } } - + public override void Space() { output.Write(' '); } - + public override void Indent() { output.Indent(); } - + public override void Unindent() { output.Unindent(); } - + public override void NewLine() { if (!firstUsingDeclaration && lastUsingDeclaration) { @@ -277,7 +282,7 @@ namespace ICSharpCode.Decompiler } output.WriteLine(); } - + public override void WriteComment(CommentType commentType, string content) { switch (commentType) { @@ -309,7 +314,7 @@ namespace ICSharpCode.Decompiler break; } } - + public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument) { // pre-processor directive must start on its own line @@ -321,7 +326,7 @@ namespace ICSharpCode.Decompiler } output.WriteLine(); } - + public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None) { new TextWriterTokenWriter(new TextOutputWriter(output)).WritePrimitiveValue(value, format); @@ -376,7 +381,7 @@ namespace ICSharpCode.Decompiler break; } } - + public override void StartNode(AstNode node) { if (nodeStack.Count == 0) { @@ -390,7 +395,7 @@ namespace ICSharpCode.Decompiler } nodeStack.Push(node); } - + private bool IsUsingDeclaration(AstNode node) { return node is UsingDeclaration || node is UsingAliasDeclaration; @@ -401,10 +406,10 @@ namespace ICSharpCode.Decompiler if (nodeStack.Pop() != node) throw new InvalidOperationException(); } - + public static bool IsDefinition(ref AstNode node) { - if (node is EntityDeclaration) + if (node is EntityDeclaration && !(node.Parent is LocalFunctionDeclarationStatement)) return true; if (node is VariableInitializer && node.Parent is FieldDeclaration) { node = node.Parent; diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index 8b0253026..96c22ce91 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -648,6 +648,9 @@ namespace ICSharpCode.ILSpy if (!settings.LiftNullables) { flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes; } + if (entity is IMethod m && m.IsLocalFunction) { + writer.WriteIdentifier(Identifier.Create("(local)")); + } new CSharpAmbience() { ConversionFlags = flags, }.ConvertSymbol(entity, writer, settings.CSharpFormattingOptions); From eed9ebc4cf415bd16cb494aaac21ee5c7774ddea Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Sun, 26 Jul 2020 09:45:38 +0200 Subject: [PATCH 26/92] Set version to 6.1 --- ILSpy/Properties/AssemblyInfo.template.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs index ac72179e6..e564bd6b8 100644 --- a/ILSpy/Properties/AssemblyInfo.template.cs +++ b/ILSpy/Properties/AssemblyInfo.template.cs @@ -37,7 +37,7 @@ using System.Diagnostics.CodeAnalysis; internal static class RevisionClass { public const string Major = "6"; - public const string Minor = "0"; + public const string Minor = "1"; public const string Build = "0"; public const string Revision = "$INSERTREVISION$"; public const string VersionName = null; From 33bc9fbef47e70f8fb945c1c53a550cf12e74c49 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 26 Jul 2020 10:17:23 +0200 Subject: [PATCH 27/92] Fix display of generic type parameters of local functions in tooltips --- .../TestCases/Pretty/LocalFunctions.cs | 2 +- ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs index 10308cbbd..c38a81c17 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs @@ -41,7 +41,7 @@ namespace LocalFunctions #if CS90 [My] [return: My] - int NonStaticMethod6([My] int unused) + int NonStaticMethod6<[My] T3>([My] int unused) #else int NonStaticMethod6(int unused) #endif diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs index dab35cace..71506af61 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs @@ -104,7 +104,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (symbol is ITypeDefinition) WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy); - else if (symbol is IMember && !(symbol is LocalFunctionMethod)) + else if (symbol is IMember) WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy); else writer.WriteIdentifier(Identifier.Create(symbol.Name)); @@ -223,7 +223,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { TypeSystemAstBuilder astBuilder = CreateAstBuilder(); EntityDeclaration node = astBuilder.ConvertEntity(member); - if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType && member.DeclaringType != null) { + if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType && member.DeclaringType != null && !(member is LocalFunctionMethod)) { ConvertType(member.DeclaringType, writer, formattingPolicy); writer.WriteToken(Roles.Dot, "."); } From 8d72672e6c991a0f52181ead15c6b1a8420b25e3 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 26 Jul 2020 20:30:03 +0200 Subject: [PATCH 28/92] Reimplement DecompilerSettings.StaticLocalFunctions (was lost in the refactoring in #2077) --- .../IL/Transforms/LocalFunctionDecompiler.cs | 22 ++++++++++++++++++- .../Implementation/LocalFunctionMethod.cs | 15 ++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index 0b9ae651e..003462046 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -484,7 +484,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; parametersToRemove++; } - return new LocalFunctionMethod(method, method.Name, parametersToRemove, typeParametersToRemove); + return new LocalFunctionMethod(method, method.Name, CanBeStaticLocalFunction(), parametersToRemove, typeParametersToRemove); + + bool CanBeStaticLocalFunction() + { + if (!context.Settings.StaticLocalFunctions) + return false; + // Cannot be static because there are closure parameters that will be removed + if (parametersToRemove > 0) + return false; + // no closure parameters, but static: + // we can safely assume, this local function can be declared static + if (method.IsStatic) + return true; + // the local function is used in conjunction with a lambda, which means, + // it is defined inside the display-class type + var declaringType = method.DeclaringTypeDefinition; + if (!declaringType.IsCompilerGenerated()) + return false; + // if there are no instance fields, we can make it a static local function + return !declaringType.GetFields(f => !f.IsStatic).Any(); + } } static void TransformToLocalFunctionReference(ILFunction function, CallInstruction useSite) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs index 57cce32dd..1139366f1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs @@ -31,12 +31,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { readonly IMethod baseMethod; - public LocalFunctionMethod(IMethod baseMethod, string name, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) + public LocalFunctionMethod(IMethod baseMethod, string name, bool isStaticLocalFunction, int numberOfCompilerGeneratedParameters, int numberOfCompilerGeneratedTypeParameters) { if (baseMethod == null) throw new ArgumentNullException(nameof(baseMethod)); this.baseMethod = baseMethod; this.Name = name; + this.IsStaticLocalFunction = isStaticLocalFunction; this.NumberOfCompilerGeneratedParameters = numberOfCompilerGeneratedParameters; this.NumberOfCompilerGeneratedTypeParameters = numberOfCompilerGeneratedTypeParameters; } @@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return baseMethod.Equals(other.baseMethod, typeNormalization) && NumberOfCompilerGeneratedParameters == other.NumberOfCompilerGeneratedParameters - && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters; + && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters + && IsStaticLocalFunction == other.IsStaticLocalFunction; } public override bool Equals(object obj) @@ -56,7 +58,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return baseMethod.Equals(other.baseMethod) && NumberOfCompilerGeneratedParameters == other.NumberOfCompilerGeneratedParameters - && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters; + && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters + && IsStaticLocalFunction == other.IsStaticLocalFunction; } public override int GetHashCode() @@ -66,14 +69,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override string ToString() { - return string.Format("[LocalFunctionMethod: ReducedFrom={0}, Name={1}, NumberOfGeneratedParameters={2}, NumberOfCompilerGeneratedTypeParameters={3}]", ReducedFrom, Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + return string.Format("[LocalFunctionMethod: ReducedFrom={0}, Name={1}, NumberOfGeneratedParameters={2}, NumberOfCompilerGeneratedTypeParameters={3}, IsStaticLocalFunction={4}]", ReducedFrom, Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters, IsStaticLocalFunction); } internal int NumberOfCompilerGeneratedParameters { get; } internal int NumberOfCompilerGeneratedTypeParameters { get; } - internal bool IsStaticLocalFunction => NumberOfCompilerGeneratedParameters == 0 && (baseMethod.IsStatic || (baseMethod.DeclaringTypeDefinition.IsCompilerGenerated() && !baseMethod.DeclaringType.GetFields(f => !f.IsStatic).Any())); + internal bool IsStaticLocalFunction { get; } public IMember MemberDefinition => this; @@ -89,7 +92,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return new LocalFunctionMethod( baseMethod.Specialize(substitution), - Name, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); + Name, IsStaticLocalFunction, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); } IMember IMember.Specialize(TypeParameterSubstitution substitution) From 4b865c27e412c6b255df27540a8c20b2c2437d28 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 27 Jul 2020 21:58:05 +0200 Subject: [PATCH 29/92] Fix #2076: VS AddIn opens reference assembly. --- .../Helpers/Tester.cs | 2 +- .../Metadata/DotNetCorePathFinder.cs | 16 ++++----- .../DotNetCorePathFinderExtensions.cs | 33 ++++++++++++++++--- .../Metadata/UniversalAssemblyResolver.cs | 20 +++++++---- ILSpy.AddIn/AssemblyFileFinder.cs | 23 ++++++------- ILSpy.AddIn/Commands/OpenILSpyCommand.cs | 3 +- ILSpy.AddIn/ILSpyInstance.cs | 4 +-- ILSpy/ILSpy.csproj | 4 +-- ILSpy/LoadedAssembly.cs | 4 ++- ILSpy/MainWindow.xaml.cs | 9 +++++ 10 files changed, 77 insertions(+), 41 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index f3c9536d0..b177b7ef9 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -185,7 +185,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers return Regex.Replace(il, @"'\{[0-9A-F-]+\}'", "''"); } - static readonly string coreRefAsmPath = new DotNetCorePathFinder(new Version(3, 1)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.1"); + static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NETCoreApp, new Version(3, 1)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.1"); static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2"); diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs index e118bd05b..c5c8722cf 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs @@ -66,16 +66,9 @@ namespace ICSharpCode.Decompiler.Metadata readonly Version targetFrameworkVersion; readonly string dotnetBasePath = FindDotNetExeDirectory(); - public DotNetCorePathFinder(Version targetFrameworkVersion) + public DotNetCorePathFinder(TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion) { this.targetFrameworkVersion = targetFrameworkVersion; - } - - public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion, ReferenceLoadInfo loadInfo = null) - { - string assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName); - string basePath = Path.GetDirectoryName(parentAssemblyFileName); - this.targetFrameworkVersion = targetFrameworkVersion; if (targetFramework == TargetFrameworkIdentifier.NETStandard) { // .NET Standard 2.1 is implemented by .NET Core 3.0 or higher @@ -83,6 +76,13 @@ namespace ICSharpCode.Decompiler.Metadata this.targetFrameworkVersion = new Version(3, 0, 0); } } + } + + public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkIdString, TargetFrameworkIdentifier targetFramework, Version targetFrameworkVersion, ReferenceLoadInfo loadInfo = null) + : this(targetFramework, targetFrameworkVersion) + { + string assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName); + string basePath = Path.GetDirectoryName(parentAssemblyFileName); searchPaths.Add(basePath); diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index 2be6f8072..b29fae6e5 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -20,20 +20,26 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using ICSharpCode.Decompiler.TypeSystem.Implementation; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Metadata { public static class DotNetCorePathFinderExtensions { - static readonly string RefPathPattern = + static readonly string PathPattern = @"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?.NETFramework)[/\\]v(?[^/\\]+)[/\\])" + @"|((?Microsoft\.NET)[/\\]assembly[/\\]GAC_(MSIL|32|64)[/\\])" + @"|((?Microsoft\.NET)[/\\]Framework(64)?[/\\](?[^/\\]+)[/\\])" + @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + - @"|(shared[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\])"; + @"|(shared[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\])" + + @"|(packs[/\\](?[^/\\]+)\\(?[^/\\]+)\\ref([/\\].*)?[/\\])"; + + static readonly string RefPathPattern = + @"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?.NETFramework)[/\\]v(?[^/\\]+)[/\\])" + + @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + + @"|(packs[/\\](?[^/\\]+)\\(?[^/\\]+)\\ref([/\\].*)?[/\\])"; public static string DetectTargetFrameworkId(this PEFile assembly) { @@ -99,7 +105,7 @@ namespace ICSharpCode.Decompiler.Metadata * - .NETCore -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll * - .NETStandard -> C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll */ - var pathMatch = Regex.Match(assemblyPath, RefPathPattern, + var pathMatch = Regex.Match(assemblyPath, PathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); if (pathMatch.Success) { var type = pathMatch.Groups["type"].Value; @@ -121,6 +127,25 @@ namespace ICSharpCode.Decompiler.Metadata return string.Empty; } + + public static bool IsReferenceAssembly(this PEFile assembly) + { + return IsReferenceAssembly(assembly.Reader, assembly.FileName); + } + + public static bool IsReferenceAssembly(this PEReader assembly, string assemblyPath) + { + if (assembly == null) + throw new ArgumentNullException(nameof(assembly)); + + var metadata = assembly.GetMetadataReader(); + if (metadata.GetCustomAttributes(Handle.AssemblyDefinition).HasKnownAttribute(metadata, KnownAttribute.ReferenceAssembly)) + return true; + + // Try to detect reference assembly through specific path pattern + var refPathMatch = Regex.Match(assemblyPath, RefPathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); + return refPathMatch.Success; + } } public class ReferenceLoadInfo diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 1f4108302..0b30cbfc4 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -92,16 +92,19 @@ namespace ICSharpCode.Decompiler.Metadata public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) { + this.mainAssemblyFileName = mainAssemblyFileName; + this.throwOnError = throwOnError; this.streamOptions = streamOptions; this.metadataOptions = metadataOptions; this.targetFramework = targetFramework ?? string.Empty; (targetFrameworkIdentifier, targetFrameworkVersion) = ParseTargetFramework(this.targetFramework); - this.mainAssemblyFileName = mainAssemblyFileName; - this.baseDirectory = Path.GetDirectoryName(mainAssemblyFileName); - this.throwOnError = throwOnError; - if (string.IsNullOrWhiteSpace(this.baseDirectory)) - this.baseDirectory = Environment.CurrentDirectory; - AddSearchDirectory(baseDirectory); + + if (mainAssemblyFileName != null) { + string baseDirectory = Path.GetDirectoryName(mainAssemblyFileName); + if (string.IsNullOrWhiteSpace(this.baseDirectory)) + this.baseDirectory = Environment.CurrentDirectory; + AddSearchDirectory(baseDirectory); + } } internal static (TargetFrameworkIdentifier, Version) ParseTargetFramework(string targetFramework) @@ -191,7 +194,10 @@ namespace ICSharpCode.Decompiler.Metadata if (IsZeroOrAllOnes(targetFrameworkVersion)) goto default; if (dotNetCorePathFinder == null) { - dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, targetFrameworkIdentifier, targetFrameworkVersion); + if (mainAssemblyFileName == null) + dotNetCorePathFinder = new DotNetCorePathFinder(targetFrameworkIdentifier, targetFrameworkVersion); + else + dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, targetFrameworkIdentifier, targetFrameworkVersion); foreach (var directory in directories) { dotNetCorePathFinder.AddSearchDirectory(directory); } diff --git a/ILSpy.AddIn/AssemblyFileFinder.cs b/ILSpy.AddIn/AssemblyFileFinder.cs index 66846a6cc..cc6676782 100644 --- a/ILSpy.AddIn/AssemblyFileFinder.cs +++ b/ILSpy.AddIn/AssemblyFileFinder.cs @@ -1,32 +1,29 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; -using Mono.Cecil; namespace ICSharpCode.ILSpy.AddIn { public class AssemblyFileFinder { - public static string FindAssemblyFile(AssemblyDefinition assemblyDefinition, string assemblyFile) + public static string FindAssemblyFile(Mono.Cecil.AssemblyDefinition assemblyDefinition, string assemblyFile) { - var assemblyResolver = new UniversalAssemblyResolver(assemblyFile, false, - DetectTargetFrameworkId(assemblyDefinition, assemblyFile)); + string tfi = DetectTargetFrameworkId(assemblyDefinition, assemblyFile); + UniversalAssemblyResolver assemblyResolver; if (IsReferenceAssembly(assemblyDefinition, assemblyFile)) { - assemblyResolver.RemoveSearchDirectory(Path.GetDirectoryName(assemblyFile)); + assemblyResolver = new UniversalAssemblyResolver(null, throwOnError: false, tfi); + } else { + assemblyResolver = new UniversalAssemblyResolver(assemblyFile, throwOnError: false, tfi); } - return assemblyResolver.FindAssemblyFile( - ICSharpCode.Decompiler.Metadata.AssemblyNameReference.Parse(assemblyDefinition.Name.FullName)); + + return assemblyResolver.FindAssemblyFile(AssemblyNameReference.Parse(assemblyDefinition.Name.FullName)); } static readonly string RefPathPattern = @"NuGetFallbackFolder[/\\][^/\\]+[/\\][^/\\]+[/\\]ref[/\\]"; - public static bool IsReferenceAssembly(AssemblyDefinition assemblyDef, string assemblyFile) + public static bool IsReferenceAssembly(Mono.Cecil.AssemblyDefinition assemblyDef, string assemblyFile) { if (assemblyDef.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.ReferenceAssemblyAttribute")) return true; @@ -40,7 +37,7 @@ namespace ICSharpCode.ILSpy.AddIn @"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?<1>.NETFramework)[/\\]v(?<2>[^/\\]+)[/\\])" + @"|((NuGetFallbackFolder|packs)[/\\](?<1>[^/\\]+)\\(?<2>[^/\\]+)([/\\].*)?[/\\]ref[/\\])"; - public static string DetectTargetFrameworkId(AssemblyDefinition assembly, string assemblyPath = null) + public static string DetectTargetFrameworkId(Mono.Cecil.AssemblyDefinition assembly, string assemblyPath = null) { if (assembly == null) throw new ArgumentNullException(nameof(assembly)); diff --git a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs index cf2d65768..13ef992b0 100644 --- a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs +++ b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs @@ -80,8 +80,7 @@ namespace ICSharpCode.ILSpy.AddIn.Commands using (var assemblyDef = AssemblyDefinition.ReadAssembly(reference.Display)) { string assemblyName = assemblyDef.Name.Name; string resolvedAssemblyFile = AssemblyFileFinder.FindAssemblyFile(assemblyDef, reference.Display); - dict.Add(assemblyName, - new DetectedReference(assemblyName, resolvedAssemblyFile, false)); + dict.Add(assemblyName, new DetectedReference(assemblyName, resolvedAssemblyFile, false)); } } foreach (var projectReference in parentProject.ProjectReferences) { diff --git a/ILSpy.AddIn/ILSpyInstance.cs b/ILSpy.AddIn/ILSpyInstance.cs index b8c04bd14..bc0d21c37 100644 --- a/ILSpy.AddIn/ILSpyInstance.cs +++ b/ILSpy.AddIn/ILSpyInstance.cs @@ -12,11 +12,11 @@ namespace ICSharpCode.ILSpy.AddIn { public ILSpyParameters(IEnumerable assemblyFileNames, params string[] arguments) { - this.AssemblyFileNames = assemblyFileNames; + this.AssemblyFileNames = assemblyFileNames.ToArray(); this.Arguments = arguments; } - public IEnumerable AssemblyFileNames { get; private set; } + public string[] AssemblyFileNames { get; private set; } public string[] Arguments { get; private set; } } diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 71414747b..4d4ee4e3a 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -128,9 +128,7 @@ - - Form - + diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 8f48a19e2..60c37eefe 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -27,6 +27,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using System.Windows.Threading; + using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.PdbProvider; @@ -405,7 +407,7 @@ namespace ICSharpCode.ILSpy lock (loadingAssemblies) { loadingAssemblies.Remove(file); } - }); + }, DispatcherPriority.Normal); return asm; } diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 9e03b263c..10bd97d47 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -408,6 +408,9 @@ namespace ICSharpCode.ILSpy found = true; } else { IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies)); + // Make sure we wait for assemblies being loaded... + // BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal + await Dispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal); if (mr != null && mr.ParentModule.PEFile != null) { found = true; if (AssemblyTreeView.SelectedItem == initialSelection) { @@ -483,6 +486,12 @@ namespace ICSharpCode.ILSpy return false; } + // We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition. + if (module.IsReferenceAssembly()) { + typeHandle = default; + return false; + } + switch (typeRef) { case GetPotentiallyNestedClassTypeReference topLevelType: typeHandle = topLevelType.ResolveInPEFile(module); From 2cd77bb3cc37766b5b1d8376cde62ed795713a53 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 28 Jul 2020 10:02:17 +0200 Subject: [PATCH 30/92] Frontends for 6.1 --- DecompilerNuGetDemos.workbook | 2 +- .../ICSharpCode.Decompiler.Console.csproj | 8 ++++---- .../ICSharpCode.Decompiler.PowerShell.csproj | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DecompilerNuGetDemos.workbook b/DecompilerNuGetDemos.workbook index d5ccd0ea1..a71208905 100644 --- a/DecompilerNuGetDemos.workbook +++ b/DecompilerNuGetDemos.workbook @@ -6,7 +6,7 @@ platforms: - DotNetCore packages: - id: ICSharpCode.Decompiler - version: 6.0.0.5836 + version: 6.1.0.5902 --- Setup: load the references required to work with the decompiler diff --git a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj index f4e9b1467..bf463c7db 100644 --- a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj +++ b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj @@ -8,7 +8,7 @@ true ilspycmd ilspycmd - 6.0.0.5836 + 6.1.0.5902 Command-line decompiler using the ILSpy decompilation engine Copyright 2011-2020 AlphaSierraPapa https://github.com/icsharpcode/ILSpy/ @@ -16,8 +16,8 @@ ILSpyCmdNuGetPackageIcon.png https://github.com/icsharpcode/ILSpy/ - 6.0.0.0 - 6.0.0.0 + 6.1.0.0 + 6.1.0.0 true ILSpy Team @@ -42,7 +42,7 @@ - + diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj index 1db847e93..5028997c6 100644 --- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj +++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj @@ -17,7 +17,7 @@ - + From d2dd6328fd02504c2134a98ac03874d8c5449fdb Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 28 Jul 2020 20:53:15 +0800 Subject: [PATCH 31/92] Complete zh-Hans translation --- ILSpy/Commands/Pdb2XmlCommand.cs | 5 +- ILSpy/Properties/Resources.Designer.cs | 545 ++++++++++++------------ ILSpy/Properties/Resources.resx | 13 +- ILSpy/Properties/Resources.zh-Hans.resx | 285 ++++++++++--- 4 files changed, 504 insertions(+), 344 deletions(-) diff --git a/ILSpy/Commands/Pdb2XmlCommand.cs b/ILSpy/Commands/Pdb2XmlCommand.cs index 91b481f7b..66ad9a7a8 100644 --- a/ILSpy/Commands/Pdb2XmlCommand.cs +++ b/ILSpy/Commands/Pdb2XmlCommand.cs @@ -24,13 +24,14 @@ using System.Linq; using System.Threading.Tasks; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; using Microsoft.DiaSymReader.Tools; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Dump PDB as XML", MenuCategory = "Open", MenuOrder = 2.6)] + [ExportMainMenuCommand(Menu = "_File", Header = nameof(Resources.DEBUGDumpPdb2Xml), MenuCategory = "Open", MenuOrder = 2.6)] sealed class Pdb2XmlCommand : SimpleCommand { public override bool CanExecute(object parameter) @@ -64,7 +65,7 @@ namespace ICSharpCode.ILSpy } } - [ExportContextMenuEntry(Header = "DEBUG -- Dump PDB as XML")] + [ExportContextMenuEntry(Header = nameof(Resources.DEBUGDumpPdb2Xml))] class Pdb2XmlCommandContextMenuEntry : IContextMenuEntry { public void Execute(TextViewContext context) diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 84a05cf4c..cc28600cd 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace ICSharpCode.ILSpy.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _About. + /// 查找类似 _About 的本地化字符串。 /// public static string _About { get { @@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Add To Main List. + /// 查找类似 _Add To Main List 的本地化字符串。 /// public static string _AddMainList { get { @@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Check for Updates. + /// 查找类似 _Check for Updates 的本地化字符串。 /// public static string _CheckUpdates { get { @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Collapse all tree nodes. + /// 查找类似 _Collapse all tree nodes 的本地化字符串。 /// public static string _CollapseTreeNodes { get { @@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _File. + /// 查找类似 _File 的本地化字符串。 /// public static string _File { get { @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Help. + /// 查找类似 _Help 的本地化字符串。 /// public static string _Help { get { @@ -115,7 +115,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Load Dependencies. + /// 查找类似 _Load Dependencies 的本地化字符串。 /// public static string _LoadDependencies { get { @@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _New. + /// 查找类似 _New 的本地化字符串。 /// public static string _New { get { @@ -133,7 +133,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open.... + /// 查找类似 _Open... 的本地化字符串。 /// public static string _Open { get { @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open Command Line Here. + /// 查找类似 _Open Command Line Here 的本地化字符串。 /// public static string _OpenCommandLineHere { get { @@ -151,7 +151,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open Containing Folder. + /// 查找类似 _Open Containing Folder 的本地化字符串。 /// public static string _OpenContainingFolder { get { @@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Options.... + /// 查找类似 _Options... 的本地化字符串。 /// public static string _Options { get { @@ -169,7 +169,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Reload. + /// 查找类似 _Reload 的本地化字符串。 /// public static string _Reload { get { @@ -178,7 +178,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Remove. + /// 查找类似 _Remove 的本地化字符串。 /// public static string _Remove { get { @@ -187,7 +187,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Remove Assemblies with load errors. + /// 查找类似 _Remove Assemblies with load errors 的本地化字符串。 /// public static string _RemoveAssembliesWithLoadErrors { get { @@ -196,7 +196,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Reset. + /// 查找类似 _Reset 的本地化字符串。 /// public static string _Reset { get { @@ -205,7 +205,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Resources. + /// 查找类似 Resources 的本地化字符串。 /// public static string _Resources { get { @@ -214,7 +214,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Save Code.... + /// 查找类似 _Save Code... 的本地化字符串。 /// public static string _SaveCode { get { @@ -223,7 +223,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Search:. + /// 查找类似 _Search: 的本地化字符串。 /// public static string _Search { get { @@ -232,7 +232,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Search for:. + /// 查找类似 _Search for: 的本地化字符串。 /// public static string _SearchFor { get { @@ -241,7 +241,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Show debug steps. + /// 查找类似 _Show debug steps 的本地化字符串。 /// public static string _ShowDebugSteps { get { @@ -250,7 +250,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Toggle Folding. + /// 查找类似 Toggle Folding 的本地化字符串。 /// public static string _ToggleFolding { get { @@ -259,7 +259,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _View. + /// 查找类似 _View 的本地化字符串。 /// public static string _View { get { @@ -268,7 +268,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Window. + /// 查找类似 _Window 的本地化字符串。 /// public static string _Window { get { @@ -277,7 +277,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to About. + /// 查找类似 About 的本地化字符串。 /// public static string About { get { @@ -286,7 +286,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Add preconfigured list.... + /// 查找类似 Add preconfigured list... 的本地化字符串。 /// public static string AddPreconfiguredList { get { @@ -295,7 +295,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Add shell integration. + /// 查找类似 Add shell integration 的本地化字符串。 /// public static string AddShellIntegration { get { @@ -304,9 +304,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. + /// 查找类似 This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. /// - ///Do you want to continue?. + ///Do you want to continue? 的本地化字符串。 /// public static string AddShellIntegrationMessage { get { @@ -315,7 +315,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to |All Files|*.*. + /// 查找类似 |All Files|*.* 的本地化字符串。 /// public static string AllFiles { get { @@ -324,7 +324,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Allow multiple instances. + /// 查找类似 Allow multiple instances 的本地化字符串。 /// public static string AllowMultipleInstances { get { @@ -333,7 +333,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always use braces. + /// 查找类似 Always use braces 的本地化字符串。 /// public static string AlwaysBraces { get { @@ -342,7 +342,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Analyze. + /// 查找类似 Analyze 的本地化字符串。 /// public static string Analyze { get { @@ -351,7 +351,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Assemblies. + /// 查找类似 Assemblies 的本地化字符串。 /// public static string Assemblies { get { @@ -360,7 +360,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Assembly. + /// 查找类似 Assembly 的本地化字符串。 /// public static string Assembly { get { @@ -369,8 +369,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to The directory is not empty. File will be overwritten. - ///Are you sure you want to continue?. + /// 查找类似 The directory is not empty. File will be overwritten. + ///Are you sure you want to continue? 的本地化字符串。 /// public static string AssemblySaveCodeDirectoryNotEmpty { get { @@ -379,7 +379,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Project Directory not empty. + /// 查找类似 Project Directory not empty 的本地化字符串。 /// public static string AssemblySaveCodeDirectoryNotEmptyTitle { get { @@ -388,7 +388,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Automatically check for updates every week. + /// 查找类似 Automatically check for updates every week 的本地化字符串。 /// public static string AutomaticallyCheckUpdatesEveryWeek { get { @@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Back. + /// 查找类似 Back 的本地化字符串。 /// public static string Back { get { @@ -406,7 +406,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Base Types. + /// 查找类似 Base Types 的本地化字符串。 /// public static string BaseTypes { get { @@ -415,7 +415,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to C_lone. + /// 查找类似 C_lone 的本地化字符串。 /// public static string C_lone { get { @@ -424,7 +424,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Cancel. + /// 查找类似 Cancel 的本地化字符串。 /// public static string Cancel { get { @@ -433,7 +433,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again.. + /// 查找类似 Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. 的本地化字符串。 /// public static string CannotAnalyzeMissingRef { get { @@ -442,7 +442,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Check again. + /// 查找类似 Check again 的本地化字符串。 /// public static string CheckAgain { get { @@ -451,7 +451,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Checking.... + /// 查找类似 Checking... 的本地化字符串。 /// public static string Checking { get { @@ -460,7 +460,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Check for updates. + /// 查找类似 Check for updates 的本地化字符串。 /// public static string CheckUpdates { get { @@ -469,7 +469,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Close. + /// 查找类似 Close 的本地化字符串。 /// public static string Close { get { @@ -478,7 +478,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Collapse all tree nodes. + /// 查找类似 Collapse all tree nodes 的本地化字符串。 /// public static string CollapseTreeNodes { get { @@ -487,7 +487,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy. + /// 查找类似 Copy 的本地化字符串。 /// public static string Copy { get { @@ -496,7 +496,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy error message. + /// 查找类似 Copy error message 的本地化字符串。 /// public static string CopyErrorMessage { get { @@ -505,7 +505,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Copy FQ Name. + /// 查找类似 Copy FQ Name 的本地化字符串。 /// public static string CopyName { get { @@ -514,7 +514,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Create. + /// 查找类似 Create 的本地化字符串。 /// public static string Create { get { @@ -523,7 +523,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Culture. + /// 查找类似 Culture 的本地化字符串。 /// public static string CultureLabel { get { @@ -532,7 +532,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Decompile All. + /// 查找类似 DEBUG -- Decompile All 的本地化字符串。 /// public static string DEBUGDecompile { get { @@ -541,7 +541,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Decompile 100x. + /// 查找类似 DEBUG -- Decompile 100x 的本地化字符串。 /// public static string DEBUGDecompile100x { get { @@ -550,7 +550,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to DEBUG -- Disassemble All. + /// 查找类似 DEBUG -- Disassemble All 的本地化字符串。 /// public static string DEBUGDisassemble { get { @@ -559,7 +559,16 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Debug Steps. + /// 查找类似 DEBUG -- Dump PDB as XML 的本地化字符串。 + /// + public static string DEBUGDumpPdb2Xml { + get { + return ResourceManager.GetString("DEBUGDumpPdb2Xml", resourceCulture); + } + } + + /// + /// 查找类似 Debug Steps 的本地化字符串。 /// public static string DebugSteps { get { @@ -568,7 +577,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Debug this step. + /// 查找类似 Debug this step 的本地化字符串。 /// public static string DebugThisStep { get { @@ -577,7 +586,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompiler. + /// 查找类似 Decompiler 的本地化字符串。 /// public static string Decompiler { get { @@ -586,7 +595,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Allow extension 'Add' methods in collection initializer expressions. + /// 查找类似 Allow extension 'Add' methods in collection initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_AllowExtensionAddMethodsInCollectionInitializerExpressions { get { @@ -595,7 +604,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use 'ref' extension methods. + /// 查找类似 Use 'ref' extension methods 的本地化字符串。 /// public static string DecompilerSettings_AllowExtensionMethodSyntaxOnRef { get { @@ -604,7 +613,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always cast targets of explicit interface implementation calls. + /// 查找类似 Always cast targets of explicit interface implementation calls 的本地化字符串。 /// public static string DecompilerSettings_AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { get { @@ -613,7 +622,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always show enum member values. + /// 查找类似 Always show enum member values 的本地化字符串。 /// public static string DecompilerSettings_AlwaysShowEnumMemberValues { get { @@ -622,7 +631,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Always use braces. + /// 查找类似 Always use braces 的本地化字符串。 /// public static string DecompilerSettings_AlwaysUseBraces { get { @@ -631,7 +640,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Apply Windows Runtime projections on loaded assemblies. + /// 查找类似 Apply Windows Runtime projections on loaded assemblies 的本地化字符串。 /// public static string DecompilerSettings_ApplyWindowsRuntimeProjectionsOnLoadedAssemblies { get { @@ -640,7 +649,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Array initializer expressions. + /// 查找类似 Array initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_ArrayInitializerExpressions { get { @@ -649,7 +658,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile async IAsyncEnumerator methods. + /// 查找类似 Decompile async IAsyncEnumerator methods 的本地化字符串。 /// public static string DecompilerSettings_AsyncEnumerator { get { @@ -658,7 +667,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile ?. and ?[] operators. + /// 查找类似 Decompile ?. and ?[] operators 的本地化字符串。 /// public static string DecompilerSettings_DecompileAndOperators { get { @@ -667,7 +676,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile anonymous methods/lambdas. + /// 查找类似 Decompile anonymous methods/lambdas 的本地化字符串。 /// public static string DecompilerSettings_DecompileAnonymousMethodsLambdas { get { @@ -676,7 +685,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile anonymous types. + /// 查找类似 Decompile anonymous types 的本地化字符串。 /// public static string DecompilerSettings_DecompileAnonymousTypes { get { @@ -685,7 +694,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile async methods. + /// 查找类似 Decompile async methods 的本地化字符串。 /// public static string DecompilerSettings_DecompileAsyncMethods { get { @@ -694,7 +703,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile automatic events. + /// 查找类似 Decompile automatic events 的本地化字符串。 /// public static string DecompilerSettings_DecompileAutomaticEvents { get { @@ -703,7 +712,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile automatic properties. + /// 查找类似 Decompile automatic properties 的本地化字符串。 /// public static string DecompilerSettings_DecompileAutomaticProperties { get { @@ -712,7 +721,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile await in catch/finally blocks. + /// 查找类似 Decompile await in catch/finally blocks 的本地化字符串。 /// public static string DecompilerSettings_DecompileAwaitInCatchFinallyBlocks { get { @@ -721,7 +730,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile C# 1.0 'public unsafe fixed int arr[10];' members. + /// 查找类似 Decompile C# 1.0 'public unsafe fixed int arr[10];' members 的本地化字符串。 /// public static string DecompilerSettings_DecompileC10PublicUnsafeFixedIntArr10Members { get { @@ -730,7 +739,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile [DecimalConstant(...)] as simple literal values. + /// 查找类似 Decompile [DecimalConstant(...)] as simple literal values 的本地化字符串。 /// public static string DecompilerSettings_DecompileDecimalConstantAsSimpleLiteralValues { get { @@ -739,7 +748,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile enumerators (yield return). + /// 查找类似 Decompile enumerators (yield return) 的本地化字符串。 /// public static string DecompilerSettings_DecompileEnumeratorsYieldReturn { get { @@ -748,7 +757,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile expression trees. + /// 查找类似 Decompile expression trees 的本地化字符串。 /// public static string DecompilerSettings_DecompileExpressionTrees { get { @@ -757,7 +766,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile use of the 'dynamic' type. + /// 查找类似 Decompile use of the 'dynamic' type 的本地化字符串。 /// public static string DecompilerSettings_DecompileUseOfTheDynamicType { get { @@ -766,7 +775,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect awaited using and foreach statements. + /// 查找类似 Detect awaited using and foreach statements 的本地化字符串。 /// public static string DecompilerSettings_DetectAsyncUsingAndForeachStatements { get { @@ -775,7 +784,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect foreach statements. + /// 查找类似 Detect foreach statements 的本地化字符串。 /// public static string DecompilerSettings_DetectForeachStatements { get { @@ -784,7 +793,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect lock statements. + /// 查找类似 Detect lock statements 的本地化字符串。 /// public static string DecompilerSettings_DetectLockStatements { get { @@ -793,7 +802,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect switch on string. + /// 查找类似 Detect switch on string 的本地化字符串。 /// public static string DecompilerSettings_DetectSwitchOnString { get { @@ -802,7 +811,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect tuple comparisons. + /// 查找类似 Detect tuple comparisons 的本地化字符串。 /// public static string DecompilerSettings_DetectTupleComparisons { get { @@ -811,7 +820,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Detect using statements. + /// 查找类似 Detect using statements 的本地化字符串。 /// public static string DecompilerSettings_DetectUsingStatements { get { @@ -820,7 +829,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Dictionary initializer expressions. + /// 查找类似 Dictionary initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_DictionaryInitializerExpressions { get { @@ -829,7 +838,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Transform to do-while, if possible.. + /// 查找类似 Transform to do-while, if possible 的本地化字符串。 /// public static string DecompilerSettings_DoWhileStatement { get { @@ -838,7 +847,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Transform to for, if possible.. + /// 查找类似 Transform to for, if possible 的本地化字符串。 /// public static string DecompilerSettings_ForStatement { get { @@ -847,7 +856,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to F#-specific options. + /// 查找类似 F#-specific options 的本地化字符串。 /// public static string DecompilerSettings_FSpecificOptions { get { @@ -856,7 +865,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Include XML documentation comments in the decompiled code. + /// 查找类似 Include XML documentation comments in the decompiled code 的本地化字符串。 /// public static string DecompilerSettings_IncludeXMLDocumentationCommentsInTheDecompiledCode { get { @@ -865,7 +874,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Insert using declarations. + /// 查找类似 Insert using declarations 的本地化字符串。 /// public static string DecompilerSettings_InsertUsingDeclarations { get { @@ -874,7 +883,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Introduce local functions. + /// 查找类似 Introduce local functions 的本地化字符串。 /// public static string DecompilerSettings_IntroduceLocalFunctions { get { @@ -883,7 +892,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Introduce static local functions. + /// 查找类似 Introduce static local functions 的本地化字符串。 /// public static string DecompilerSettings_IntroduceStaticLocalFunctions { get { @@ -892,7 +901,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs. + /// 查找类似 IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs 的本地化字符串。 /// public static string DecompilerSettings_IsByRefLikeAttributeShouldBeReplacedWithRefModifiersOnStructs { get { @@ -901,7 +910,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters. + /// 查找类似 IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters 的本地化字符串。 /// public static string DecompilerSettings_IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters { get { @@ -911,7 +920,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints. + /// 查找类似 IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints 的本地化字符串。 /// public static string DecompilerSettings_IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints { get { @@ -921,7 +930,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use nint/nuint types. + /// 查找类似 Use nint/nuint types 的本地化字符串。 /// public static string DecompilerSettings_NativeIntegers { get { @@ -930,7 +939,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Nullable reference types. + /// 查找类似 Nullable reference types 的本地化字符串。 /// public static string DecompilerSettings_NullableReferenceTypes { get { @@ -939,7 +948,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Object/collection initializer expressions. + /// 查找类似 Object/collection initializer expressions 的本地化字符串。 /// public static string DecompilerSettings_ObjectCollectionInitializerExpressions { get { @@ -948,7 +957,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other. + /// 查找类似 Other 的本地化字符串。 /// public static string DecompilerSettings_Other { get { @@ -957,7 +966,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Ranges. + /// 查找类似 Ranges 的本地化字符串。 /// public static string DecompilerSettings_Ranges { get { @@ -966,7 +975,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Read-only methods. + /// 查找类似 Read-only methods 的本地化字符串。 /// public static string DecompilerSettings_ReadOnlyMethods { get { @@ -975,7 +984,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead and side effect free code (use with caution!). + /// 查找类似 Remove dead and side effect free code (use with caution!) 的本地化字符串。 /// public static string DecompilerSettings_RemoveDeadAndSideEffectFreeCodeUseWithCaution { get { @@ -984,7 +993,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead stores (use with caution!). + /// 查找类似 Remove dead stores (use with caution!) 的本地化字符串。 /// public static string DecompilerSettings_RemoveDeadStores { get { @@ -993,7 +1002,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove optional arguments, if possible. + /// 查找类似 Remove optional arguments, if possible 的本地化字符串。 /// public static string DecompilerSettings_RemoveOptionalArgumentsIfPossible { get { @@ -1002,7 +1011,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible.. + /// 查找类似 Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible 的本地化字符串。 /// public static string DecompilerSettings_SeparateLocalVariableDeclarations { get { @@ -1011,7 +1020,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show info from debug symbols, if available. + /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 /// public static string DecompilerSettings_ShowInfoFromDebugSymbolsIfAvailable { get { @@ -1020,7 +1029,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use discards. + /// 查找类似 Use discards 的本地化字符串。 /// public static string DecompilerSettings_UseDiscards { get { @@ -1029,7 +1038,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use expression-bodied member syntax for get-only properties. + /// 查找类似 Use expression-bodied member syntax for get-only properties 的本地化字符串。 /// public static string DecompilerSettings_UseExpressionBodiedMemberSyntaxForGetOnlyProperties { get { @@ -1038,7 +1047,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use extension method syntax. + /// 查找类似 Use extension method syntax 的本地化字符串。 /// public static string DecompilerSettings_UseExtensionMethodSyntax { get { @@ -1047,7 +1056,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use implicit conversions between tuple types. + /// 查找类似 Use implicit conversions between tuple types 的本地化字符串。 /// public static string DecompilerSettings_UseImplicitConversionsBetweenTupleTypes { get { @@ -1056,7 +1065,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use implicit method group conversions. + /// 查找类似 Use implicit method group conversions 的本地化字符串。 /// public static string DecompilerSettings_UseImplicitMethodGroupConversions { get { @@ -1065,7 +1074,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use lambda syntax, if possible. + /// 查找类似 Use lambda syntax, if possible 的本地化字符串。 /// public static string DecompilerSettings_UseLambdaSyntaxIfPossible { get { @@ -1074,7 +1083,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use lifted operators for nullables. + /// 查找类似 Use lifted operators for nullables 的本地化字符串。 /// public static string DecompilerSettings_UseLiftedOperatorsForNullables { get { @@ -1083,7 +1092,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use LINQ expression syntax. + /// 查找类似 Use LINQ expression syntax 的本地化字符串。 /// public static string DecompilerSettings_UseLINQExpressionSyntax { get { @@ -1092,7 +1101,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use named arguments. + /// 查找类似 Use named arguments 的本地化字符串。 /// public static string DecompilerSettings_UseNamedArguments { get { @@ -1101,7 +1110,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use non-trailing named arguments. + /// 查找类似 Use non-trailing named arguments 的本地化字符串。 /// public static string DecompilerSettings_UseNonTrailingNamedArguments { get { @@ -1110,7 +1119,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use out variable declarations. + /// 查找类似 Use out variable declarations 的本地化字符串。 /// public static string DecompilerSettings_UseOutVariableDeclarations { get { @@ -1119,7 +1128,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use pattern-based fixed statement. + /// 查找类似 Use pattern-based fixed statement 的本地化字符串。 /// public static string DecompilerSettings_UsePatternBasedFixedStatement { get { @@ -1128,7 +1137,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use new SDK style format for generated project files (*.csproj). + /// 查找类似 Use new SDK style format for generated project files (*.csproj) 的本地化字符串。 /// public static string DecompilerSettings_UseSdkStyleProjectFormat { get { @@ -1137,7 +1146,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use stackalloc initializer syntax. + /// 查找类似 Use stackalloc initializer syntax 的本地化字符串。 /// public static string DecompilerSettings_UseStackallocInitializerSyntax { get { @@ -1146,7 +1155,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use string interpolation. + /// 查找类似 Use string interpolation 的本地化字符串。 /// public static string DecompilerSettings_UseStringInterpolation { get { @@ -1155,7 +1164,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use throw expressions. + /// 查找类似 Use throw expressions 的本地化字符串。 /// public static string DecompilerSettings_UseThrowExpressions { get { @@ -1164,7 +1173,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use tuple type syntax. + /// 查找类似 Use tuple type syntax 的本地化字符串。 /// public static string DecompilerSettings_UseTupleTypeSyntax { get { @@ -1173,7 +1182,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use variable names from debug symbols, if available. + /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 /// public static string DecompilerSettings_UseVariableNamesFromDebugSymbolsIfAvailable { get { @@ -1182,7 +1191,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to VB-specific options. + /// 查找类似 VB-specific options 的本地化字符串。 /// public static string DecompilerSettings_VBSpecificOptions { get { @@ -1191,7 +1200,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls.. + /// 查找类似 The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls. 的本地化字符串。 /// public static string DecompilerSettingsPanelLongText { get { @@ -1200,7 +1209,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompile to new tab. + /// 查找类似 Decompile to new tab 的本地化字符串。 /// public static string DecompileToNewPanel { get { @@ -1209,7 +1218,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Decompiling.... + /// 查找类似 Decompiling... 的本地化字符串。 /// public static string Decompiling { get { @@ -1218,7 +1227,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Dependencies. + /// 查找类似 Dependencies 的本地化字符串。 /// public static string Dependencies { get { @@ -1227,7 +1236,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Derived Types. + /// 查找类似 Derived Types 的本地化字符串。 /// public static string DerivedTypes { get { @@ -1236,7 +1245,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Display. + /// 查找类似 Display 的本地化字符串。 /// public static string Display { get { @@ -1245,7 +1254,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Display Code. + /// 查找类似 Display Code 的本地化字符串。 /// public static string DisplayCode { get { @@ -1254,7 +1263,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Font:. + /// 查找类似 Font: 的本地化字符串。 /// public static string DisplaySettingsPanel_Font { get { @@ -1263,7 +1272,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Download. + /// 查找类似 Download 的本地化字符串。 /// public static string Download { get { @@ -1272,7 +1281,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to E_xit. + /// 查找类似 E_xit 的本地化字符串。 /// public static string E_xit { get { @@ -1281,7 +1290,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Editor. + /// 查找类似 Editor 的本地化字符串。 /// public static string Editor { get { @@ -1290,7 +1299,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enable folding on all blocks in braces. + /// 查找类似 Enable folding on all blocks in braces 的本地化字符串。 /// public static string EnableFoldingBlocksBraces { get { @@ -1299,7 +1308,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enable word wrap. + /// 查找类似 Enable word wrap 的本地化字符串。 /// public static string EnableWordWrap { get { @@ -1308,7 +1317,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Enter a list name:. + /// 查找类似 Enter a list name: 的本地化字符串。 /// public static string EnterListName { get { @@ -1317,7 +1326,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Exit. + /// 查找类似 Exit 的本地化字符串。 /// public static string Exit { get { @@ -1326,7 +1335,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Expand member definitions after decompilation. + /// 查找类似 Expand member definitions after decompilation 的本地化字符串。 /// public static string ExpandMemberDefinitionsAfterDecompilation { get { @@ -1335,7 +1344,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Expand using declarations after decompilation. + /// 查找类似 Expand using declarations after decompilation 的本地化字符串。 /// public static string ExpandUsingDeclarationsAfterDecompilation { get { @@ -1344,7 +1353,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Folding. + /// 查找类似 Folding 的本地化字符串。 /// public static string Folding { get { @@ -1353,7 +1362,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Font. + /// 查找类似 Font 的本地化字符串。 /// public static string Font { get { @@ -1362,7 +1371,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Forward. + /// 查找类似 Forward 的本地化字符串。 /// public static string Forward { get { @@ -1371,7 +1380,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Generate portable PDB. + /// 查找类似 Generate portable PDB 的本地化字符串。 /// public static string GeneratePortable { get { @@ -1380,7 +1389,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Hide empty metadata tables from tree view. + /// 查找类似 Hide empty metadata tables from tree view 的本地化字符串。 /// public static string HideEmptyMetadataTables { get { @@ -1389,7 +1398,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Highlight matching braces. + /// 查找类似 Highlight matching braces 的本地化字符串。 /// public static string HighlightMatchingBraces { get { @@ -1398,7 +1407,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ILSpy version . + /// 查找类似 ILSpy version 的本地化字符串。 /// public static string ILSpyVersion { get { @@ -1407,7 +1416,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to A new ILSpy version is available.. + /// 查找类似 A new ILSpy version is available. 的本地化字符串。 /// public static string ILSpyVersionAvailable { get { @@ -1416,7 +1425,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Indentation. + /// 查找类似 Indentation 的本地化字符串。 /// public static string Indentation { get { @@ -1425,7 +1434,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Indent size:. + /// 查找类似 Indent size: 的本地化字符串。 /// public static string IndentSize { get { @@ -1434,7 +1443,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Insert using declarations. + /// 查找类似 Insert using declarations 的本地化字符串。 /// public static string InsertUsingDeclarations { get { @@ -1443,7 +1452,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Are you sure that you want to delete the selected assembly list?. + /// 查找类似 Are you sure that you want to delete the selected assembly list? 的本地化字符串。 /// public static string ListDeleteConfirmation { get { @@ -1452,7 +1461,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to A list with the same name was found.. + /// 查找类似 A list with the same name was found. 的本地化字符串。 /// public static string ListExistsAlready { get { @@ -1461,7 +1470,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Are you sure that you want to remove all assembly lists and recreate the default assembly lists?. + /// 查找类似 Are you sure that you want to remove all assembly lists and recreate the default assembly lists? 的本地化字符串。 /// public static string ListsResetConfirmation { get { @@ -1470,7 +1479,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Load assemblies that were loaded in the last instance.. + /// 查找类似 Load assemblies that were loaded in the last instance. 的本地化字符串。 /// public static string LoadAssembliesThatWereLoadedInTheLastInstance { get { @@ -1479,7 +1488,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Loading.... + /// 查找类似 Loading... 的本地化字符串。 /// public static string Loading { get { @@ -1488,7 +1497,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Location. + /// 查找类似 Location 的本地化字符串。 /// public static string Location { get { @@ -1497,7 +1506,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Manage assembly _lists.... + /// 查找类似 Manage assembly _lists... 的本地化字符串。 /// public static string ManageAssembly_Lists { get { @@ -1506,7 +1515,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Manage Assembly Lists. + /// 查找类似 Manage Assembly Lists 的本地化字符串。 /// public static string ManageAssemblyLists { get { @@ -1515,7 +1524,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Misc. + /// 查找类似 Misc 的本地化字符串。 /// public static string Misc { get { @@ -1524,7 +1533,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Name. + /// 查找类似 Name 的本地化字符串。 /// public static string Name { get { @@ -1533,7 +1542,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Navigation. + /// 查找类似 Navigation 的本地化字符串。 /// public static string Navigation { get { @@ -1542,8 +1551,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Navigation failed because the target is hidden or a compiler-generated class.\n - ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again.. + /// 查找类似 Navigation failed because the target is hidden or a compiler-generated class.\n + ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again. 的本地化字符串。 /// public static string NavigationFailed { get { @@ -1552,7 +1561,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to New list. + /// 查找类似 New list 的本地化字符串。 /// public static string NewList { get { @@ -1561,7 +1570,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to New Tab. + /// 查找类似 New Tab 的本地化字符串。 /// public static string NewTab { get { @@ -1570,7 +1579,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Nuget Package Browser. + /// 查找类似 Nuget Package Browser 的本地化字符串。 /// public static string NugetPackageBrowser { get { @@ -1579,7 +1588,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to OK. + /// 查找类似 OK 的本地化字符串。 /// public static string OK { get { @@ -1588,7 +1597,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open. + /// 查找类似 Open 的本地化字符串。 /// public static string Open { get { @@ -1597,7 +1606,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open Explorer. + /// 查找类似 Open Explorer 的本地化字符串。 /// public static string OpenExplorer { get { @@ -1606,7 +1615,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open From GAC. + /// 查找类似 Open From GAC 的本地化字符串。 /// public static string OpenFrom { get { @@ -1615,7 +1624,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Open from _GAC.... + /// 查找类似 Open from _GAC... 的本地化字符串。 /// public static string OpenFrom_GAC { get { @@ -1624,7 +1633,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Delete. + /// 查找类似 _Delete 的本地化字符串。 /// public static string OpenListDialog__Delete { get { @@ -1633,7 +1642,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to _Open. + /// 查找类似 _Open 的本地化字符串。 /// public static string OpenListDialog__Open { get { @@ -1642,7 +1651,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Options. + /// 查找类似 Options 的本地化字符串。 /// public static string Options { get { @@ -1651,7 +1660,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other. + /// 查找类似 Other 的本地化字符串。 /// public static string Other { get { @@ -1660,7 +1669,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other options. + /// 查找类似 Other options 的本地化字符串。 /// public static string OtherOptions { get { @@ -1669,7 +1678,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Other Resources. + /// 查找类似 Other Resources 的本地化字符串。 /// public static string OtherResources { get { @@ -1678,7 +1687,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.. + /// 查找类似 for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. 的本地化字符串。 /// public static string PropertyManuallyMissingReferencesListLoadedAssemblies { get { @@ -1687,7 +1696,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Public Key Token. + /// 查找类似 Public Key Token 的本地化字符串。 /// public static string PublicToken { get { @@ -1696,7 +1705,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to R_ename. + /// 查找类似 R_ename 的本地化字符串。 /// public static string R_ename { get { @@ -1705,7 +1714,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reference Name. + /// 查找类似 Reference Name 的本地化字符串。 /// public static string ReferenceName { get { @@ -1714,7 +1723,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to References. + /// 查找类似 References 的本地化字符串。 /// public static string References { get { @@ -1723,7 +1732,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reload all assemblies. + /// 查找类似 Reload all assemblies 的本地化字符串。 /// public static string RefreshCommand_ReloadAssemblies { get { @@ -1732,7 +1741,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reload all assemblies. + /// 查找类似 Reload all assemblies 的本地化字符串。 /// public static string ReloadAssemblies { get { @@ -1741,7 +1750,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove. + /// 查找类似 Remove 的本地化字符串。 /// public static string Remove { get { @@ -1750,7 +1759,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove dead and side effect free code. + /// 查找类似 Remove dead and side effect free code 的本地化字符串。 /// public static string RemoveDeadSideEffectFreeCode { get { @@ -1759,7 +1768,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Remove shell integration. + /// 查找类似 Remove shell integration 的本地化字符串。 /// public static string RemoveShellIntegration { get { @@ -1768,9 +1777,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". + /// 查找类似 This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". /// - ///Do you want to continue?. + ///Do you want to continue? 的本地化字符串。 /// public static string RemoveShellIntegrationMessage { get { @@ -1779,7 +1788,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Rename list. + /// 查找类似 Rename list 的本地化字符串。 /// public static string RenameList { get { @@ -1788,7 +1797,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reset to defaults. + /// 查找类似 Reset to defaults 的本地化字符串。 /// public static string ResetToDefaults { get { @@ -1797,7 +1806,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Do you really want to load the default settings for the active page?. + /// 查找类似 Do you really want to load the default settings for the active page? 的本地化字符串。 /// public static string ResetToDefaultsConfirmationMessage { get { @@ -1806,7 +1815,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Resources file (*.resources)|*.resources|Resource XML file|*.resx. + /// 查找类似 Resources file (*.resources)|*.resources|Resource XML file|*.resx 的本地化字符串。 /// public static string ResourcesFileFilter { get { @@ -1815,7 +1824,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Save. + /// 查找类似 Save 的本地化字符串。 /// public static string Save { get { @@ -1824,7 +1833,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Save Code. + /// 查找类似 Save Code 的本地化字符串。 /// public static string SaveCode { get { @@ -1833,7 +1842,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search.... + /// 查找类似 Search... 的本地化字符串。 /// public static string Search { get { @@ -1842,7 +1851,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search aborted, more than 1000 results found.. + /// 查找类似 Search aborted, more than 1000 results found. 的本地化字符串。 /// public static string SearchAbortedMoreThan1000ResultsFound { get { @@ -1851,7 +1860,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search (Ctrl+Shift+F or Ctrl+E). + /// 查找类似 Search (Ctrl+Shift+F or Ctrl+E) 的本地化字符串。 /// public static string SearchCtrlShiftFOrCtrlE { get { @@ -1860,7 +1869,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Searching.... + /// 查找类似 Searching... 的本地化字符串。 /// public static string Searching { get { @@ -1869,7 +1878,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search Microsoft Docs.... + /// 查找类似 Search Microsoft Docs... 的本地化字符串。 /// public static string SearchMSDN { get { @@ -1878,7 +1887,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search. + /// 查找类似 Search 的本地化字符串。 /// public static string SearchPane_Search { get { @@ -1887,7 +1896,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select All. + /// 查找类似 Select All 的本地化字符串。 /// public static string Select { get { @@ -1896,7 +1905,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select assemblies to open:. + /// 查找类似 Select assemblies to open: 的本地化字符串。 /// public static string SelectAssembliesOpen { get { @@ -1905,7 +1914,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select a list of assemblies. + /// 查找类似 Select a list of assemblies 的本地化字符串。 /// public static string SelectAssemblyListDropdownTooltip { get { @@ -1914,7 +1923,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select language to decompile to. + /// 查找类似 Select language to decompile to 的本地化字符串。 /// public static string SelectLanguageDropdownTooltip { get { @@ -1923,7 +1932,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select a list:. + /// 查找类似 Select a list: 的本地化字符串。 /// public static string SelectList { get { @@ -1932,7 +1941,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Select version of language to output. + /// 查找类似 Select version of language to output 的本地化字符串。 /// public static string SelectVersionDropdownTooltip { get { @@ -1941,7 +1950,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Shell. + /// 查找类似 Shell 的本地化字符串。 /// public static string Shell { get { @@ -1950,7 +1959,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show _all types and members. + /// 查找类似 Show _all types and members 的本地化字符串。 /// public static string Show_allTypesAndMembers { get { @@ -1959,7 +1968,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show public, private and internal. + /// 查找类似 Show public, private and internal 的本地化字符串。 /// public static string Show_internalTypesMembers { get { @@ -1968,7 +1977,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show only _public types and members. + /// 查找类似 Show only _public types and members 的本地化字符串。 /// public static string Show_publiconlyTypesMembers { get { @@ -1977,7 +1986,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show all types and members. + /// 查找类似 Show all types and members 的本地化字符串。 /// public static string ShowAllTypesAndMembers { get { @@ -1986,7 +1995,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show assembly load log. + /// 查找类似 Show assembly load log 的本地化字符串。 /// public static string ShowAssemblyLoad { get { @@ -1995,7 +2004,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ShowChildIndexInBlock. + /// 查找类似 ShowChildIndexInBlock 的本地化字符串。 /// public static string ShowChildIndexInBlock { get { @@ -2004,7 +2013,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show XML documentation in decompiled code. + /// 查找类似 Show XML documentation in decompiled code 的本地化字符串。 /// public static string ShowDocumentationDecompiledCode { get { @@ -2013,7 +2022,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to ShowILRanges. + /// 查找类似 ShowILRanges 的本地化字符串。 /// public static string ShowILRanges { get { @@ -2022,7 +2031,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show info from debug symbols, if available. + /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 /// public static string ShowInfoFromDebugSymbolsAvailable { get { @@ -2031,7 +2040,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show public, private and internal. + /// 查找类似 Show public, private and internal 的本地化字符串。 /// public static string ShowInternalTypesMembers { get { @@ -2040,7 +2049,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show line numbers. + /// 查找类似 Show line numbers 的本地化字符串。 /// public static string ShowLineNumbers { get { @@ -2049,7 +2058,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show metadata tokens. + /// 查找类似 Show metadata tokens 的本地化字符串。 /// public static string ShowMetadataTokens { get { @@ -2058,7 +2067,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show metadata tokens in base 10. + /// 查找类似 Show metadata tokens in base 10 的本地化字符串。 /// public static string ShowMetadataTokensInBase10 { get { @@ -2067,7 +2076,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show only public types and members. + /// 查找类似 Show only public types and members 的本地化字符串。 /// public static string ShowPublicOnlyTypesMembers { get { @@ -2076,7 +2085,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show state after this step. + /// 查找类似 Show state after this step 的本地化字符串。 /// public static string ShowStateAfterThisStep { get { @@ -2085,7 +2094,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Show state before this step. + /// 查找类似 Show state before this step 的本地化字符串。 /// public static string ShowStateBeforeThisStep { get { @@ -2094,7 +2103,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Size:. + /// 查找类似 Size: 的本地化字符串。 /// public static string Size { get { @@ -2103,7 +2112,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort assembly _list by name. + /// 查找类似 Sort assembly _list by name 的本地化字符串。 /// public static string SortAssembly_listName { get { @@ -2112,7 +2121,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort assembly list by name. + /// 查找类似 Sort assembly list by name 的本地化字符串。 /// public static string SortAssemblyListName { get { @@ -2121,7 +2130,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Sort results by fitness. + /// 查找类似 Sort results by fitness 的本地化字符串。 /// public static string SortResultsFitness { get { @@ -2130,7 +2139,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Stand by.... + /// 查找类似 Stand by... 的本地化字符串。 /// public static string StandBy { get { @@ -2139,7 +2148,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Status. + /// 查找类似 Status 的本地化字符串。 /// public static string Status { get { @@ -2148,7 +2157,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to String Table. + /// 查找类似 String Table 的本地化字符串。 /// public static string StringTable { get { @@ -2157,7 +2166,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Tab size:. + /// 查找类似 Tab size: 的本地化字符串。 /// public static string TabSize { get { @@ -2166,7 +2175,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Toggle All Folding. + /// 查找类似 Toggle All Folding 的本地化字符串。 /// public static string ToggleFolding { get { @@ -2175,7 +2184,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Type. + /// 查找类似 Type 的本地化字符串。 /// public static string Type { get { @@ -2184,7 +2193,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to No update for ILSpy found.. + /// 查找类似 No update for ILSpy found. 的本地化字符串。 /// public static string UpdateILSpyFound { get { @@ -2193,7 +2202,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to UseFieldSugar. + /// 查找类似 UseFieldSugar 的本地化字符串。 /// public static string UseFieldSugar { get { @@ -2202,7 +2211,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to UseLogicOperationSugar. + /// 查找类似 UseLogicOperationSugar 的本地化字符串。 /// public static string UseLogicOperationSugar { get { @@ -2211,7 +2220,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use tabs instead of spaces. + /// 查找类似 Use tabs instead of spaces 的本地化字符串。 /// public static string UseTabsInsteadOfSpaces { get { @@ -2220,7 +2229,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to You are using the latest release.. + /// 查找类似 You are using the latest release. 的本地化字符串。 /// public static string UsingLatestRelease { get { @@ -2229,7 +2238,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to You are using a nightly build newer than the latest release.. + /// 查找类似 You are using a nightly build newer than the latest release. 的本地化字符串。 /// public static string UsingNightlyBuildNewerThanLatestRelease { get { @@ -2238,7 +2247,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Value. + /// 查找类似 Value 的本地化字符串。 /// public static string Value { get { @@ -2247,7 +2256,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Value (as string). + /// 查找类似 Value (as string) 的本地化字符串。 /// public static string ValueString { get { @@ -2256,7 +2265,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Use variable names from debug symbols, if available. + /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 /// public static string VariableNamesFromDebugSymbolsAvailable { get { @@ -2265,7 +2274,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Version. + /// 查找类似 Version 的本地化字符串。 /// public static string Version { get { @@ -2274,7 +2283,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Version {0} is available.. + /// 查找类似 Version {0} is available. 的本地化字符串。 /// public static string VersionAvailable { get { @@ -2283,7 +2292,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to View. + /// 查找类似 View 的本地化字符串。 /// public static string View { get { @@ -2292,7 +2301,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code.. + /// 查找类似 Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. 的本地化字符串。 /// public static string WarningAsmMarkedRef { get { @@ -2301,7 +2310,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,. + /// 查找类似 Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, 的本地化字符串。 /// public static string WarningSomeAssemblyReference { get { @@ -2310,7 +2319,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/.... + /// 查找类似 Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/... 的本地化字符串。 /// public static string WatermarkText { get { @@ -2319,7 +2328,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Close all documents. + /// 查找类似 _Close all documents 的本地化字符串。 /// public static string Window_CloseAllDocuments { get { @@ -2328,7 +2337,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// Looks up a localized string similar to Reset layout. + /// 查找类似 _Reset layout 的本地化字符串。 /// public static string Window_ResetLayout { get { diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 62a8ffa83..bc61fcb17 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -782,10 +782,10 @@ Are you sure you want to continue? Assemblies - Close all documents + _Close all documents - Reset layout + _Reset layout _Window @@ -794,13 +794,13 @@ Are you sure you want to continue? Use pattern-based fixed statement - Transform to do-while, if possible. + Transform to do-while, if possible - Transform to for, if possible. + Transform to for, if possible - Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible. + Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible Reset to defaults @@ -879,4 +879,7 @@ Do you want to continue? Base Types + + DEBUG -- Dump PDB as XML + \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 980fec4c7..a31cb218d 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -139,7 +139,7 @@ 打开 - DEBUG -- 反编译全部 + 调试 -- 反汇编全部 退出(_X) @@ -154,22 +154,19 @@ 打开(_O)... - 从_GAC中打开...... - - - 打开列表(_L) + 从 GAC 中打开(_G)... 重新加载全部程序集 - DEBUG - 全部反编译 + 调试 -- 反编译全部 - DEBUG - 反编译100x + 调试 -- 反编译100x - 生成可携带PDB + 生成可携带 PDB 重新加载程序集 @@ -184,7 +181,7 @@ 移除 - 保存代码(_S) + 保存代码(_S)... 显示调试步骤(_S) @@ -211,7 +208,7 @@ 名称 - 值(为字符串) + 值(以字符串形式) 类型 @@ -244,7 +241,7 @@ 引用 - ILSpy版本 + ILSpy 版本 正在反编译... @@ -307,16 +304,16 @@ 在这里打开命令行(_O) - 复制FQ名称 + 复制完全限定名称 复制错误信息 - 使用调试符号中的变量名称 (如果可用) + 使用调试符号中的变量名称(如果可用) - 显示调试符号的信息 (如果可用) + 显示调试符号的信息(如果可用) 在反编译代码中显示 XML 文档 @@ -325,7 +322,7 @@ 在大括号中的所有块上启用折叠 - 删除死亡和副作用免费代码 + 删除死代码和无副作用的代码 插入使用声明 @@ -352,7 +349,7 @@ 派生类型 - 资源文件 (*.resources)|*.resources|XML资源文件|*.resx + 资源文件|*.resources|XML资源文件|*.resx 排序结果自适应 @@ -366,47 +363,35 @@ 打开(_O) - - 创建(_C) - 引用名称 版本 - - 区域 - 公钥标记 - - 打开列表 - - 选择一个列表: + 选择一个列表: 搜索(_S): - 从 GAC 打开 + 从 GAC 中打开 Nuget 包浏览器 - - 新建列表 - - 选择要打开的程序集: + 选择要打开的程序集: 创建 - 输入列表名称: + 输入列表名称: 分析 @@ -469,7 +454,7 @@ 每周自动检查更新 - 搜索 t:TypeName, m:Member 或c:Constant; 使用完全匹配 (=term), '不应包含' (-term) 或 '必须包含' (+term); 使用 /reg(ular)?Ex(pressions)?/或两者 - t:/Type(Name)?/... + 搜索 t:TypeName、m:Member 或 c:Constant;使用完全匹配 (=term), '不应包含' (-term) 或 '必须包含' (+term); 使用 /reg(ular)?Ex(pressions)?/或两者 - t:/Type(Name)?/... 选项 @@ -490,7 +475,7 @@ 字体: - 大小: + 大小: 调试步骤 @@ -517,13 +502,13 @@ 调试此步骤 - 警告: 此程序集被标记为 "引用程序集", 这意味着它只包含元数据, 没有可执行代码。 + 警告:此程序集被标记为“引用程序集”,这意味着它只包含元数据,没有可执行代码。 - 警告: 某些程序集引用无法自动解析。这可能会导致某些部分反编译错误, + 警告:某些程序集引用无法自动解析。这可能会导致某些部分反编译错误, - 比如属性getter/setter 访问。要获得最佳反编译结果, 请手动将缺少的引用添加到加载的程序集列表中。 + 例如属性 getter/setter 访问。要获得最佳反编译结果,请手动将缺少的引用添加到加载的程序集列表中。 显示程序集加载日志 @@ -532,10 +517,10 @@ 其他资源 - 使用Tab替代空格 + 使用 Tab 替代空格 - 在基数10中显示元数据标记 + 使用十进制显示元数据标记 反编译后展开引用和声明 @@ -547,13 +532,13 @@ 缩进 - 缩进长度: + 缩进长度: - Tab长度: + Tab 长度: - 搜索 (Ctrl + Shift + F 或 Ctrl + E) + 搜索(Ctrl + Shift + F 或 Ctrl + E) 显示所有类型和成员 @@ -568,10 +553,10 @@ 下面选择的设置将与语言下拉列表中的选择一起应用于反编译程序输出。在下拉列表中选择较低的语言版本将停用较高版本的所有选定选项。请注意, 某些设置隐式依赖于彼此, 例如: 如果不首先将静态调用转换为扩展方法调用, 则无法引入 LINQ 表达式。 - 反编译枚举器 (yield return) + 反编译枚举器(yield return) - 反编译匿名方法或lambdas + 反编译匿名方法或 lambda 反编译匿名类型 @@ -583,19 +568,19 @@ 反编译表达树 - 反编译使用"dynamic" 类型 + 反编译使用 dynamic 类型 反编译异步方法 - 反编译catch/finally内的await + 反编译 catch/finally 内的 await 反编译 [DecimalConstant(...)] 作为简单的文本值 - 反编译 C# 1.0 "public unsafe fixed int arr[10];" 成员 + 反编译 C# 1.0“public unsafe fixed int arr[10];”成员 对空变量使用提升运算符 @@ -610,7 +595,7 @@ 反编译自动事件 - 检测using语句 + 检测 using 语句 其他 @@ -619,16 +604,16 @@ 始终使用大括号 - 检测 foreach语句 + 检测 foreach 语句 - 检测 lock语句 + 检测 lock 语句 - 检测switch 的字符串 + 检测 switch 的字符串 - 插入using声明 + 插入 using 声明 使用扩展方法语法 @@ -643,7 +628,7 @@ 始终强制转换显式接口实现调用的目标 - 使用调试符号中的变量名 (如果可用) + 使用调试符号中的变量名(如果可用) 数组初始化器表达式 @@ -652,10 +637,10 @@ 对象或集合初始化器表达式 - Dictionary初始值设定项表达式 + Dictionary 初始值设定项表达式 - 在集合初始化器表达式中允许扩展 "添加" 方法 + 在集合初始化器表达式中允许扩展 Add 方法 使用字符串插值 @@ -673,16 +658,16 @@ 使用丢弃物 - IsByRefLikeAttribute应替换为结构上的 "ref" 修饰符 + IsByRefLikeAttribute 应替换为结构上的 ref 修饰符 - IsReadOnlyAttribute 应替为结构参数上的 "readonly"/"in"中的修饰符 + IsReadOnlyAttribute 应替为结构参数上的 readonly/in 中的修饰符 - 类型参数上的IsUnmanagedAttribute 应替换为 "非托管" 约束 + 类型参数上的 IsUnmanagedAttribute 应替换为 unmanaged 约束 - 使用stackalloc 初始化器语法 + 使用 stackalloc 初始化器语法 使用元组类型语法 @@ -700,13 +685,10 @@ 使用非尾随命名参数 - 如果可能, 删除可选参数 + 如果可能,删除可选参数 - 引入本地功能 - - - C# 7.0 本地函数未实现! + 引入局部函数(local functions) 可空引用类型 @@ -715,24 +697,189 @@ 显示调试符号中的信息 (如果可用) - Vb 特定选项 + VB 特定选项 - F # 特定选项 + F# 特定选项 - 删除死的和副作用免费的代码 (请谨慎使用) + 删除死代码和无副作用的代码(请谨慎使用) 在已加载的程序集上应用 Windows 运行时投影 - 搜索Microsoft Docs... + 搜索 Microsoft Docs... 关于 - 使用新的 SDK 格式 (*.csproj) 生成项目文件 + 使用新的 SDK 格式(*.csproj)生成项目文件 + + + 新建(_N) + + + 窗口(_W) + + + 添加预配置列表... + + + 添加文件资源管理器集成 + + + 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中添加“{0}”。这样在文件资源管理器中,.dll 文件与 .exe 文件可以在右键菜单中使用 ILSpy 打开。 + +确定继续? + + + 程序集 + + + 程序集 + + + 目录非空。文件会被覆盖。 +确定继续? + + + 项目目录非空 + + + 基类型 + + + 克隆(_L) + + + 区域 + + + 关闭 + + + 无法解析实体。可能是由于缺少程序集引用。请添加缺少的程序集并重试。 + + + 使用 ref 扩展方法 + + + 始终显示枚举数值 + + + 反编译异步 IAsyncEnumerator 方法 + + + 检测使用了 await 的 using 和 foreach 块 + + + 如果可能,转换到 do-while 块 + + + 如果可能,转换到 for 块 + + + 引入静态局部函数(static local functions) + + + 使用 nint/nuint 类型 + + + 范围(ranges) + + + 只读方法 + + + 删除死值(请谨慎使用) + + + 如果可能,分离局部变量的声明与初始化(int x = 5; -> int x; x = 5;) + + + 使用基于模式的 fixed 语句 + + + 使用 throw 表达式 + + + 在新选项卡反编译 + + + 在树视图中隐藏空的元数据表 + + + 高亮配对的大括号 + + + 管理程序集列表(_L)... + + + 管理程序集列表 + + + 是否删除选中的程序集列表? + + + 已有同名的列表。 + + + 是否删除所有程序集列表,并重建默认程序集列表? + + + 导航失败,因为目标是隐藏的或编译器生成的类。\n +请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 + + + 新建列表 + + + 新选项卡 + + + 重命名(_E) + + + 移除文件资源管理器集成 + + + 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中移除“{0}”。 + +确定继续? + + + 重命名列表 + + + 还原到默认值 + + + 是否为活动页面加载默认值? + + + 选择一个程序集列表 + + + 选择一个反编译目标语言 + + + 选择输出语言的版本 + + + 只显示公有类型和成员(_P) + + + 只显示公有类型和成员 + + + 关闭所有文档(_C) + + + 重置布局(_R) + + + 调试 -- PDB 转储为 XML \ No newline at end of file From 70529f92ac8353b03988db79cac005e4006bf097 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 28 Jul 2020 21:01:24 +0800 Subject: [PATCH 32/92] Fix ManageAssemblyLists menu text --- ILSpy/Commands/ManageAssemblyListsCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy/Commands/ManageAssemblyListsCommand.cs b/ILSpy/Commands/ManageAssemblyListsCommand.cs index 49effa4a7..10ba404d2 100644 --- a/ILSpy/Commands/ManageAssemblyListsCommand.cs +++ b/ILSpy/Commands/ManageAssemblyListsCommand.cs @@ -21,7 +21,7 @@ using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.ManageAssemblyLists), MenuIcon = "Images/AssemblyList", MenuCategory = nameof(Resources.Open), MenuOrder = 1.7)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.ManageAssembly_Lists), MenuIcon = "Images/AssemblyList", MenuCategory = nameof(Resources.Open), MenuOrder = 1.7)] sealed class ManageAssemblyListsCommand : SimpleCommand { public override void Execute(object parameter) From 11a2512413ae1d82c8806297bd4de5c3cb7092e9 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 28 Jul 2020 21:08:25 +0800 Subject: [PATCH 33/92] More translations --- ILSpy/Properties/Resources.zh-Hans.resx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index a31cb218d..89cbcd24f 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -406,7 +406,7 @@ 打开资源管理器 - |所有文件 |*.* + |所有文件|*.* 保存代码 @@ -478,19 +478,19 @@ 大小: - 调试步骤 + 调试步 - UseFieldSugar + 使用 fld 语法糖 - UseLogicOperationSugar + 使用 logic 语法糖 - ShowILRanges + 显示 IL 范围 - ShowChildIndexInBlock + 显示块中的子序号 在此步骤之前显示状态 @@ -499,7 +499,7 @@ 在此步骤之后显示状态 - 调试此步骤 + 调试此步 警告:此程序集被标记为“引用程序集”,这意味着它只包含元数据,没有可执行代码。 From 2f96faffb3ee9c468fba6dffa6e1f1743c595323 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 28 Jul 2020 21:21:17 +0800 Subject: [PATCH 34/92] Small adjust --- ILSpy/Properties/Resources.zh-Hans.resx | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 89cbcd24f..4b523c2a5 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -208,7 +208,7 @@ 名称 - 值(以字符串形式) + 值(以字符串形式) 类型 @@ -310,10 +310,10 @@ 复制错误信息 - 使用调试符号中的变量名称(如果可用) + 使用调试符号中的变量名称(如果可用) - 显示调试符号的信息(如果可用) + 显示调试符号的信息(如果可用) 在反编译代码中显示 XML 文档 @@ -418,7 +418,7 @@ 搜索... - 搜索已中止, 发现超过1000个结果。 + 搜索已中止,发现超过1000个结果。 搜索... @@ -454,7 +454,7 @@ 每周自动检查更新 - 搜索 t:TypeName、m:Member 或 c:Constant;使用完全匹配 (=term), '不应包含' (-term) 或 '必须包含' (+term); 使用 /reg(ular)?Ex(pressions)?/或两者 - t:/Type(Name)?/... + 搜索 t:类型、m:成员 或 c:常量;使用完全匹配(=term)、不应包含(-term)或必须包含(+term);使用 /正(则)?表达(式)?/;或同时使用二者 - t:/类(型)?/... 选项 @@ -538,7 +538,7 @@ Tab 长度: - 搜索(Ctrl + Shift + F 或 Ctrl + E) + 搜索(Ctrl + Shift + F 或 Ctrl + E) 显示所有类型和成员 @@ -553,7 +553,7 @@ 下面选择的设置将与语言下拉列表中的选择一起应用于反编译程序输出。在下拉列表中选择较低的语言版本将停用较高版本的所有选定选项。请注意, 某些设置隐式依赖于彼此, 例如: 如果不首先将静态调用转换为扩展方法调用, 则无法引入 LINQ 表达式。 - 反编译枚举器(yield return) + 反编译枚举器(yield return) 反编译匿名方法或 lambda @@ -628,7 +628,7 @@ 始终强制转换显式接口实现调用的目标 - 使用调试符号中的变量名(如果可用) + 使用调试符号中的变量名(如果可用) 数组初始化器表达式 @@ -688,13 +688,13 @@ 如果可能,删除可选参数 - 引入局部函数(local functions) + 引入局部函数(local functions) 可空引用类型 - 显示调试符号中的信息 (如果可用) + 显示调试符号中的信息(如果可用) VB 特定选项 @@ -703,7 +703,7 @@ F# 特定选项 - 删除死代码和无副作用的代码(请谨慎使用) + 删除死代码和无副作用的代码(请谨慎使用) 在已加载的程序集上应用 Windows 运行时投影 @@ -715,7 +715,7 @@ 关于 - 使用新的 SDK 格式(*.csproj)生成项目文件 + 使用新的 SDK 格式(*.csproj)生成项目文件 新建(_N) @@ -781,19 +781,19 @@ 如果可能,转换到 for 块 - 引入静态局部函数(static local functions) + 引入静态局部函数(static local functions) 使用 nint/nuint 类型 - 范围(ranges) + 范围(ranges) 只读方法 - 删除死值(请谨慎使用) + 删除死值(请谨慎使用) 如果可能,分离局部变量的声明与初始化(int x = 5; -> int x; x = 5;) @@ -830,7 +830,7 @@ 导航失败,因为目标是隐藏的或编译器生成的类。\n -请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 +请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 新建列表 From 2065855b43a4a977fca2dab23790bce1cb106ba5 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 28 Jul 2020 21:26:15 +0800 Subject: [PATCH 35/92] Clarify decompile and disassemble --- ILSpy/Properties/Resources.zh-Hans.resx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 4b523c2a5..adf0aeec4 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -139,7 +139,7 @@ 打开 - 调试 -- 反汇编全部 + 调试 -- 全部反编译到 IL 退出(_X) @@ -160,10 +160,10 @@ 重新加载全部程序集 - 调试 -- 反编译全部 + 调试 -- 全部反编译到 C# - 调试 -- 反编译100x + 调试 -- 反编译100次 生成可携带 PDB From d02fd0982219d4e87e805aed4ad225c10d4636de Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 27 Jul 2020 21:02:35 +0200 Subject: [PATCH 36/92] Explicitly create partitioners for `Parallel.ForEach` calls. Apparently the default `Parallel.ForEach` logic checks whether the input enumerable is an array or `IList`, and if it is, creates whole chunks of sequential list/array indices and assigns those to the worker threads. This is more efficient if the individual items are processed very quickly; but if they take varying amounts of time, a single chunk full of expensive items might keep a single CPU core busy for long after all other CPU cores have gone idle. --- .../WholeProjectDecompiler.cs | 3 +- ILSpy/Commands/DecompileAllCommand.cs | 44 ++++++++++--------- ILSpy/Commands/DisassembleAllCommand.cs | 9 +++- ILSpy/SolutionWriter.cs | 7 ++- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 56394502f..790c21da9 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -33,6 +33,7 @@ using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.DebugInfo; +using System.Collections.Concurrent; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler { @@ -205,7 +206,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler var progress = ProgressIndicator; DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings); Parallel.ForEach( - files, + Partitioner.Create(files, loadBalance: true), new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, CancellationToken = cancellationToken diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs index ac263edf7..56a698e33 100644 --- a/ILSpy/Commands/DecompileAllCommand.cs +++ b/ILSpy/Commands/DecompileAllCommand.cs @@ -19,6 +19,7 @@ #if DEBUG using System; +using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -40,29 +41,32 @@ namespace ICSharpCode.ILSpy { Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); - Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) { - if (!asm.HasLoadError) { - Stopwatch w = Stopwatch.StartNew(); - Exception exception = null; - using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) { - try { - new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct }); + Parallel.ForEach( + Partitioner.Create( MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true), + new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, + delegate(LoadedAssembly asm) { + if (!asm.HasLoadError) { + Stopwatch w = Stopwatch.StartNew(); + Exception exception = null; + using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) { + try { + new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct }); + } + catch (Exception ex) { + writer.WriteLine(ex.ToString()); + exception = ex; + } } - catch (Exception ex) { - writer.WriteLine(ex.ToString()); - exception = ex; + lock (output) { + output.Write(asm.ShortName + " - " + w.Elapsed); + if (exception != null) { + output.Write(" - "); + output.Write(exception.GetType().Name); + } + output.WriteLine(); } } - lock (output) { - output.Write(asm.ShortName + " - " + w.Elapsed); - if (exception != null) { - output.Write(" - "); - output.Write(exception.GetType().Name); - } - output.WriteLine(); - } - } - }); + }); return output; }, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions(); } diff --git a/ILSpy/Commands/DisassembleAllCommand.cs b/ILSpy/Commands/DisassembleAllCommand.cs index 23319be78..e220ead0c 100644 --- a/ILSpy/Commands/DisassembleAllCommand.cs +++ b/ILSpy/Commands/DisassembleAllCommand.cs @@ -23,6 +23,8 @@ using System.Diagnostics; using System.Threading.Tasks; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.Properties; +using System.Collections.Concurrent; + namespace ICSharpCode.ILSpy { [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)] @@ -37,8 +39,11 @@ namespace ICSharpCode.ILSpy { Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); - Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) { - if (!asm.HasLoadError) { + Parallel.ForEach( + Partitioner.Create(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true), + new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, + delegate (LoadedAssembly asm) { + if (!asm.HasLoadError) { Stopwatch w = Stopwatch.StartNew(); Exception exception = null; using (var writer = new System.IO.StreamWriter("c:\\temp\\disassembled\\" + asm.Text.Replace("(", "").Replace(")", "").Replace(' ', '_') + ".il")) { diff --git a/ILSpy/SolutionWriter.cs b/ILSpy/SolutionWriter.cs index 03ee32ab3..614076206 100644 --- a/ILSpy/SolutionWriter.cs +++ b/ILSpy/SolutionWriter.cs @@ -99,7 +99,12 @@ namespace ICSharpCode.ILSpy Stopwatch stopwatch = Stopwatch.StartNew(); try { - await Task.Run(() => Parallel.ForEach(assemblies, n => WriteProject(n, language, solutionDirectory, ct))) + // Explicitly create an enumerable partitioner here to avoid Parallel.ForEach's special cases for lists, + // as those seem to use static partitioning which is inefficient if assemblies take differently + // long to decompile. + await Task.Run(() => Parallel.ForEach(Partitioner.Create(assemblies), + new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, + n => WriteProject(n, language, solutionDirectory, ct))) .ConfigureAwait(false); await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects)) From d388319cba7d1973f65e95c4c1f05f36dcfda02d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Jul 2020 22:16:17 +0200 Subject: [PATCH 37/92] Add support for C# 9 init accessors. --- .../CSharp/CSharpDecompiler.cs | 1 + .../OutputVisitor/CSharpOutputVisitor.cs | 6 +- .../CSharp/Syntax/TypeMembers/Accessor.cs | 5 +- .../Syntax/TypeMembers/PropertyDeclaration.cs | 1 + .../CSharp/Syntax/TypeSystemAstBuilder.cs | 55 ++++++++++++++----- ICSharpCode.Decompiler/DecompilerSettings.cs | 20 ++++++- ICSharpCode.Decompiler/TypeSystem/IMethod.cs | 6 ++ .../TypeSystem/Implementation/FakeMember.cs | 1 + .../Implementation/LocalFunctionMethod.cs | 1 + .../Implementation/MetadataMethod.cs | 22 ++++++-- .../Implementation/MetadataProperty.cs | 3 +- .../Implementation/SpecializedMethod.cs | 1 + .../Implementation/SyntheticRangeIndexer.cs | 1 + .../TypeSystem/VarArgInstanceMethod.cs | 1 + .../CSharpHighlightingTokenWriter.cs | 2 + 15 files changed, 104 insertions(+), 22 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 0c18b39a3..40517bfc8 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -405,6 +405,7 @@ namespace ICSharpCode.Decompiler.CSharp typeSystemAstBuilder.AlwaysUseShortTypeNames = true; typeSystemAstBuilder.AddResolveResultAnnotations = true; typeSystemAstBuilder.UseNullableSpecifierForValueTypes = settings.LiftNullables; + typeSystemAstBuilder.SupportInitAccessors = settings.InitAccessors; return typeSystemAstBuilder; } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 81f3f0c6e..1fc2b44bd 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1927,7 +1927,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteKeyword("get", PropertyDeclaration.GetKeywordRole); style = policy.PropertyGetBraceStyle; } else if (accessor.Role == PropertyDeclaration.SetterRole) { - WriteKeyword("set", PropertyDeclaration.SetKeywordRole); + if (accessor.Keyword.Role == PropertyDeclaration.InitKeywordRole) { + WriteKeyword("init", PropertyDeclaration.InitKeywordRole); + } else { + WriteKeyword("set", PropertyDeclaration.SetKeywordRole); + } style = policy.PropertySetBraceStyle; } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) { WriteKeyword("add", CustomEventDeclaration.AddKeywordRole); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs index dd41e83b7..345aa9aca 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs @@ -72,13 +72,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } /// - /// Gets the 'get'/'set'/'add'/'remove' keyword + /// Gets the 'get'/'set'/'init'/'add'/'remove' keyword /// public CSharpTokenNode Keyword { get { for (AstNode child = this.FirstChild; child != null; child = child.NextSibling) { if (child.Role == PropertyDeclaration.GetKeywordRole || child.Role == PropertyDeclaration.SetKeywordRole - || child.Role == CustomEventDeclaration.AddKeywordRole || child.Role == CustomEventDeclaration.RemoveKeywordRole) + || child.Role == PropertyDeclaration.InitKeywordRole + || child.Role == CustomEventDeclaration.AddKeywordRole || child.Role == CustomEventDeclaration.RemoveKeywordRole) { return (CSharpTokenNode)child; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs index 00f163122..34ac8039a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static readonly TokenRole GetKeywordRole = new TokenRole ("get"); public static readonly TokenRole SetKeywordRole = new TokenRole ("set"); + public static readonly TokenRole InitKeywordRole = new TokenRole ("init"); public static readonly Role GetterRole = new Role("Getter", Accessor.Null); public static readonly Role SetterRole = new Role("Setter", Accessor.Null); public static readonly Role ExpressionBodyRole = new Role("ExpressionBody", Expression.Null); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 33464c99a..1f944a664 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using System.Reflection; using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.Semantics; @@ -205,6 +206,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// The default value is . /// public bool PrintIntegralValuesAsHex { get; set; } + + /// + /// Controls whether C# 9 "init;" accessors are supported. + /// If disabled, emits "set /*init*/;" instead. + /// + public bool SupportInitAccessors { get; set; } #endregion #region Convert Type @@ -1363,7 +1370,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return ConvertDestructor((IMethod)entity); case SymbolKind.Accessor: IMethod accessor = (IMethod)entity; - return ConvertAccessor(accessor, accessor.AccessorOwner != null ? accessor.AccessorOwner.Accessibility : Accessibility.None, false); + Accessibility ownerAccessibility = accessor.AccessorOwner?.Accessibility ?? Accessibility.None; + return ConvertAccessor(accessor, accessor.AccessorKind, ownerAccessibility, false); default: throw new ArgumentException("Invalid value for SymbolKind: " + entity.SymbolKind); } @@ -1554,15 +1562,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } - Accessor ConvertAccessor(IMethod accessor, Accessibility ownerAccessibility, bool addParameterAttribute) + Accessor ConvertAccessor(IMethod accessor, MethodSemanticsAttributes kind, Accessibility ownerAccessibility, bool addParameterAttribute) { if (accessor == null) return Accessor.Null; Accessor decl = new Accessor(); - if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility) - decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); - if (accessor.HasReadonlyModifier()) - decl.Modifiers |= Modifiers.Readonly; if (ShowAttributes) { decl.Attributes.AddRange(ConvertAttributes(accessor.GetAttributes())); decl.Attributes.AddRange(ConvertAttributes(accessor.GetReturnTypeAttributes(), "return")); @@ -1570,10 +1574,35 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Attributes.AddRange(ConvertAttributes(accessor.Parameters.Last().GetAttributes(), "param")); } } + if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility) + decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); + if (accessor.HasReadonlyModifier()) + decl.Modifiers |= Modifiers.Readonly; + TokenRole keywordRole = kind switch + { + MethodSemanticsAttributes.Getter => PropertyDeclaration.GetKeywordRole, + MethodSemanticsAttributes.Setter => PropertyDeclaration.SetKeywordRole, + MethodSemanticsAttributes.Adder => CustomEventDeclaration.AddKeywordRole, + MethodSemanticsAttributes.Remover => CustomEventDeclaration.RemoveKeywordRole, + _ => null + }; + if (kind == MethodSemanticsAttributes.Setter && SupportInitAccessors && accessor.IsInitOnly) { + keywordRole = PropertyDeclaration.InitKeywordRole; + } + if (keywordRole != null) { + decl.AddChild(new CSharpTokenNode(TextLocation.Empty, keywordRole), keywordRole); + } + if (accessor.IsInitOnly && keywordRole != PropertyDeclaration.InitKeywordRole) { + decl.AddChild(new Comment("init", CommentType.MultiLine), Roles.Comment); + } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, accessor)); } - decl.Body = GenerateBodyBlock(); + if (GenerateBody) { + decl.Body = GenerateBodyBlock(); + } else { + decl.AddChild(new CSharpTokenNode(TextLocation.Empty, Roles.Semicolon), Roles.Semicolon); + } return decl; } @@ -1592,8 +1621,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ct.HasReadOnlySpecifier = true; } decl.Name = property.Name; - decl.Getter = ConvertAccessor(property.Getter, property.Accessibility, false); - decl.Setter = ConvertAccessor(property.Setter, property.Accessibility, true); + decl.Getter = ConvertAccessor(property.Getter, MethodSemanticsAttributes.Getter, property.Accessibility, false); + decl.Setter = ConvertAccessor(property.Setter, MethodSemanticsAttributes.Setter, property.Accessibility, true); decl.PrivateImplementationType = GetExplicitInterfaceType (property); MergeReadOnlyModifiers(decl, decl.Getter, decl.Setter); return decl; @@ -1624,8 +1653,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax foreach (IParameter p in indexer.Parameters) { decl.Parameters.Add(ConvertParameter(p)); } - decl.Getter = ConvertAccessor(indexer.Getter, indexer.Accessibility, false); - decl.Setter = ConvertAccessor(indexer.Setter, indexer.Accessibility, true); + decl.Getter = ConvertAccessor(indexer.Getter, MethodSemanticsAttributes.Getter, indexer.Accessibility, false); + decl.Setter = ConvertAccessor(indexer.Setter, MethodSemanticsAttributes.Setter, indexer.Accessibility, true); decl.PrivateImplementationType = GetExplicitInterfaceType (indexer); MergeReadOnlyModifiers(decl, decl.Getter, decl.Setter); return decl; @@ -1644,8 +1673,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } decl.ReturnType = ConvertType(ev.ReturnType); decl.Name = ev.Name; - decl.AddAccessor = ConvertAccessor(ev.AddAccessor, ev.Accessibility, true); - decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor, ev.Accessibility, true); + decl.AddAccessor = ConvertAccessor(ev.AddAccessor, MethodSemanticsAttributes.Adder, ev.Accessibility, true); + decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor, MethodSemanticsAttributes.Remover, ev.Accessibility, true); decl.PrivateImplementationType = GetExplicitInterfaceType (ev); MergeReadOnlyModifiers(decl, decl.AddAccessor, decl.RemoveAccessor); return decl; diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index e1b158b0a..26bd075b0 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -116,12 +116,13 @@ namespace ICSharpCode.Decompiler } if (languageVersion < CSharp.LanguageVersion.Preview) { nativeIntegers = false; + initAccessors = false; } } public CSharp.LanguageVersion GetMinimumRequiredVersion() { - if (nativeIntegers) + if (nativeIntegers || initAccessors) return CSharp.LanguageVersion.Preview; if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement || staticLocalFunctions || ranges) return CSharp.LanguageVersion.CSharp8_0; @@ -163,6 +164,23 @@ namespace ICSharpCode.Decompiler } } + bool initAccessors = true; + + /// + /// Use C# 9 init; property accessors. + /// + [Category("C# 9.0 (experimental)")] + [Description("DecompilerSettings.InitAccessors")] + public bool InitAccessors { + get { return initAccessors; } + set { + if (initAccessors != value) { + initAccessors = value; + OnPropertyChanged(); + } + } + } + bool anonymousMethods = true; /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs index ad1c177d6..b12b4f064 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs @@ -40,6 +40,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// bool ReturnTypeIsRefReadOnly { get; } + /// + /// Gets whether this method may only be called on fresh instances. + /// Used with C# 9 `init;` property setters. + /// + bool IsInitOnly { get; } + /// /// Gets whether the method accepts the 'this' reference as ref readonly. /// This can be either because the method is C# 8.0 'readonly', or because it is within a C# 7.2 'readonly struct' diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs index 2a11babee..837539720 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs @@ -134,6 +134,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IEnumerable IMethod.GetReturnTypeAttributes() => EmptyList.Instance; bool IMethod.ReturnTypeIsRefReadOnly => false; bool IMethod.ThisIsRefReadOnly => false; + bool IMethod.IsInitOnly => false; public IReadOnlyList TypeParameters { get; set; } = EmptyList.Instance; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs index 1139366f1..1e14fa85b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs @@ -147,6 +147,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly; + bool IMethod.IsInitOnly => baseMethod.IsInitOnly; /// /// We consider local functions as always static, because they do not have a "this parameter". /// Even local functions in instance methods capture this. diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index ab02b8252..a015d7d3d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -50,6 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IType returnType; byte returnTypeIsRefReadonly = ThreeState.Unknown; byte thisIsRefReadonly = ThreeState.Unknown; + bool isInitOnly; internal MetadataMethod(MetadataModule module, MethodDefinitionHandle handle) { @@ -150,6 +151,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } + public bool IsInitOnly { + get { + var returnType = LazyInit.VolatileRead(ref this.returnType); + if (returnType == null) + DecodeSignature(); + return this.isInitOnly; + } + } + internal Nullability NullableContext { get { var methodDef = module.metadata.GetMethodDefinition(handle); @@ -163,19 +173,23 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var genericContext = new GenericContext(DeclaringType.TypeParameters, this.TypeParameters); IType returnType; IParameter[] parameters; + ModifiedType mod; try { var nullableContext = methodDef.GetCustomAttributes().GetNullableContext(module.metadata) ?? DeclaringTypeDefinition.NullableContext; var signature = methodDef.DecodeSignature(module.TypeProvider, genericContext); - (returnType, parameters) = DecodeSignature(module, this, signature, methodDef.GetParameters(), nullableContext, module.OptionsForEntity(this)); + (returnType, parameters, mod) = DecodeSignature(module, this, signature, methodDef.GetParameters(), nullableContext, module.OptionsForEntity(this)); } catch (BadImageFormatException) { returnType = SpecialType.UnknownType; parameters = Empty.Array; + mod = null; } + this.isInitOnly = mod is { Modifier: { Name: "IsExternalInit", Namespace: "System.Runtime.CompilerServices" } }; LazyInit.GetOrSet(ref this.returnType, returnType); LazyInit.GetOrSet(ref this.parameters, parameters); } - internal static (IType, IParameter[]) DecodeSignature(MetadataModule module, IParameterizedMember owner, + internal static (IType returnType, IParameter[] parameters, ModifiedType returnTypeModifier) DecodeSignature( + MetadataModule module, IParameterizedMember owner, MethodSignature signature, ParameterHandleCollection? parameterHandles, Nullability nullableContext, TypeSystemOptions typeSystemOptions, CustomAttributeHandleCollection? returnTypeAttributes = null) @@ -231,7 +245,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation Debug.Assert(i == parameters.Length); var returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(signature.ReturnType, module.Compilation, returnTypeAttributes, metadata, typeSystemOptions, nullableContext); - return (returnType, parameters); + return (returnType, parameters, signature.ReturnType as ModifiedType); } #endregion @@ -453,7 +467,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #endregion public Accessibility Accessibility => GetAccessibility(attributes); - + internal static Accessibility GetAccessibility(MethodAttributes attr) { switch (attr & MethodAttributes.MemberAccessMask) { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 83596cb51..2f33e3d17 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -153,7 +153,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // Roslyn uses the same workaround (see the NullableTypeDecoder.TransformType // call in PEPropertySymbol). var typeOptions = module.OptionsForEntity(declTypeDef); - (returnType, parameters) = MetadataMethod.DecodeSignature(module, this, signature, + (returnType, parameters, _) = MetadataMethod.DecodeSignature( + module, this, signature, parameterHandles, nullableContext, typeOptions, returnTypeAttributes: propertyDef.GetCustomAttributes()); } catch (BadImageFormatException) { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs index 58d1e2f56..7ec70de21 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs @@ -98,6 +98,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool ReturnTypeIsRefReadOnly => methodDefinition.ReturnTypeIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => methodDefinition.ThisIsRefReadOnly; + bool IMethod.IsInitOnly => methodDefinition.IsInitOnly; public IReadOnlyList TypeParameters { get { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs index 9d79e1b79..0acaf9d28 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs @@ -62,6 +62,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool IMethod.ReturnTypeIsRefReadOnly => underlyingMethod.ReturnTypeIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => underlyingMethod.ThisIsRefReadOnly; + bool IMethod.IsInitOnly => underlyingMethod.IsInitOnly; IReadOnlyList IMethod.TypeParameters => EmptyList.Instance; IReadOnlyList IMethod.TypeArguments => EmptyList.Instance; diff --git a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs index ecc0cbf22..6b53caa88 100644 --- a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs @@ -115,6 +115,7 @@ namespace ICSharpCode.Decompiler.TypeSystem IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly; + bool IMethod.IsInitOnly => baseMethod.IsInitOnly; public IReadOnlyList TypeParameters { get { return baseMethod.TypeParameters; } diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index 6845088a3..f588cd153 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -184,8 +184,10 @@ namespace ICSharpCode.ILSpy case "set": case "add": case "remove": + case "init": if (role == PropertyDeclaration.GetKeywordRole || role == PropertyDeclaration.SetKeywordRole || + role == PropertyDeclaration.InitKeywordRole || role == CustomEventDeclaration.AddKeywordRole || role == CustomEventDeclaration.RemoveKeywordRole) color = accessorKeywordsColor; From 4bc5b2bcbb62fd42655312ac5b82522a45b79cce Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 30 Jul 2020 12:14:33 +0800 Subject: [PATCH 38/92] update tests --- ILSpy-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy-tests b/ILSpy-tests index e83c25d91..aa8f1197e 160000 --- a/ILSpy-tests +++ b/ILSpy-tests @@ -1 +1 @@ -Subproject commit e83c25d910124986a42089055ecff70682c4fdb9 +Subproject commit aa8f1197e6a513bcc10bcc38ec7d2143d27a2246 From c05151d28db5477e4daf881d9a08dee44702de6b Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Thu, 30 Jul 2020 16:26:29 +0800 Subject: [PATCH 39/92] Adjust res order. --- ILSpy/Properties/Resources.zh-Hans.resx | 97 +++++++++++++------------ 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 05b3cf770..393a598ba 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -747,9 +747,6 @@ 项目目录非空 - - 基类型 - 克隆(_L) @@ -783,9 +780,6 @@ 引入静态局部函数(static local functions) - - 使用 nint/nuint 类型 - 范围(ranges) @@ -813,73 +807,82 @@ 高亮配对的大括号 - - 管理程序集列表(_L)... - - - 管理程序集列表 + + 重置布局(_R) - - 是否删除选中的程序集列表? + + 关闭所有文档(_C) - - 已有同名的列表。 + + 只显示公有类型和成员 - - 是否删除所有程序集列表,并重建默认程序集列表? + + 只显示公有类型和成员(_P) - - 导航失败,因为目标是隐藏的或编译器生成的类。\n -请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 + + 选择输出语言的版本 - - 新建列表 + + 选择一个程序集列表 - - 新选项卡 + + 选择一个反编译目标语言 - - 重命名(_E) + + 重命名列表 - - 移除文件资源管理器集成 + + 还原到默认值 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中移除“{0}”。 确定继续? - - 重命名列表 - - - 还原到默认值 + + 移除文件资源管理器集成 是否为活动页面加载默认值? - - 选择一个程序集列表 + + 重命名(_E) - - 选择一个反编译目标语言 + + 新建列表 - - 选择输出语言的版本 + + 新选项卡 - - 只显示公有类型和成员(_P) + + 管理程序集列表(_L)... - - 只显示公有类型和成员 + + 管理程序集列表 - - 关闭所有文档(_C) + + 导航失败,因为目标是隐藏的或编译器生成的类。\n +请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 - - 重置布局(_R) + + 是否删除选中的程序集列表? + + + 已有同名的列表。 + + + 是否删除所有程序集列表,并重建默认程序集列表? + + + ILSpyAboutPage_zh_Hans.txt 调试 -- PDB 转储为 XML + + 使用 nint/nuint 类型 + + + 基类型 + \ No newline at end of file From 3e64895ec2fb312e67cd6becc74c6e59e9b2c888 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Thu, 30 Jul 2020 16:48:21 +0800 Subject: [PATCH 40/92] =?UTF-8?q?Step=20->=20=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ILSpy/Properties/Resources.zh-Hans.resx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 393a598ba..36bbc1b90 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -478,7 +478,7 @@ 大小: - 调试步 + 调试步骤 使用 fld 语法糖 @@ -499,7 +499,7 @@ 在此步骤之后显示状态 - 调试此步 + 调试此步骤 警告:此程序集被标记为“引用程序集”,这意味着它只包含元数据,没有可执行代码。 From 4b05d85565997e29a6d8b2dd4cb21d46c1ece96f Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Thu, 30 Jul 2020 16:52:58 +0800 Subject: [PATCH 41/92] Update about page --- doc/ILSpyAboutPage_zh_Hans.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ILSpyAboutPage_zh_Hans.txt b/doc/ILSpyAboutPage_zh_Hans.txt index ed771b2e5..9a9221be0 100644 --- a/doc/ILSpyAboutPage_zh_Hans.txt +++ b/doc/ILSpyAboutPage_zh_Hans.txt @@ -1,13 +1,13 @@ -ILSpy 是开源的.NET程序集浏览器和反编译器. +ILSpy 是开源的 .NET 程序集浏览器和反编译器。 网站: https://ilspy.net/ 反馈BUG: https://github.com/icsharpcode/ILSpy/issues/new/choose -中文翻译反馈:https://github.com/maikebing/ILSpy/issues +中文翻译反馈:https://github.com/maikebing/ILSpy/issues Copyright 2011-2020 AlphaSierraPapa for the ILSpy team 当前和过去的贡献者: https://github.com/icsharpcode/ILSpy/graphs/contributors -ILSpy 基于 MIT License 发行. +ILSpy 基于 MIT 许可证发行。 -ILSpy 使用了其他开源库才能魔术般的实现, 于此同时我们想感谢他们为那些组件付出的人们! -它们各自的许可和版权信息请查看third-party注意事项. \ No newline at end of file +ILSpy 使用了其他开源库才能魔术般地实现,在此我们想感谢为那些组件付出的人们! +它们各自的许可和版权信息请查看第三方注意事项(third-party notices)。 \ No newline at end of file From 0830a7dadaf71b5199a42eaf0479b9d62a6ca5cd Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 30 Jul 2020 19:54:06 +0800 Subject: [PATCH 42/92] for vsct --- ILSpy.AddIn/ILSpy.AddIn.csproj | 27 ++++-- ILSpy.AddIn/ILSpyAddIn.en-US.vsct | 124 ++++++++++++++++++++++++++++ ILSpy.AddIn/ILSpyAddIn.vsct | 102 +---------------------- ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct | 123 +++++++++++++++++++++++++++ ILSpy.AddIn/ILSpyAddInPackage.cs | 1 + 5 files changed, 269 insertions(+), 108 deletions(-) create mode 100644 ILSpy.AddIn/ILSpyAddIn.en-US.vsct create mode 100644 ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 2ffbb6b44..adf54d6f9 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -122,23 +122,36 @@ - + + true + \ILSpy\zh-Hans\ + + + + + + + Designer - - - + + + Menus.ctmenu + Designer + - - - + + Menus.ctmenu Designer + + + diff --git a/ILSpy.AddIn/ILSpyAddIn.en-US.vsct b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct new file mode 100644 index 000000000..f0867de8b --- /dev/null +++ b/ILSpy.AddIn/ILSpyAddIn.en-US.vsct @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy.AddIn/ILSpyAddIn.vsct b/ILSpy.AddIn/ILSpyAddIn.vsct index d747baf57..156263ee9 100644 --- a/ILSpy.AddIn/ILSpyAddIn.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.vsct @@ -19,107 +19,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct new file mode 100644 index 000000000..544ddc299 --- /dev/null +++ b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy.AddIn/ILSpyAddInPackage.cs b/ILSpy.AddIn/ILSpyAddInPackage.cs index 533a78bdd..950cdc0d5 100644 --- a/ILSpy.AddIn/ILSpyAddInPackage.cs +++ b/ILSpy.AddIn/ILSpyAddInPackage.cs @@ -37,6 +37,7 @@ namespace ICSharpCode.ILSpy.AddIn [ProvideMenuResource("Menus.ctmenu", 1)] [Guid(GuidList.guidILSpyAddInPkgString)] [ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExistsAndFullyLoaded_string, PackageAutoLoadFlags.BackgroundLoad)] + [ProvideBindingPath] public sealed class ILSpyAddInPackage : AsyncPackage { /// From 9aa39a941a09089b654bc57c17858047ca1cfdf0 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 30 Jul 2020 21:37:04 +0800 Subject: [PATCH 43/92] modify for vsct --- ILSpy.AddIn/ILSpy.AddIn.csproj | 23 +++-- ILSpy.AddIn/ILSpyAddIn.en-US.vsct | 32 +------ ILSpy.AddIn/ILSpyAddIn.vsct | 50 +++++++++- ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct | 33 +------ ILSpy.AddIn/Properties/AssemblyInfo.cs | 3 +- ILSpy.AddIn/VSPackage.en-US.resx | 126 +++++++++++++++++++++++++ ILSpy.AddIn/VSPackage.zh-Hans.resx | 6 ++ 7 files changed, 199 insertions(+), 74 deletions(-) create mode 100644 ILSpy.AddIn/VSPackage.en-US.resx diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index adf54d6f9..b4f78a163 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -12,7 +12,6 @@ IC#Code ILSpy - en-US 1.7.1.0 1.7.1.0 @@ -90,11 +89,20 @@ Resources.Designer.cs Designer + + true + VSPackage.en-US.resources + VSPackage.resx + true VSPackage - + + true + VSPackage.zh-Hans.resources + VSPackage.resx + - - - - - - - - - - - - - - - - - - - @@ -109,15 +87,7 @@ - - - - - + diff --git a/ILSpy.AddIn/ILSpyAddIn.vsct b/ILSpy.AddIn/ILSpyAddIn.vsct index 156263ee9..3d992eae7 100644 --- a/ILSpy.AddIn/ILSpyAddIn.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.vsct @@ -19,11 +19,55 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -36,7 +80,7 @@ - + diff --git a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct index 544ddc299..f84717c94 100644 --- a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct @@ -35,28 +35,6 @@ with command ids defined by other packages. --> - - - - - - - - - - - - - - - - - - - @@ -108,16 +86,7 @@ - - - - - - + diff --git a/ILSpy.AddIn/Properties/AssemblyInfo.cs b/ILSpy.AddIn/Properties/AssemblyInfo.cs index db36e8d59..64f95fad1 100644 --- a/ILSpy.AddIn/Properties/AssemblyInfo.cs +++ b/ILSpy.AddIn/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -11,6 +12,6 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: CLSCompliant(false)] - +[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] [assembly: InternalsVisibleTo("ILSpy.AddIn_IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")] [assembly: InternalsVisibleTo("ILSpy.AddIn_UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")] diff --git a/ILSpy.AddIn/VSPackage.en-US.resx b/ILSpy.AddIn/VSPackage.en-US.resx new file mode 100644 index 000000000..73c158134 --- /dev/null +++ b/ILSpy.AddIn/VSPackage.en-US.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ILSpy.AddIn + + + Integration of the ILSpy Decompiler into Visual Studio. + + \ No newline at end of file diff --git a/ILSpy.AddIn/VSPackage.zh-Hans.resx b/ILSpy.AddIn/VSPackage.zh-Hans.resx index 1af7de150..73c158134 100644 --- a/ILSpy.AddIn/VSPackage.zh-Hans.resx +++ b/ILSpy.AddIn/VSPackage.zh-Hans.resx @@ -117,4 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ILSpy.AddIn + + + Integration of the ILSpy Decompiler into Visual Studio. + \ No newline at end of file From 5f150efb74660e32f08750bdc0becb151ccc1a55 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Thu, 30 Jul 2020 21:58:50 +0800 Subject: [PATCH 44/92] add for vsixlangpack --- ILSpy.AddIn/ILSpy.AddIn.csproj | 9 ++++++--- ILSpy.AddIn/zh-Hans/extension.vsixlangpack | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 ILSpy.AddIn/zh-Hans/extension.vsixlangpack diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index b4f78a163..a5471e387 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -130,14 +130,13 @@ - + true \ILSpy\zh-Hans\ - - + Designer @@ -147,6 +146,10 @@ Designer + + true + Always + Menus.ctmenu Designer diff --git a/ILSpy.AddIn/zh-Hans/extension.vsixlangpack b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack new file mode 100644 index 000000000..2ebb0cd5a --- /dev/null +++ b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack @@ -0,0 +1,7 @@ + + + + ILSpy + 可以在Visual Studio中直接打开反编译工具ILSpy. + + \ No newline at end of file From 485278acf8be1a86d3b3d0e68f238d56fa8274a1 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 31 Jul 2020 12:17:24 +0800 Subject: [PATCH 45/92] add ILSpy.ReadyToRun.Plugin.resources.dll to appveyor.yml for 7z --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 151bac6c2..5b3fdceef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ build_script: - msbuild ILSpy.sln /v:minimal /p:ResolveNuGetPackages=false "/logger:%ProgramFiles%\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" after_build: -- 7z a ILSpy_binaries.zip %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.dll %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.exe %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.config %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*\ILSpy.resources.dll +- 7z a ILSpy_binaries.zip %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.dll %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.exe %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*.config %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*\ILSpy.resources.dll %APPVEYOR_BUILD_FOLDER%\ILSpy\bin\%configuration%\net472\*\ILSpy.ReadyToRun.Plugin.resources.dll test_script: - vstest.console.exe /logger:Appveyor /Parallel "ICSharpCode.Decompiler.Tests\bin\%configuration%\net472\ICSharpCode.Decompiler.Tests.exe" "ILSpy.Tests\bin\%configuration%\net472\ILSpy.Tests.exe" "ILSpy.BamlDecompiler.Tests\bin\%configuration%\net472\ILSpy.BamlDecompiler.Tests.exe" From 865f85550159f351f185ce020503cb2eccf2e836 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 31 Jul 2020 12:31:26 +0800 Subject: [PATCH 46/92] Add something missing. --- ILSpy/Commands/DecompileCommand.cs | 5 +- ILSpy/Commands/GeneratePdbContextMenuEntry.cs | 10 +-- ILSpy/Commands/SaveCodeContextMenuEntry.cs | 2 +- ILSpy/Commands/SelectPdbContextMenuEntry.cs | 5 +- ILSpy/Properties/Resources.Designer.cs | 64 +++++++++++++++++-- ILSpy/Properties/Resources.resx | 18 ++++++ ILSpy/Properties/Resources.zh-Hans.resx | 18 ++++++ 7 files changed, 107 insertions(+), 15 deletions(-) diff --git a/ILSpy/Commands/DecompileCommand.cs b/ILSpy/Commands/DecompileCommand.cs index 24c6c4180..d9485e512 100644 --- a/ILSpy/Commands/DecompileCommand.cs +++ b/ILSpy/Commands/DecompileCommand.cs @@ -24,11 +24,12 @@ using System.Windows.Controls; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Metadata; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TreeNodes; namespace ICSharpCode.ILSpy.Commands { - [ExportContextMenuEntry(Header = "Decompile", Order = 10)] + [ExportContextMenuEntry(Header = nameof(Resources.Decompile), Order = 10)] class DecompileCommand : IContextMenuEntry { public bool IsVisible(TextViewContext context) @@ -68,7 +69,7 @@ namespace ICSharpCode.ILSpy.Commands } } - [ExportContextMenuEntry(Header = "Go to token", Order = 10)] + [ExportContextMenuEntry(Header = nameof(Resources.GoToToken), Order = 10)] class GoToToken : IContextMenuEntry { public void Execute(TextViewContext context) diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index 9bea8740e..609356f59 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -32,7 +32,7 @@ using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportContextMenuEntry(Header = "Generate portable PDB")] + [ExportContextMenuEntry(Header = nameof(Resources.GeneratePortable))] class GeneratePdbContextMenuEntry : IContextMenuEntry { public void Execute(TextViewContext context) @@ -55,12 +55,12 @@ namespace ICSharpCode.ILSpy { var file = assembly.GetPEFileOrNull(); if (!PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file)) { - MessageBox.Show($"Cannot create PDB file for {Path.GetFileName(assembly.FileName)}, because it does not contain a PE Debug Directory Entry of type 'CodeView'."); + MessageBox.Show(string.Format(Resources.CannotCreatePDBFile, Path.GetFileName(assembly.FileName))); return; } SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(assembly.ShortName) + ".pdb"; - dlg.Filter = "Portable PDB|*.pdb|All files|*.*"; + dlg.Filter = Resources.PortablePDBPdbAllFiles; dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName); if (dlg.ShowDialog() != true) return; DecompilationOptions options = new DecompilationOptions(); @@ -81,14 +81,14 @@ namespace ICSharpCode.ILSpy stopwatch.Stop(); output.WriteLine("Generation complete in " + stopwatch.Elapsed.TotalSeconds.ToString("F1") + " seconds."); output.WriteLine(); - output.AddButton(null, "Open Explorer", delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); }); + output.AddButton(null, Resources.OpenExplorer, delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); }); output.WriteLine(); return output; }, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions(); } } - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = "Save")] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = Resources.Save)] class GeneratePdbMainMenuEntry : SimpleCommand { public override bool CanExecute(object parameter) diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs index 84282eaa2..c54a2ba7b 100644 --- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs +++ b/ILSpy/Commands/SaveCodeContextMenuEntry.cs @@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.TextView { SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = "Solution.sln"; - dlg.Filter = "Visual Studio Solution file|*.sln|All files|*.*"; + dlg.Filter = Resources.VisualStudioSolutionFileSlnAllFiles; if (dlg.ShowDialog() != true) { return null; diff --git a/ILSpy/Commands/SelectPdbContextMenuEntry.cs b/ILSpy/Commands/SelectPdbContextMenuEntry.cs index 3303ca15c..b538ad708 100644 --- a/ILSpy/Commands/SelectPdbContextMenuEntry.cs +++ b/ILSpy/Commands/SelectPdbContextMenuEntry.cs @@ -18,12 +18,13 @@ using System.IO; using System.Linq; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; using Microsoft.Win32; namespace ICSharpCode.ILSpy { - [ExportContextMenuEntry(Header = "Select PDB...")] + [ExportContextMenuEntry(Header = nameof(Resources.SelectPDB))] class SelectPdbContextMenuEntry : IContextMenuEntry { public void Execute(TextViewContext context) @@ -32,7 +33,7 @@ namespace ICSharpCode.ILSpy if (assembly == null) return; OpenFileDialog dlg = new OpenFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(assembly.ShortName) + ".pdb"; - dlg.Filter = "Portable PDB|*.pdb|All files|*.*"; + dlg.Filter = Resources.PortablePDBPdbAllFiles; dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName); if (dlg.ShowDialog() != true) return; diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index d3c5eea8c..08ee41409 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -441,6 +441,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'. 的本地化字符串。 + /// + public static string CannotCreatePDBFile { + get { + return ResourceManager.GetString("CannotCreatePDBFile", resourceCulture); + } + } + /// /// 查找类似 Check again 的本地化字符串。 /// @@ -585,6 +594,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Decompile 的本地化字符串。 + /// + public static string Decompile { + get { + return ResourceManager.GetString("Decompile", resourceCulture); + } + } + /// /// 查找类似 Decompiler 的本地化字符串。 /// @@ -838,7 +856,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Transform to do-while, if possible. 的本地化字符串。 + /// 查找类似 Transform to do-while, if possible 的本地化字符串。 /// public static string DecompilerSettings_DoWhileStatement { get { @@ -847,7 +865,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Transform to for, if possible. 的本地化字符串。 + /// 查找类似 Transform to for, if possible 的本地化字符串。 /// public static string DecompilerSettings_ForStatement { get { @@ -1011,7 +1029,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible. 的本地化字符串。 + /// 查找类似 Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible 的本地化字符串。 /// public static string DecompilerSettings_SeparateLocalVariableDeclarations { get { @@ -1388,6 +1406,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Go to token 的本地化字符串。 + /// + public static string GoToToken { + get { + return ResourceManager.GetString("GoToToken", resourceCulture); + } + } + /// /// 查找类似 Hide empty metadata tables from tree view 的本地化字符串。 /// @@ -1695,6 +1722,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Portable PDB|*.pdb|All files|*.* 的本地化字符串。 + /// + public static string PortablePDBPdbAllFiles { + get { + return ResourceManager.GetString("PortablePDBPdbAllFiles", resourceCulture); + } + } + /// /// 查找类似 for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. 的本地化字符串。 /// @@ -1949,6 +1985,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Select PDB... 的本地化字符串。 + /// + public static string SelectPDB { + get { + return ResourceManager.GetString("SelectPDB", resourceCulture); + } + } + /// /// 查找类似 Select version of language to output 的本地化字符串。 /// @@ -2309,6 +2354,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Visual Studio Solution file|*.sln|All files|*.* 的本地化字符串。 + /// + public static string VisualStudioSolutionFileSlnAllFiles { + get { + return ResourceManager.GetString("VisualStudioSolutionFileSlnAllFiles", resourceCulture); + } + } + /// /// 查找类似 Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. 的本地化字符串。 /// @@ -2337,7 +2391,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Close all documents 的本地化字符串。 + /// 查找类似 _Close all documents 的本地化字符串。 /// public static string Window_CloseAllDocuments { get { @@ -2346,7 +2400,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Reset layout 的本地化字符串。 + /// 查找类似 _Reset layout 的本地化字符串。 /// public static string Window_ResetLayout { get { diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 5930fc5f8..67976b582 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -885,4 +885,22 @@ Do you want to continue? ILSpyAboutPage.txt + + Select PDB... + + + Portable PDB|*.pdb|All files|*.* + + + Decompile + + + Go to token + + + Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'. + + + Visual Studio Solution file|*.sln|All files|*.* + \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 36bbc1b90..cb3403087 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -885,4 +885,22 @@ 基类型 + + 无法创建为{0}创建PDB文件,因为它不包含PE调试目录类型 'CodeView'. + + + Visual Studio 解决方案文件(*.sln)|*.sln|所有文件(*.*)|*.* + + + 转至令牌 + + + 反编译 + + + 可携带 PDB(*.pdb)|*.pdb|所有文件(*.*)|*.* + + + 选择 PDB... + \ No newline at end of file From 3edc8860c873df77261d2997118f0c535db63114 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 31 Jul 2020 12:40:11 +0800 Subject: [PATCH 47/92] fix An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type --- ILSpy/Commands/GeneratePdbContextMenuEntry.cs | 6 +++--- ILSpy/Properties/Resources.Designer.cs | 18 ++++++++++++++++++ ILSpy/Properties/Resources.resx | 6 ++++++ ILSpy/Properties/Resources.zh-Hans.resx | 6 ++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index 609356f59..36330fefa 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -74,12 +74,12 @@ namespace ICSharpCode.ILSpy PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream); } catch (OperationCanceledException) { output.WriteLine(); - output.WriteLine("Generation was cancelled."); + output.WriteLine(Resources.GenerationWasCancelled); throw; } } stopwatch.Stop(); - output.WriteLine("Generation complete in " + stopwatch.Elapsed.TotalSeconds.ToString("F1") + " seconds."); + output.WriteLine(string.Format(Resources.GenerationCompleteInSeconds, stopwatch.Elapsed.TotalSeconds.ToString("F1"))); output.WriteLine(); output.AddButton(null, Resources.OpenExplorer, delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); }); output.WriteLine(); @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy } } - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = Resources.Save)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))] class GeneratePdbMainMenuEntry : SimpleCommand { public override bool CanExecute(object parameter) diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 08ee41409..62e6bfb9b 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1406,6 +1406,24 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// 查找类似 Generation complete in {0} seconds. 的本地化字符串。 + /// + public static string GenerationCompleteInSeconds { + get { + return ResourceManager.GetString("GenerationCompleteInSeconds", resourceCulture); + } + } + + /// + /// 查找类似 Generation was cancelled. 的本地化字符串。 + /// + public static string GenerationWasCancelled { + get { + return ResourceManager.GetString("GenerationWasCancelled", resourceCulture); + } + } + /// /// 查找类似 Go to token 的本地化字符串。 /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 67976b582..adb29448e 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -903,4 +903,10 @@ Do you want to continue? Visual Studio Solution file|*.sln|All files|*.* + + Generation complete in {0} seconds. + + + Generation was cancelled. + \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index cb3403087..99f0552a2 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -903,4 +903,10 @@ 选择 PDB... + + 生成已取消。 + + + 生成完成,耗时 {0} 秒. + \ No newline at end of file From d1bced7eb3b11cd8006905545b3a46cfedd3c80b Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 31 Jul 2020 13:36:40 +0800 Subject: [PATCH 48/92] fix for Berrysoft 's suggestion --- ILSpy.AddIn/zh-Hans/extension.vsixlangpack | 2 +- ILSpy/Properties/Resources.zh-Hans.resx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ILSpy.AddIn/zh-Hans/extension.vsixlangpack b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack index 2ebb0cd5a..06e466b6e 100644 --- a/ILSpy.AddIn/zh-Hans/extension.vsixlangpack +++ b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack @@ -2,6 +2,6 @@ ILSpy - 可以在Visual Studio中直接打开反编译工具ILSpy. + 可以在Visual Studio中直接打开反编译工具ILSpy。 \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 99f0552a2..2ecf5a42b 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -904,9 +904,9 @@ 选择 PDB... - 生成已取消。 + 已取消生成。 - 生成完成,耗时 {0} 秒. + 生成完成,耗时 {0} 秒。 \ No newline at end of file From 383d02611f655ae03c4cf8d18e9ee5b823ec5482 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 31 Jul 2020 09:55:14 +0200 Subject: [PATCH 49/92] Add BuildTools/sort-resx.ps1 and sort contents of resx files by key --- BuildTools/sort-resx.ps1 | 18 + ILSpy.ReadyToRun/Properties/Resources.resx | 10 +- .../Properties/Resources.zh-Hans.resx | 6 +- ILSpy/ILSpy.csproj | 9 +- ILSpy/Properties/Resources.resx | 1060 ++++++++-------- ILSpy/Properties/Resources.zh-Hans.resx | 1064 ++++++++--------- 6 files changed, 1096 insertions(+), 1071 deletions(-) create mode 100644 BuildTools/sort-resx.ps1 diff --git a/BuildTools/sort-resx.ps1 b/BuildTools/sort-resx.ps1 new file mode 100644 index 000000000..d85d46849 --- /dev/null +++ b/BuildTools/sort-resx.ps1 @@ -0,0 +1,18 @@ +$ErrorActionPreference = "Stop"; + +[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null + +Write-Host "Sorting .resx files..."; + +Get-ChildItem -Include *.resx -Recurse | foreach ($_) { + Write-Host $_.FullName; + + $doc = [System.Xml.Linq.XDocument]::Load($_.FullName); + $descendants = [System.Linq.Enumerable]::ToArray($doc.Descendants("data")); + + [System.Xml.Linq.Extensions]::Remove($descendants); + $ordered = [System.Linq.Enumerable]::OrderBy($descendants, [System.Func[System.Xml.Linq.XElement,string]] { param ($e) $e.Attribute("name").Value }, [System.StringComparer]::Ordinal); + $doc.Root.Add($ordered); + $doc.Save($_.FullName); +} + diff --git a/ILSpy.ReadyToRun/Properties/Resources.resx b/ILSpy.ReadyToRun/Properties/Resources.resx index 67b36ef54..8c6d1ce8c 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.resx @@ -117,16 +117,16 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ReadyToRun - Disassembly Format - - Show Unwind Info + + ReadyToRun Show Debug Info + + Show Unwind Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx index f13237c18..9430c8a3d 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx @@ -117,12 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ReadyToRun - 反汇编格式 + + ReadyToRun + 显示调试信息 diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index c19321de3..197bd9ed7 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -844,7 +844,14 @@ - + + + + powershell -NoProfile -ExecutionPolicy Bypass -File BuildTools/sort-resx.ps1 + + + + diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index adb29448e..32fc39d61 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -117,796 +117,796 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Navigation + + About - - Back + + Add preconfigured list... - - Forward + + Add shell integration - - _Check for Updates + + This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. + +Do you want to continue? - - _Help + + |All Files|*.* - - _File + + Allow multiple instances - - Open + + Always use braces - - DEBUG -- Disassemble All + + Analyze - - E_xit + + Assemblies - - Exit + + Assembly - - Save + + The directory is not empty. File will be overwritten. +Are you sure you want to continue? - - _Open... + + Project Directory not empty - - Open from _GAC... + + Automatically check for updates every week - - Manage assembly _lists... + + Back - - Reload all assemblies + + Base Types - - DEBUG -- Decompile All + + C_lone - - DEBUG -- Decompile 100x + + Cancel - - Generate portable PDB + + Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. - - Reload all assemblies + + Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'. - - _Reload + + Check again - - _Remove Assemblies with load errors + + Check for updates - - Remove + + Checking... - - _Save Code... + + Close - - _Show debug steps + + Collapse all tree nodes - - _View + + Copy - - Sort assembly _list by name + + Copy error message - - View + + Copy FQ Name - - Sort assembly list by name + + Create - - _Collapse all tree nodes + + Culture - - Collapse all tree nodes + + DEBUG -- Decompile All - - Name + + DEBUG -- Decompile 100x - - Value (as string) + + DEBUG -- Disassemble All - - Type + + DEBUG -- Dump PDB as XML - - String Table + + Debug Steps - - Value + + Debug this step - - Use variable names from debug symbols, if available + + Decompile - - Show info from debug symbols, if available + + Decompile to new tab - - Show XML documentation in decompiled code + + Decompiler - - Enable folding on all blocks in braces + + Allow extension 'Add' methods in collection initializer expressions - - Remove dead and side effect free code + + Use 'ref' extension methods - - Insert using declarations + + Always cast targets of explicit interface implementation calls - + + Always show enum member values + + Always use braces - - Expand member definitions after decompilation + + Apply Windows Runtime projections on loaded assemblies - - Font + + Array initializer expressions - - Other options + + Decompile async IAsyncEnumerator methods - - Show line numbers + + Decompile ?. and ?[] operators - - Show metadata tokens + + Decompile anonymous methods/lambdas - - Enable word wrap + + Decompile anonymous types - - Sort results by fitness + + Decompile async methods - - Allow multiple instances + + Decompile automatic events - - Cancel + + Decompile automatic properties - - OK + + Decompile await in catch/finally blocks - - Search + + Decompile C# 1.0 'public unsafe fixed int arr[10];' members - - Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/... + + Decompile [DecimalConstant(...)] as simple literal values - - _Search for: + + Decompile enumerators (yield return) - - Location + + Decompile expression trees - - Decompiling... + + Decompile use of the 'dynamic' type - - Copy + + Detect awaited using and foreach statements - - Editor + + Detect foreach statements - - Toggle All Folding + + Detect lock statements - - Folding + + Detect switch on string - - Resources file (*.resources)|*.resources|Resource XML file|*.resx + + Detect tuple comparisons - - _Remove + + Detect using statements - - _Load Dependencies + + Dictionary initializer expressions - - Dependencies + + Transform to do-while, if possible - - _Add To Main List + + F#-specific options - - _Open Containing Folder + + Transform to for, if possible - - Shell + + Include XML documentation comments in the decompiled code - - _Open Command Line Here + + Insert using declarations - - Copy FQ Name + + Introduce local functions - - Loading... + + Introduce static local functions - - Copy error message + + IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs - - Derived Types + + IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters - - References + + IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints - - Resources + + Use nint/nuint types - - _About + + Nullable reference types - - ILSpy version + + Object/collection initializer expressions - - Automatically check for updates every week + + Other - - Check for updates + + Ranges - - Checking... + + Read-only methods - - You are using the latest release. + + Remove dead and side effect free code (use with caution!) - - Version {0} is available. + + Remove dead stores (use with caution!) - - Download + + Remove optional arguments, if possible - - You are using a nightly build newer than the latest release. + + Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible - - Show public, private and internal + + Show info from debug symbols, if available - - Show public, private and internal + + Use discards - - Stand by... + + Use expression-bodied member syntax for get-only properties - - Status + + Use extension method syntax - - A new ILSpy version is available. + + Use implicit conversions between tuple types - - No update for ILSpy found. + + Use implicit method group conversions - - Check again + + Use LINQ expression syntax - - Searching... + + Use lambda syntax, if possible - - Search aborted, more than 1000 results found. + + Use lifted operators for nullables - - Search... + + Use named arguments - - Display Code + + Use non-trailing named arguments - - Save Code + + Use out variable declarations - - |All Files|*.* + + Use pattern-based fixed statement - - Open Explorer + + Use new SDK style format for generated project files (*.csproj) - - Select All + + Use stackalloc initializer syntax - - Toggle Folding + + Use string interpolation - - Analyze + + Use throw expressions - - Enter a list name: + + Use tuple type syntax - - Create + + Use variable names from debug symbols, if available - - New list + + VB-specific options - - Select assemblies to open: + + The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls. - - Nuget Package Browser + + Decompiling... - - Open From GAC + + Dependencies - - _Search: + + Derived Types - - Reference Name + + Display - - Version + + Display Code - - Public Key Token + + Font: - - Manage Assembly Lists + + Download - - Select a list: + + E_xit - - _New + + Editor - - _Open + + Enable folding on all blocks in braces - - _Delete + + Enable word wrap - - _Reset + + Enter a list name: - - Options + + Exit - - _Options... + + Expand member definitions after decompilation - - Display + + Expand using declarations after decompilation - - Decompiler + + Folding - - Misc + + Font - - Font: + + Forward - - Size: + + Generate portable PDB - - Debug Steps + + Generation complete in {0} seconds. - - UseFieldSugar + + Generation was cancelled. - - UseLogicOperationSugar + + Go to token - - ShowILRanges - - - ShowChildIndexInBlock - - - Show state before this step + + Hide empty metadata tables from tree view - - Show state after this step + + Highlight matching braces - - Debug this step + + ILSpyAboutPage.txt - - Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. + + ILSpy version - - Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, + + A new ILSpy version is available. - - for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. + + Indent size: - - Show assembly load log + + Indentation - - Other Resources + + Insert using declarations - - Use tabs instead of spaces + + Are you sure that you want to delete the selected assembly list? - - Show metadata tokens in base 10 + + A list with the same name was found. - - Expand using declarations after decompilation + + Are you sure that you want to remove all assembly lists and recreate the default assembly lists? Load assemblies that were loaded in the last instance. - - Indentation - - - Indent size: + + Loading... - - Tab size: + + Location - - Search (Ctrl+Shift+F or Ctrl+E) + + Manage Assembly Lists - - Show all types and members + + Manage assembly _lists... - - Other + + Misc - - Show _all types and members + + Name - - The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls. + + Navigation - - Decompile enumerators (yield return) + + Navigation failed because the target is hidden or a compiler-generated class.\n +Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again. - - Decompile anonymous methods/lambdas + + New list - - Decompile anonymous types + + New Tab - - Use lambda syntax, if possible + + Nuget Package Browser - - Decompile expression trees + + OK - - Decompile use of the 'dynamic' type + + Open - - Decompile async methods + + Open Explorer - - Decompile await in catch/finally blocks + + Open From GAC - - Decompile [DecimalConstant(...)] as simple literal values + + Open from _GAC... - - Decompile C# 1.0 'public unsafe fixed int arr[10];' members + + _Delete - - Use lifted operators for nullables + + _Open - - Decompile ?. and ?[] operators + + Options - - Decompile automatic properties + + Other - - Decompile automatic events + + Other options - - Detect using statements + + Other Resources - - Other + + Portable PDB|*.pdb|All files|*.* - - Always use braces + + for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. - - Detect foreach statements + + Public Key Token - - Detect lock statements + + R_ename - - Detect switch on string + + Reference Name - - Insert using declarations + + References - - Use extension method syntax + + Reload all assemblies - - Use LINQ expression syntax + + Reload all assemblies - - Use implicit method group conversions + + Remove - - Always cast targets of explicit interface implementation calls + + Remove dead and side effect free code - - Use variable names from debug symbols, if available + + Remove shell integration - - Array initializer expressions + + This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". + +Do you want to continue? - - Object/collection initializer expressions + + Rename list - - Dictionary initializer expressions + + Reset to defaults - - Allow extension 'Add' methods in collection initializer expressions + + Do you really want to load the default settings for the active page? - - Use string interpolation + + Resources file (*.resources)|*.resources|Resource XML file|*.resx - - Include XML documentation comments in the decompiled code + + Save - - Use expression-bodied member syntax for get-only properties + + Save Code - - Use out variable declarations + + Search... - - Use discards + + Search aborted, more than 1000 results found. - - IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs + + Search (Ctrl+Shift+F or Ctrl+E) - - IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters + + Search Microsoft Docs... - - IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints + + Search - - Use stackalloc initializer syntax + + Searching... - - Use tuple type syntax + + Select All - - Use implicit conversions between tuple types + + Select assemblies to open: - - Detect tuple comparisons + + Select a list of assemblies - - Use named arguments + + Select language to decompile to - - Use non-trailing named arguments - - - Remove optional arguments, if possible - - - Introduce local functions + + Select a list: - - Nullable reference types + + Select PDB... - - Show info from debug symbols, if available + + Select version of language to output - - VB-specific options + + Shell - - F#-specific options + + Show all types and members - - Remove dead and side effect free code (use with caution!) + + Show assembly load log - - Apply Windows Runtime projections on loaded assemblies + + ShowChildIndexInBlock - - Search Microsoft Docs... + + Show XML documentation in decompiled code - - Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. + + ShowILRanges - - Use throw expressions + + Show info from debug symbols, if available - - Use 'ref' extension methods + + Show public, private and internal - - The directory is not empty. File will be overwritten. -Are you sure you want to continue? + + Show line numbers - - Project Directory not empty + + Show metadata tokens - - Highlight matching braces + + Show metadata tokens in base 10 - - Select language to decompile to + + Show only public types and members - - Select version of language to output + + Show state after this step - - Remove dead stores (use with caution!) + + Show state before this step - - Always show enum member values + + Show _all types and members - - Show only public types and members + + Show public, private and internal Show only _public types and members - - Assembly + + Size: - - Decompile to new tab + + Sort assembly list by name - - Decompile async IAsyncEnumerator methods + + Sort assembly _list by name - - Read-only methods + + Sort results by fitness - - Detect awaited using and foreach statements + + Stand by... - - About + + Status - - Assemblies + + String Table - - _Close all documents + + Tab size: - - _Reset layout + + Toggle All Folding - - _Window + + Type - - Use pattern-based fixed statement + + No update for ILSpy found. - - Transform to do-while, if possible + + UseFieldSugar - - Transform to for, if possible + + UseLogicOperationSugar - - Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible + + Use tabs instead of spaces - - Reset to defaults + + You are using the latest release. - - Do you really want to load the default settings for the active page? + + You are using a nightly build newer than the latest release. - - Select a list of assemblies + + Value - - Close + + Value (as string) - - C_lone + + Use variable names from debug symbols, if available - - Are you sure that you want to delete the selected assembly list? + + Version - - A list with the same name was found. + + Version {0} is available. - - Are you sure that you want to remove all assembly lists and recreate the default assembly lists? + + View - - Introduce static local functions + + Visual Studio Solution file|*.sln|All files|*.* - - Hide empty metadata tables from tree view + + Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. - - Navigation failed because the target is hidden or a compiler-generated class.\n -Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again. + + Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, - - Add shell integration + + Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/... - - This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. - -Do you want to continue? + + _Close all documents - - Remove shell integration + + _Reset layout - - This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". - -Do you want to continue? + + _About - - Ranges + + _Add To Main List - - Add preconfigured list... + + _Check for Updates - - R_ename + + _Collapse all tree nodes - - Rename list + + _File - - Culture + + _Help - - New Tab + + _Load Dependencies - - Use new SDK style format for generated project files (*.csproj) + + _New - - Use nint/nuint types + + _Open... - - Base Types + + _Open Command Line Here - - DEBUG -- Dump PDB as XML + + _Open Containing Folder - - ILSpyAboutPage.txt + + _Options... - - Select PDB... + + _Reload - - Portable PDB|*.pdb|All files|*.* + + _Remove - - Decompile + + _Remove Assemblies with load errors - - Go to token + + _Reset - - Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'. + + Resources - - Visual Studio Solution file|*.sln|All files|*.* + + _Save Code... - - Generation complete in {0} seconds. + + _Search: - - Generation was cancelled. + + _Search for: + + + _Show debug steps + + + Toggle Folding + + + _View + + + _Window \ No newline at end of file diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index 2ecf5a42b..5636a202e 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -117,796 +117,796 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 导航 + + 关于 - - 后退 + + 添加预配置列表... - - 前进 + + 添加文件资源管理器集成 - - 检查更新(_C) + + 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中添加“{0}”。这样在文件资源管理器中,.dll 文件与 .exe 文件可以在右键菜单中使用 ILSpy 打开。 + +确定继续? - - 帮助(_H) + + |所有文件|*.* - - 文件(_F) + + 允许多个实例 - - 打开 + + 始终使用大括号 - - 调试 -- 全部反编译到 IL + + 分析 - - 退出(_X) + + 程序集 - - 退出 + + 程序集 - - 保存 + + 目录非空。文件会被覆盖。 +确定继续? - - 打开(_O)... + + 项目目录非空 - - 从 GAC 中打开(_G)... + + 每周自动检查更新 - - 重新加载全部程序集 + + 后退 - - 调试 -- 全部反编译到 C# + + 基类型 - - 调试 -- 反编译100次 + + 克隆(_L) - - 生成可携带 PDB + + 取消 - - 重新加载程序集 + + 无法解析实体。可能是由于缺少程序集引用。请添加缺少的程序集并重试。 - - 重新加载(_R) + + 无法创建为{0}创建PDB文件,因为它不包含PE调试目录类型 'CodeView'. - - 移除程序集及其加载错误(_R) + + 再次检查 - - 移除 + + 检查更新 - - 保存代码(_S)... + + 检查... - - 显示调试步骤(_S) + + 关闭 - - 视图(_V) + + 折叠所有树节点 - - 按名称排列程序集列表(_L) + + 复制 - - 视图 + + 复制错误信息 - - 按名称排列程序集列表 + + 复制完全限定名称 - - 折叠所有树节点(_C) + + 创建 - - 折叠所有树节点 + + 区域 - - 名称 + + 调试 -- 全部反编译到 C# - - 值(以字符串形式) + + 调试 -- 反编译100次 - - 类型 + + 调试 -- 全部反编译到 IL - - 字符串表 + + 调试 -- PDB 转储为 XML - - + + 调试步骤 - - 资源 + + 调试此步骤 - - 下载 + + 反编译 - - 检查... + + 在新选项卡反编译 - - 检查更新 + + 反编译器 - - 关于(_A) + + 在集合初始化器表达式中允许扩展 Add 方法 - - 加载中... + + 使用 ref 扩展方法 - - 引用 + + 始终强制转换显式接口实现调用的目标 - - ILSpy 版本 + + 始终显示枚举数值 - - 正在反编译... + + 始终使用大括号 - - 复制 + + 在已加载的程序集上应用 Windows 运行时投影 - - 编辑器 + + 数组初始化器表达式 - - 位置 + + 反编译异步 IAsyncEnumerator 方法 - - 搜索(_S): + + 反编译 ?. 和 ?[] 运算符 - - 移除(_R) + + 反编译匿名方法或 lambda - - 加载依赖(_L) + + 反编译匿名类型 - - 依赖(_L) + + 反编译异步方法 - - 确定 + + 反编译自动事件 - - 搜索 + + 反编译自动属性 - - 状态 + + 反编译 catch/finally 内的 await - - 字体 + + 反编译 C# 1.0“public unsafe fixed int arr[10];”成员 - - 其他选项 + + 反编译 [DecimalConstant(...)] 作为简单的文本值 - - 显示行号 + + 反编译枚举器(yield return) - - 取消 + + 反编译表达树 - - 折叠 + + 反编译使用 dynamic 类型 - - 添加到主列表(_A) + + 检测使用了 await 的 using 和 foreach 块 - - 打开包含文件夹(_O) + + 检测 foreach 语句 - - Shell + + 检测 lock 语句 - - 在这里打开命令行(_O) + + 检测 switch 的字符串 - - 复制完全限定名称 + + 检测元组比较 - - 复制错误信息 - - - 使用调试符号中的变量名称(如果可用) - - - 显示调试符号的信息(如果可用) - - - 在反编译代码中显示 XML 文档 - - - 在大括号中的所有块上启用折叠 - - - 删除死代码和无副作用的代码 - - - 插入使用声明 + + 检测 using 语句 - - 始终使用大括号 + + Dictionary 初始值设定项表达式 - - 在反编译后展开成员定义 + + 如果可能,转换到 do-while 块 - - 显示元数据标记 + + F# 特定选项 - - 启用自动换行 + + 如果可能,转换到 for 块 - - 允许多个实例 + + 在反编译代码中包括 XML 文档注释 - - 切换所有折叠 + + 插入 using 声明 - - 派生类型 + + 引入局部函数(local functions) - - 资源文件|*.resources|XML资源文件|*.resx + + 引入静态局部函数(static local functions) - - 排序结果自适应 + + IsByRefLikeAttribute 应替换为结构上的 ref 修饰符 - - 重置(_R) + + IsReadOnlyAttribute 应替为结构参数上的 readonly/in 中的修饰符 - - 删除(_D) + + 类型参数上的 IsUnmanagedAttribute 应替换为 unmanaged 约束 - - 打开(_O) + + 使用 nint/nuint 类型 - - 引用名称 + + 可空引用类型 - - 版本 + + 对象或集合初始化器表达式 - - 公钥标记 + + 其他 - - 选择一个列表: + + 范围(ranges) - - 搜索(_S): + + 只读方法 - - 从 GAC 中打开 + + 删除死代码和无副作用的代码(请谨慎使用) - - Nuget 包浏览器 + + 删除死值(请谨慎使用) - - 选择要打开的程序集: + + 如果可能,删除可选参数 - - 创建 + + 如果可能,分离局部变量的声明与初始化(int x = 5; -> int x; x = 5;) - - 输入列表名称: + + 显示调试符号中的信息(如果可用) - - 分析 + + 使用丢弃物 - - 切换折叠 + + 对仅获取属性使用表达式内部成员语法 - - 全部选择 + + 使用扩展方法语法 - - 打开资源管理器 + + 在元组类型之间使用隐式转换 - - |所有文件|*.* + + 使用隐式方法组转换 - - 保存代码 + + 使用 LINQ 表达式语法 - - 显示代码 + + 如果可能, 请使用 lambda 语法 - - 搜索... + + 对空变量使用提升运算符 - - 搜索已中止,发现超过1000个结果。 + + 使用命名参数 - - 搜索... + + 使用非尾随命名参数 - - 再次检查 + + 使用外部变量声明 - - 找不到 ILSpy 的更新。 + + 使用基于模式的 fixed 语句 - - 有新的 ILSpy 版本已经可用。 + + 使用新的 SDK 格式(*.csproj)生成项目文件 - - 就绪... + + 使用 stackalloc 初始化器语法 - - 显示内部类型和成员 + + 使用字符串插值 - - 显示内部类型和成员(_I) + + 使用 throw 表达式 - - 您使用的是每日构建版本,比最新版本更新。 + + 使用元组类型语法 - - 版本 {0} 已可用。 + + 使用调试符号中的变量名(如果可用) - - 您使用的是最新版本。 + + VB 特定选项 - - 每周自动检查更新 + + 下面选择的设置将与语言下拉列表中的选择一起应用于反编译程序输出。在下拉列表中选择较低的语言版本将停用较高版本的所有选定选项。请注意, 某些设置隐式依赖于彼此, 例如: 如果不首先将静态调用转换为扩展方法调用, 则无法引入 LINQ 表达式。 - - 搜索 t:类型、m:成员 或 c:常量;使用完全匹配(=term)、不应包含(-term)或必须包含(+term);使用 /正(则)?表达(式)?/;或同时使用二者 - t:/类(型)?/... + + 正在反编译... - - 选项 + + 依赖(_L) - - 选项(_O)... + + 派生类型 显示 - - 反编译器 - - - 杂项 + + 显示代码 字体: - - 大小: + + 下载 - - 调试步骤 + + 退出(_X) - - 使用 fld 语法糖 + + 编辑器 - - 使用 logic 语法糖 + + 在大括号中的所有块上启用折叠 - - 显示 IL 范围 + + 启用自动换行 - - 在块中显示子索引 + + 输入列表名称: - - 在此步骤之前显示状态 + + 退出 - - 在此步骤之后显示状态 + + 在反编译后展开成员定义 - - 调试此步骤 + + 反编译后展开引用和声明 - - 警告:此程序集被标记为“引用程序集”,这意味着它只包含元数据,没有可执行代码。 + + 折叠 - - 警告:某些程序集引用无法自动解析。这可能会导致某些部分反编译错误, + + 字体 - - 例如属性 getter/setter 访问。要获得最佳反编译结果,请手动将缺少的引用添加到加载的程序集列表中。 + + 前进 - - 显示程序集加载日志 + + 生成可携带 PDB - - 其他资源 + + 生成完成,耗时 {0} 秒。 - - 使用 Tab 替代空格 + + 已取消生成。 - - 使用十进制显示元数据标记 + + 转至令牌 - - 反编译后展开引用和声明 + + 在树视图中隐藏空的元数据表 - - 加载在最后一个实例中加载的程序集。 + + 高亮配对的大括号 - - 缩进 + + ILSpyAboutPage_zh_Hans.txt + + + ILSpy 版本 + + + 有新的 ILSpy 版本已经可用。 缩进长度: - - Tab 长度: - - - 搜索(Ctrl + Shift + F 或 Ctrl + E) + + 缩进 - - 显示所有类型和成员 + + 插入使用声明 - - 其他 + + 是否删除选中的程序集列表? - - 显示所有类型和成员(_A) + + 已有同名的列表。 - - 下面选择的设置将与语言下拉列表中的选择一起应用于反编译程序输出。在下拉列表中选择较低的语言版本将停用较高版本的所有选定选项。请注意, 某些设置隐式依赖于彼此, 例如: 如果不首先将静态调用转换为扩展方法调用, 则无法引入 LINQ 表达式。 + + 是否删除所有程序集列表,并重建默认程序集列表? - - 反编译枚举器(yield return) + + 加载在最后一个实例中加载的程序集。 - - 反编译匿名方法或 lambda + + 加载中... - - 反编译匿名类型 + + 位置 - - 如果可能, 请使用 lambda 语法 + + 管理程序集列表 - - 反编译表达树 + + 管理程序集列表(_L)... - - 反编译使用 dynamic 类型 + + 杂项 - - 反编译异步方法 + + 名称 - - 反编译 catch/finally 内的 await + + 导航 - - 反编译 [DecimalConstant(...)] 作为简单的文本值 + + 导航失败,因为目标是隐藏的或编译器生成的类。\n +请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 - - 反编译 C# 1.0“public unsafe fixed int arr[10];”成员 + + 新建列表 - - 对空变量使用提升运算符 + + 新选项卡 - - 反编译 ?. 和 ?[] 运算符 + + Nuget 包浏览器 - - 反编译自动属性 + + 确定 - - 反编译自动事件 + + 打开 - - 检测 using 语句 + + 打开资源管理器 - - 其他 + + 从 GAC 中打开 - - 始终使用大括号 + + 从 GAC 中打开(_G)... - - 检测 foreach 语句 + + 删除(_D) - - 检测 lock 语句 + + 打开(_O) - - 检测 switch 的字符串 + + 选项 - - 插入 using 声明 + + 其他 - - 使用扩展方法语法 + + 其他选项 - - 使用 LINQ 表达式语法 + + 其他资源 - - 使用隐式方法组转换 + + 可携带 PDB(*.pdb)|*.pdb|所有文件(*.*)|*.* - - 始终强制转换显式接口实现调用的目标 + + 例如属性 getter/setter 访问。要获得最佳反编译结果,请手动将缺少的引用添加到加载的程序集列表中。 - - 使用调试符号中的变量名(如果可用) + + 公钥标记 - - 数组初始化器表达式 + + 重命名(_E) - - 对象或集合初始化器表达式 + + 引用名称 - - Dictionary 初始值设定项表达式 + + 引用 - - 在集合初始化器表达式中允许扩展 Add 方法 + + 重新加载程序集 - - 使用字符串插值 + + 重新加载全部程序集 - - 在反编译代码中包括 XML 文档注释 + + 移除 - - 对仅获取属性使用表达式内部成员语法 + + 删除死代码和无副作用的代码 - - 使用外部变量声明 + + 移除文件资源管理器集成 - - 使用丢弃物 + + 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中移除“{0}”。 + +确定继续? - - IsByRefLikeAttribute 应替换为结构上的 ref 修饰符 + + 重命名列表 - - IsReadOnlyAttribute 应替为结构参数上的 readonly/in 中的修饰符 + + 还原到默认值 - - 类型参数上的 IsUnmanagedAttribute 应替换为 unmanaged 约束 + + 是否为活动页面加载默认值? - - 使用 stackalloc 初始化器语法 + + 资源文件|*.resources|XML资源文件|*.resx - - 使用元组类型语法 + + 保存 - - 在元组类型之间使用隐式转换 + + 保存代码 - - 检测元组比较 + + 搜索... - - 使用命名参数 + + 搜索已中止,发现超过1000个结果。 - - 使用非尾随命名参数 + + 搜索(Ctrl + Shift + F 或 Ctrl + E) - - 如果可能,删除可选参数 + + 搜索 Microsoft Docs... - - 引入局部函数(local functions) + + 搜索 - - 可空引用类型 + + 搜索... - - 显示调试符号中的信息(如果可用) + + 全部选择 - - VB 特定选项 + + 选择要打开的程序集: - - F# 特定选项 + + 选择一个程序集列表 - - 删除死代码和无副作用的代码(请谨慎使用) + + 选择一个反编译目标语言 - - 在已加载的程序集上应用 Windows 运行时投影 + + 选择一个列表: - - 搜索 Microsoft Docs... + + 选择 PDB... - - 关于 + + 选择输出语言的版本 - - 使用新的 SDK 格式(*.csproj)生成项目文件 + + Shell - - 新建(_N) + + 显示所有类型和成员 - - 窗口(_W) + + 显示程序集加载日志 - - 添加预配置列表... + + 在块中显示子索引 - - 添加文件资源管理器集成 + + 在反编译代码中显示 XML 文档 - - 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中添加“{0}”。这样在文件资源管理器中,.dll 文件与 .exe 文件可以在右键菜单中使用 ILSpy 打开。 - -确定继续? + + 显示 IL 范围 - - 程序集 + + 显示调试符号的信息(如果可用) - - 程序集 + + 显示内部类型和成员 - - 目录非空。文件会被覆盖。 -确定继续? + + 显示行号 - - 项目目录非空 + + 显示元数据标记 - - 克隆(_L) + + 使用十进制显示元数据标记 - - 区域 + + 只显示公有类型和成员 - - 关闭 + + 在此步骤之后显示状态 - - 无法解析实体。可能是由于缺少程序集引用。请添加缺少的程序集并重试。 + + 在此步骤之前显示状态 - - 使用 ref 扩展方法 + + 显示所有类型和成员(_A) - - 始终显示枚举数值 + + 显示内部类型和成员(_I) - - 反编译异步 IAsyncEnumerator 方法 + + 只显示公有类型和成员(_P) - - 检测使用了 await 的 using 和 foreach 块 + + 大小: - - 如果可能,转换到 do-while 块 + + 按名称排列程序集列表 - - 如果可能,转换到 for 块 + + 按名称排列程序集列表(_L) - - 引入静态局部函数(static local functions) + + 排序结果自适应 - - 范围(ranges) + + 就绪... - - 只读方法 + + 状态 - - 删除死值(请谨慎使用) + + 字符串表 - - 如果可能,分离局部变量的声明与初始化(int x = 5; -> int x; x = 5;) + + Tab 长度: - - 使用基于模式的 fixed 语句 + + 切换所有折叠 - - 使用 throw 表达式 + + 类型 - - 在新选项卡反编译 + + 找不到 ILSpy 的更新。 - - 在树视图中隐藏空的元数据表 + + 使用 fld 语法糖 - - 高亮配对的大括号 + + 使用 logic 语法糖 - - 重置布局(_R) + + 使用 Tab 替代空格 - - 关闭所有文档(_C) + + 您使用的是最新版本。 - - 只显示公有类型和成员 + + 您使用的是每日构建版本,比最新版本更新。 - - 只显示公有类型和成员(_P) + + - - 选择输出语言的版本 + + 值(以字符串形式) - - 选择一个程序集列表 + + 使用调试符号中的变量名称(如果可用) - - 选择一个反编译目标语言 + + 版本 - - 重命名列表 + + 版本 {0} 已可用。 - - 还原到默认值 + + 视图 - - 这会在注册表的“HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command”与“HKCU\Software\Classes\exefile\shell\Open with ILSpy\command”中移除“{0}”。 - -确定继续? + + Visual Studio 解决方案文件(*.sln)|*.sln|所有文件(*.*)|*.* - - 移除文件资源管理器集成 + + 警告:此程序集被标记为“引用程序集”,这意味着它只包含元数据,没有可执行代码。 - - 是否为活动页面加载默认值? + + 警告:某些程序集引用无法自动解析。这可能会导致某些部分反编译错误, - - 重命名(_E) + + 搜索 t:类型、m:成员 或 c:常量;使用完全匹配(=term)、不应包含(-term)或必须包含(+term);使用 /正(则)?表达(式)?/;或同时使用二者 - t:/类(型)?/... - - 新建列表 + + 关闭所有文档(_C) - - 新选项卡 + + 重置布局(_R) - - 管理程序集列表(_L)... + + 关于(_A) - - 管理程序集列表 + + 添加到主列表(_A) - - 导航失败,因为目标是隐藏的或编译器生成的类。\n -请禁用所有的、可能隐藏它们的筛选器(例如,启用“视图 > 显示内部类型和成员”),并重试。 + + 检查更新(_C) - - 是否删除选中的程序集列表? + + 折叠所有树节点(_C) - - 已有同名的列表。 + + 文件(_F) - - 是否删除所有程序集列表,并重建默认程序集列表? + + 帮助(_H) - - ILSpyAboutPage_zh_Hans.txt + + 加载依赖(_L) - - 调试 -- PDB 转储为 XML + + 新建(_N) - - 使用 nint/nuint 类型 + + 打开(_O)... - - 基类型 + + 在这里打开命令行(_O) - - 无法创建为{0}创建PDB文件,因为它不包含PE调试目录类型 'CodeView'. + + 打开包含文件夹(_O) - - Visual Studio 解决方案文件(*.sln)|*.sln|所有文件(*.*)|*.* + + 选项(_O)... - - 转至令牌 + + 重新加载(_R) - - 反编译 + + 移除(_R) - - 可携带 PDB(*.pdb)|*.pdb|所有文件(*.*)|*.* + + 移除程序集及其加载错误(_R) - - 选择 PDB... + + 重置(_R) - - 已取消生成。 + + 资源 - - 生成完成,耗时 {0} 秒。 + + 保存代码(_S)... + + + 搜索(_S): + + + 搜索(_S): + + + 显示调试步骤(_S) + + + 切换折叠 + + + 视图(_V) + + + 窗口(_W) \ No newline at end of file From bb39fe9f87eb15fff0232dac01dd608bc1151ba3 Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Fri, 31 Jul 2020 18:07:36 +0800 Subject: [PATCH 50/92] =?UTF-8?q?fix=20=20for=20Berrysoft=E2=80=98s=20sugg?= =?UTF-8?q?estion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct | 6 ++-- ILSpy.AddIn/VSPackage.zh-Hans.resx | 2 +- ILSpy.AddIn/zh-Hans/extension.vsixlangpack | 2 +- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 3 +- ILSpy.ReadyToRun/Properties/AssemblyInfo.cs | 31 +++------------------ ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 3 +- 6 files changed, 12 insertions(+), 35 deletions(-) diff --git a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct index f84717c94..d50bfb062 100644 --- a/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct +++ b/ILSpy.AddIn/ILSpyAddIn.zh-Hans.vsct @@ -53,7 +53,7 @@ DynamicVisibility DefaultInvisible - 用ILSpy打开 + 用 ILSpy 打开 @@ -63,7 +63,7 @@ DynamicVisibility DefaultInvisible - 用ILSpy打开输出 + 用 ILSpy 打开输出 @@ -73,7 +73,7 @@ DynamicVisibility DefaultInvisible - 用ILSpy打开代码 + 用 ILSpy 打开代码 diff --git a/ILSpy.AddIn/VSPackage.zh-Hans.resx b/ILSpy.AddIn/VSPackage.zh-Hans.resx index 73c158134..db43f348a 100644 --- a/ILSpy.AddIn/VSPackage.zh-Hans.resx +++ b/ILSpy.AddIn/VSPackage.zh-Hans.resx @@ -121,6 +121,6 @@ ILSpy.AddIn - Integration of the ILSpy Decompiler into Visual Studio. + 可以在 Visual Studio 中直接打开反编译工具 ILSpy 。 \ No newline at end of file diff --git a/ILSpy.AddIn/zh-Hans/extension.vsixlangpack b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack index 06e466b6e..c650a50a2 100644 --- a/ILSpy.AddIn/zh-Hans/extension.vsixlangpack +++ b/ILSpy.AddIn/zh-Hans/extension.vsixlangpack @@ -2,6 +2,6 @@ ILSpy - 可以在Visual Studio中直接打开反编译工具ILSpy。 + 可以在 Visual Studio 中直接打开反编译工具 ILSpy 。 \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index 77203a458..878beb5d6 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -7,7 +7,7 @@ 8.0 False - + en-US false true false @@ -46,6 +46,7 @@ + True True diff --git a/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs b/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs index 85918694e..cd1bac780 100644 --- a/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs +++ b/ILSpy.ReadyToRun/Properties/AssemblyInfo.cs @@ -1,33 +1,10 @@ -#region Using directives - +using System; using System.Reflection; -using System.Runtime.InteropServices; +using System.Resources; using System.Runtime.CompilerServices; - -#endregion +using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("ILSpy.ReadyToRun.Plugin")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ILSpy.ReadyToRun.Plugin")] -[assembly: AssemblyCopyright("Copyright 2011")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -[assembly: InternalsVisibleTo("ILSpy.ReadyToRun.Tests")] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index b244a5b43..2bfb3bccf 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -27,7 +27,6 @@ using System.Reflection.PortableExecutable; using System.Resources; using System.Runtime.CompilerServices; using Iced.Intel; - using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.IL; @@ -36,7 +35,7 @@ using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ILCompiler.Reflection.ReadyToRun; using ILCompiler.Reflection.ReadyToRun.Amd64; -[assembly: NeutralResourcesLanguage("en-US")] + namespace ICSharpCode.ILSpy.ReadyToRun { [Export(typeof(Language))] From abb9d49a0fcdb9c82be047ef2e707060e48ac19c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 2 Aug 2020 11:57:33 +0200 Subject: [PATCH 51/92] Add support for C# 8 switch expressions. --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../ILPrettyTestRunner.cs | 4 +- .../PrettyTestRunner.cs | 9 +- .../TestCases/Pretty/SwitchExpressions.cs | 143 +++++++++++++++ .../CSharp/ExpressionBuilder.cs | 50 ++++++ .../OutputVisitor/CSharpOutputVisitor.cs | 27 +++ .../OutputVisitor/InsertParenthesesVisitor.cs | 9 + .../CSharp/StatementBuilder.cs | 14 +- .../CSharp/Syntax/DepthFirstAstVisitor.cs | 36 +++- .../Syntax/Expressions/SwitchExpression.cs | 118 +++++++++++++ .../CSharp/Syntax/IAstVisitor.cs | 6 + ICSharpCode.Decompiler/DecompilerSettings.cs | 20 ++- .../ICSharpCode.Decompiler.csproj | 1 + ICSharpCode.Decompiler/IL/Instructions.cs | 2 +- ICSharpCode.Decompiler/IL/Instructions.tt | 2 +- .../IL/Instructions/SwitchInstruction.cs | 24 ++- .../IL/Transforms/ExpressionTransforms.cs | 167 +++++++++++++----- 17 files changed, 569 insertions(+), 64 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs create mode 100644 ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index c8e8d2721..915b06889 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -92,6 +92,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs index d9a9e2ede..cd864eab9 100644 --- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs @@ -127,13 +127,13 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void CS1xSwitch_Debug() { - Run(); + Run(settings: new DecompilerSettings { SwitchExpressions = false }); } [Test] public void CS1xSwitch_Release() { - Run(); + Run(settings: new DecompilerSettings { SwitchExpressions = false }); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index b657ad839..ceeae1d1a 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -135,10 +135,17 @@ namespace ICSharpCode.Decompiler.Tests { RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings { // legacy csc generates a dead store in debug builds - RemoveDeadStores = (cscOptions == CompilerOptions.None) + RemoveDeadStores = (cscOptions == CompilerOptions.None), + SwitchExpressions = false, }); } + [Test] + public void SwitchExpressions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions) + { + RunForLibrary(cscOptions: cscOptions); + } + [Test] public void ReduceNesting([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs new file mode 100644 index 000000000..321e456c5 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs @@ -0,0 +1,143 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + public static class SwitchExpressions + { + public enum State + { + False, + True, + Null + } + + public static bool? SwitchOverNullableEnum(State? state) + { + return state switch { + State.False => false, + State.True => true, + State.Null => null, + _ => throw new InvalidOperationException(), + }; + } + + public static string SparseIntegerSwitch(int i) + { + Console.WriteLine("SparseIntegerSwitch: " + i); + return i switch { + -10000000 => "-10 mln", + -100 => "-hundred", + -1 => "-1", + 0 => "0", + 1 => "1", + 2 => "2", + 4 => "4", + 100 => "hundred", + 10000 => "ten thousand", + 10001 => "ten thousand and one", + int.MaxValue => "int.MaxValue", + _ => "something else", + }; + } + + public static bool SparseIntegerSwitch3(int i) + { + // not using a switch expression because we'd have to duplicate the 'true' branch + switch (i) { + case 0: + case 10: + case 11: + case 12: + case 100: + case 101: + case 200: + return true; + default: + return false; + } + } + + public static string SwitchOverNullableInt(int? i) + { + return i switch { + null => "null", + 0 => "zero", + 5 => "five", + 10 => "ten", + _ => "large", + }; + } + + public static void SwitchOverInt(int i) + { + Console.WriteLine(i switch { + 0 => "zero", + 5 => "five", + 10 => "ten", + 15 => "fifteen", + 20 => "twenty", + 25 => "twenty-five", + 30 => "thirty", + _ => throw new NotImplementedException(), + }); + } + + public static string SwitchOverString1(string text) + { + Console.WriteLine("SwitchOverString1: " + text); + return text switch { + "First case" => "Text1", + "Second case" => "Text2", + "Third case" => "Text3", + "Fourth case" => "Text4", + "Fifth case" => "Text5", + "Sixth case" => "Text6", + null => null, + _ => "Default", + }; + } + + public static string SwitchOverString2(string text) + { + Console.WriteLine("SwitchOverString1: " + text); + // Cannot use switch expression, because "return Text2;" would need to be duplicated + switch (text) { + case "First case": + return "Text1"; + case "Second case": + case "2nd case": + return "Text2"; + case "Third case": + return "Text3"; + case "Fourth case": + return "Text4"; + case "Fifth case": + return "Text5"; + case "Sixth case": + return "Text6"; + case null: + return null; + default: + return "Default"; + } + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 140329dcd..ee0d112dc 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2920,6 +2920,56 @@ namespace ICSharpCode.Decompiler.CSharp } } + protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) + { + TranslatedExpression value; + if (inst.Value is StringToInt strToInt) { + value = Translate(strToInt.Argument); + } else { + strToInt = null; + value = Translate(inst.Value); + } + + IL.SwitchSection defaultSection = inst.GetDefaultSection(); + SwitchExpression switchExpr = new SwitchExpression(); + switchExpr.Expression = value; + IType resultType; + if (context.TypeHint.Kind != TypeKind.Unknown && context.TypeHint.GetStackType() == inst.ResultType) { + resultType = context.TypeHint; + } else { + resultType = compilation.FindType(inst.ResultType.ToKnownTypeCode()); + } + + foreach (var section in inst.Sections) { + if (section == defaultSection) + continue; + var ses = new SwitchExpressionSection(); + if (section.HasNullLabel) { + Debug.Assert(section.Labels.IsEmpty); + ses.Pattern = new NullReferenceExpression(); + } else { + long val = section.Labels.Values.Single(); + var rr = statementBuilder.CreateTypedCaseLabel(val, value.Type, strToInt?.Map).Single(); + ses.Pattern = astBuilder.ConvertConstantValue(rr); + } + ses.Body = TranslateSectionBody(section); + switchExpr.SwitchSections.Add(ses); + } + + var defaultSES = new SwitchExpressionSection(); + defaultSES.Pattern = new IdentifierExpression("_"); + defaultSES.Body = TranslateSectionBody(defaultSection); + switchExpr.SwitchSections.Add(defaultSES); + + return switchExpr.WithILInstruction(inst).WithRR(new ResolveResult(resultType)); + + Expression TranslateSectionBody(IL.SwitchSection section) + { + var body = Translate(section.Body, resultType); + return body.ConvertTo(resultType, this, allowImplicitConversion: true); + } + } + protected internal override TranslatedExpression VisitAddressOf(AddressOf inst, TranslationContext context) { // HACK: this is only correct if the argument is an R-value; otherwise we're missing the copy to the temporary diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 1fc2b44bd..1f3b9dc2d 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1759,6 +1759,33 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor EndNode(caseLabel); } + public virtual void VisitSwitchExpression(SwitchExpression switchExpression) + { + StartNode(switchExpression); + switchExpression.Expression.AcceptVisitor(this); + Space(); + WriteKeyword(SwitchExpression.SwitchKeywordRole); + OpenBrace(BraceStyle.EndOfLine); + foreach (AstNode node in switchExpression.SwitchSections) { + node.AcceptVisitor(this); + Comma(node); + NewLine(); + } + CloseBrace(BraceStyle.EndOfLine); + EndNode(switchExpression); + } + + public virtual void VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection) + { + StartNode(switchExpressionSection); + switchExpressionSection.Pattern.AcceptVisitor(this); + Space(); + WriteToken(Roles.Arrow); + Space(); + switchExpressionSection.Body.AcceptVisitor(this); + EndNode(switchExpressionSection); + } + public virtual void VisitThrowStatement(ThrowStatement throwStatement) { StartNode(throwStatement); diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs index 4791b3127..b4a235b97 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -52,6 +52,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Shift, // << >> Additive, // binary + - Multiplicative, // * / % + Switch, // C# 8 switch expression Range, // .. Unary, QueryOrLambda, @@ -145,6 +146,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return PrecedenceLevel.Conditional; if (expr is AssignmentExpression || expr is LambdaExpression) return PrecedenceLevel.Assignment; + if (expr is SwitchExpression) + return PrecedenceLevel.Switch; // anything else: primary expression return PrecedenceLevel.Primary; } @@ -414,5 +417,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } base.VisitNamedExpression (namedExpression); } + + public override void VisitSwitchExpression(SwitchExpression switchExpression) + { + ParenthesizeIfRequired(switchExpression.Expression, PrecedenceLevel.Switch + 1); + base.VisitSwitchExpression(switchExpression); + } } } diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 052ab9a59..a935bfb99 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -120,7 +120,7 @@ namespace ICSharpCode.Decompiler.CSharp return new IfElseStatement(condition, trueStatement, falseStatement).WithILInstruction(inst); } - IEnumerable CreateTypedCaseLabel(long i, IType type, List<(string Key, int Value)> map = null) + internal IEnumerable CreateTypedCaseLabel(long i, IType type, List<(string Key, int Value)> map = null) { object value; // unpack nullable type, if necessary: @@ -165,20 +165,14 @@ namespace ICSharpCode.Decompiler.CSharp caseLabelMapping = new Dictionary(); TranslatedExpression value; - var strToInt = inst.Value as StringToInt; - if (strToInt != null) { + if (inst.Value is StringToInt strToInt) { value = exprBuilder.Translate(strToInt.Argument); } else { + strToInt = null; value = exprBuilder.Translate(inst.Value); } - // Pick the section with the most labels as default section. - IL.SwitchSection defaultSection = inst.Sections.First(); - foreach (var section in inst.Sections) { - if (section.Labels.Count() > defaultSection.Labels.Count()) { - defaultSection = section; - } - } + IL.SwitchSection defaultSection = inst.GetDefaultSection(); var stmt = new SwitchStatement() { Expression = value }; Dictionary translationDictionary = new Dictionary(); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs index 5d6b71a8b..f543cf611 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs @@ -345,7 +345,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { VisitChildren (caseLabel); } - + + public virtual void VisitSwitchExpression(SwitchExpression switchExpression) + { + VisitChildren(switchExpression); + } + + public virtual void VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection) + { + VisitChildren(switchExpressionSection); + } + public virtual void VisitThrowStatement (ThrowStatement throwStatement) { VisitChildren (throwStatement); @@ -987,7 +997,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return VisitChildren (caseLabel); } - + + public virtual T VisitSwitchExpression(SwitchExpression switchExpression) + { + return VisitChildren(switchExpression); + } + + public virtual T VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection) + { + return VisitChildren(switchExpressionSection); + } + public virtual T VisitThrowStatement (ThrowStatement throwStatement) { return VisitChildren (throwStatement); @@ -1629,7 +1649,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return VisitChildren (caseLabel, data); } - + + public virtual S VisitSwitchExpression(SwitchExpression switchExpression, T data) + { + return VisitChildren(switchExpression, data); + } + + public virtual S VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection, T data) + { + return VisitChildren(switchExpressionSection, data); + } + public virtual S VisitThrowStatement (ThrowStatement throwStatement, T data) { return VisitChildren (throwStatement, data); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs new file mode 100644 index 000000000..9c9e166d6 --- /dev/null +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2020 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// 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. + + +namespace ICSharpCode.Decompiler.CSharp.Syntax +{ + /// + /// Expression switch { SwitchSections } + /// + public class SwitchExpression : Expression + { + public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); + public static readonly Role SwitchSectionRole = new Role("SwitchSection"); + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public CSharpTokenNode SwitchToken { + get { return GetChildByRole(SwitchKeywordRole); } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole(Roles.LBrace); } + } + + public AstNodeCollection SwitchSections { + get { return GetChildrenByRole(SwitchSectionRole); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole(Roles.RBrace); } + } + + public override void AcceptVisitor(IAstVisitor visitor) + { + visitor.VisitSwitchExpression(this); + } + + public override T AcceptVisitor(IAstVisitor visitor) + { + return visitor.VisitSwitchExpression(this); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSwitchExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SwitchExpression o = other as SwitchExpression; + return o != null && this.Expression.DoMatch(o.Expression, match) && this.SwitchSections.DoMatch(o.SwitchSections, match); + } + } + + /// + /// Pattern => Expression + /// + public class SwitchExpressionSection : AstNode + { + public static readonly Role PatternRole = new Role("Pattern", Expression.Null); + public static readonly Role BodyRole = new Role("Body", Expression.Null); + + public Expression Pattern { + get { return GetChildByRole(PatternRole); } + set { SetChildByRole(PatternRole, value); } + } + + public CSharpTokenNode ArrowToken { + get { return GetChildByRole(Roles.Arrow); } + } + + public Expression Body { + get { return GetChildByRole(BodyRole); } + set { SetChildByRole(BodyRole, value); } + } + + public override NodeType NodeType => NodeType.Unknown; + + public override void AcceptVisitor(IAstVisitor visitor) + { + visitor.VisitSwitchExpressionSection(this); + } + + public override T AcceptVisitor(IAstVisitor visitor) + { + return visitor.VisitSwitchExpressionSection(this); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSwitchExpressionSection(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SwitchExpressionSection o = other as SwitchExpressionSection; + return o != null && this.Pattern.DoMatch(o.Pattern, match) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs index 90d8371ca..ef73b991d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs @@ -103,6 +103,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitSwitchStatement(SwitchStatement switchStatement); void VisitSwitchSection(SwitchSection switchSection); void VisitCaseLabel(CaseLabel caseLabel); + void VisitSwitchExpression(SwitchExpression switchExpression); + void VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection); void VisitThrowStatement(ThrowStatement throwStatement); void VisitTryCatchStatement(TryCatchStatement tryCatchStatement); void VisitCatchClause(CatchClause catchClause); @@ -243,6 +245,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitSwitchStatement(SwitchStatement switchStatement); S VisitSwitchSection(SwitchSection switchSection); S VisitCaseLabel(CaseLabel caseLabel); + S VisitSwitchExpression(SwitchExpression switchExpression); + S VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection); S VisitThrowStatement(ThrowStatement throwStatement); S VisitTryCatchStatement(TryCatchStatement tryCatchStatement); S VisitCatchClause(CatchClause catchClause); @@ -383,6 +387,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitSwitchStatement(SwitchStatement switchStatement, T data); S VisitSwitchSection(SwitchSection switchSection, T data); S VisitCaseLabel(CaseLabel caseLabel, T data); + S VisitSwitchExpression(SwitchExpression switchExpression, T data); + S VisitSwitchExpressionSection(SwitchExpressionSection switchExpressionSection, T data); S VisitThrowStatement(ThrowStatement throwStatement, T data); S VisitTryCatchStatement(TryCatchStatement tryCatchStatement, T data); S VisitCatchClause(CatchClause catchClause, T data); diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 26bd075b0..41dbedea1 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -113,6 +113,7 @@ namespace ICSharpCode.Decompiler asyncEnumerator = false; staticLocalFunctions = false; ranges = false; + switchExpressions = false; } if (languageVersion < CSharp.LanguageVersion.Preview) { nativeIntegers = false; @@ -124,7 +125,7 @@ namespace ICSharpCode.Decompiler { if (nativeIntegers || initAccessors) return CSharp.LanguageVersion.Preview; - if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement || staticLocalFunctions || ranges) + if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement || staticLocalFunctions || ranges || switchExpressions) return CSharp.LanguageVersion.CSharp8_0; if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers || patternBasedFixedStatement) return CSharp.LanguageVersion.CSharp7_3; @@ -181,6 +182,23 @@ namespace ICSharpCode.Decompiler } } + bool switchExpressions = true; + + /// + /// Use C# 8 switch expressions. + /// + [Category("C# 8.0 / VS 2019")] + [Description("DecompilerSettings.SwitchExpressions")] + public bool SwitchExpressions { + get { return switchExpressions; } + set { + if (switchExpressions != value) { + switchExpressions = value; + OnPropertyChanged(); + } + } + } + bool anonymousMethods = true; /// diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index a00763439..e10626114 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -70,6 +70,7 @@ + diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index cd420c1e7..1de9d1fc8 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -1497,7 +1497,7 @@ namespace ICSharpCode.Decompiler.IL /// Switch statement public sealed partial class SwitchInstruction : ILInstruction { - public override StackType ResultType { get { return StackType.Void; } } + public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitSwitchInstruction(this); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 2e3e35d83..b288ed9b2 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -116,7 +116,7 @@ new ChildInfo("fallbackInst"), }), CustomConstructor, CustomComputeFlags, CustomWriteTo), new OpCode("switch", "Switch statement", - CustomClassName("SwitchInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo, ResultType("Void"), + CustomClassName("SwitchInstruction"), CustomConstructor, CustomComputeFlags, CustomWriteTo, MatchCondition("IsLifted == o.IsLifted && Value.PerformMatch(o.Value, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match)")), new OpCode("switch.section", "Switch section within a switch statement", CustomClassName("SwitchSection"), CustomChildren(new [] { new ChildInfo("body") }), diff --git a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs index 6faacc0a0..63924b18e 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs @@ -130,7 +130,16 @@ namespace ICSharpCode.Decompiler.IL clone.Sections.AddRange(this.Sections.Select(h => (SwitchSection)h.Clone())); return clone; } - + + StackType resultType = StackType.Void; + + public override StackType ResultType => resultType; + + public void SetResultType(StackType resultType) + { + this.resultType = resultType; + } + internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); @@ -143,12 +152,25 @@ namespace ICSharpCode.Decompiler.IL } Debug.Assert(!section.Labels.IsEmpty || section.HasNullLabel); Debug.Assert(!section.Labels.Overlaps(sets)); + Debug.Assert(section.Body.ResultType == this.ResultType); sets = sets.UnionWith(section.Labels); } Debug.Assert(sets.SetEquals(LongSet.Universe), "switch does not handle all possible cases"); Debug.Assert(!expectNullSection, "Lifted switch is missing 'case null'"); Debug.Assert(this.IsLifted ? (value.ResultType == StackType.O) : (value.ResultType == StackType.I4 || value.ResultType == StackType.I8)); } + + public SwitchSection GetDefaultSection() + { + // Pick the section with the most labels as default section. + IL.SwitchSection defaultSection = Sections.First(); + foreach (var section in Sections) { + if (section.Labels.Count() > defaultSection.Labels.Count()) { + defaultSection = section; + } + } + return defaultSection; + } } partial class SwitchSection diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 97c17d1a8..cc4ec940a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -65,8 +65,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (container.Kind == ContainerKind.Switch) { // Special case for switch: Only visit the switch condition block. - var switchInst = (SwitchInstruction)container.EntryPoint.Instructions[0]; + var switchInst = (SwitchInstruction)container.EntryPoint.Instructions[0]; switchInst.Value.AcceptVisitor(this); + + HandleSwitchExpression(container, switchInst); } // No need to call base.VisitBlockContainer, see comment in VisitBlock. } @@ -121,12 +123,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms inst.Kind = ComparisonKind.Equality; } } - + var rightWithoutConv = inst.Right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend); if (rightWithoutConv.MatchLdcI4(0) - && inst.Sign == Sign.Unsigned - && (inst.Kind == ComparisonKind.GreaterThan || inst.Kind == ComparisonKind.LessThanOrEqual)) - { + && inst.Sign == Sign.Unsigned + && (inst.Kind == ComparisonKind.GreaterThan || inst.Kind == ComparisonKind.LessThanOrEqual)) { if (inst.Kind == ComparisonKind.GreaterThan) { context.Step("comp.unsigned(left > ldc.i4 0) => comp(left != ldc.i4 0)", inst); inst.Kind = ComparisonKind.Inequality; @@ -169,21 +170,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } } - + protected internal override void VisitConv(Conv inst) { inst.Argument.AcceptVisitor(this); if (inst.Argument.MatchLdLen(StackType.I, out ILInstruction array) && inst.TargetType.IsIntegerType() - && (!inst.CheckForOverflow || context.Settings.AssumeArrayLengthFitsIntoInt32)) - { + && (!inst.CheckForOverflow || context.Settings.AssumeArrayLengthFitsIntoInt32)) { context.Step("conv.i4(ldlen array) => ldlen.i4(array)", inst); inst.AddILRange(inst.Argument); inst.ReplaceWith(new LdLen(inst.TargetType.GetStackType(), array).WithILRange(inst)); return; } - if (inst.TargetType.IsFloatType() && inst.Argument is Conv conv - && conv.Kind == ConversionKind.IntToFloat && conv.TargetType == PrimitiveType.R) - { + if (inst.TargetType.IsFloatType() && inst.Argument is Conv conv + && conv.Kind == ConversionKind.IntToFloat && conv.TargetType == PrimitiveType.R) { // IL conv.r.un does not indicate whether to convert the target type to R4 or R8, // so the C# compiler usually follows it with an explicit conv.r4 or conv.r8. // To avoid emitting '(float)(double)val', we combine these two conversions: @@ -270,7 +269,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms arg.AcceptVisitor(this); } } - + protected internal override void VisitCall(Call inst) { var expr = EarlyExpressionTransforms.HandleCall(inst, context); @@ -430,9 +429,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else if (args.Count == 5) { int lo, mid, hi, isNegative, scale; if (args[0].MatchLdcI4(out lo) && args[1].MatchLdcI4(out mid) && - args[2].MatchLdcI4(out hi) && args[3].MatchLdcI4(out isNegative) && - args[4].MatchLdcI4(out scale)) - { + args[2].MatchLdcI4(out hi) && args[3].MatchLdcI4(out isNegative) && + args[4].MatchLdcI4(out scale)) { result = new LdcDecimal(new decimal(lo, mid, hi, isNegative != 0, (byte)scale)); return true; } @@ -501,8 +499,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Be careful: when both LHS and RHS are the constant 1, we must not // swap the arguments as it would lead to an infinite transform loop. if (inst.TrueInst.MatchLdcI4(0) && !inst.FalseInst.MatchLdcI4(0) - || inst.FalseInst.MatchLdcI4(1) && !inst.TrueInst.MatchLdcI4(1)) - { + || inst.FalseInst.MatchLdcI4(1) && !inst.TrueInst.MatchLdcI4(1)) { context.Step("canonicalize logic and/or", inst); var t = inst.TrueInst; inst.TrueInst = inst.FalseInst; @@ -531,6 +528,112 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } + IfInstruction HandleConditionalOperator(IfInstruction inst) + { + // if (cond) stloc (A, V1) else stloc (A, V2) --> stloc (A, if (cond) V1 else V2) + Block trueInst = inst.TrueInst as Block; + if (trueInst == null || trueInst.Instructions.Count != 1) + return inst; + Block falseInst = inst.FalseInst as Block; + if (falseInst == null || falseInst.Instructions.Count != 1) + return inst; + ILVariable v; + ILInstruction value1, value2; + if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) { + context.Step("conditional operator", inst); + var newIf = new IfInstruction(Comp.LogicNot(inst.Condition), value2, value1); + newIf.AddILRange(inst); + inst.ReplaceWith(new StLoc(v, newIf)); + context.RequestRerun(); // trigger potential inlining of the newly created StLoc + return newIf; + } + return inst; + } + + private void HandleSwitchExpression(BlockContainer container, SwitchInstruction switchInst) + { + if (!context.Settings.SwitchExpressions) + return; + Debug.Assert(container.Kind == ContainerKind.Switch); + Debug.Assert(container.ResultType == StackType.Void); + var defaultSection = switchInst.GetDefaultSection(); + StackType resultType = StackType.Void; + BlockContainer leaveTarget = null; + ILVariable resultVariable = null; + foreach (var section in switchInst.Sections) { + if (section != defaultSection) { + // every section except for the default must have exactly 1 label + if (section.Labels.Count() != (section.HasNullLabel ? 0u : 1u)) + return; + } + if (!section.Body.MatchBranch(out var sectionBlock)) + return; + if (sectionBlock.IncomingEdgeCount != 1) + return; + if (sectionBlock.Parent != container) + return; + if (sectionBlock.Instructions.Count == 1) { + if (sectionBlock.Instructions[0] is Throw) { + // OK + } else if (sectionBlock.Instructions[0] is Leave leave) { + if (!leave.IsLeavingFunction) + return; + leaveTarget ??= leave.TargetContainer; + Debug.Assert(leaveTarget == leave.TargetContainer); + resultType = leave.Value.ResultType; + } else { + return; + } + } else if (sectionBlock.Instructions.Count == 2) { + if (!sectionBlock.Instructions[0].MatchStLoc(out var v, out _)) + return; + if (!sectionBlock.Instructions[1].MatchLeave(container)) + return; + resultVariable ??= v; + if (resultVariable != v) + return; + resultType = resultVariable.StackType; + } else { + return; + } + } + // Exactly one of resultVariable/leaveTarget must be null + if ((resultVariable == null) == (leaveTarget == null)) + return; + if (switchInst.Value is StringToInt str2int) { + // validate that each integer is used for exactly one value + var integersUsed = new HashSet(); + foreach ((string key, int val) in str2int.Map) { + if (!integersUsed.Add(val)) + return; + } + } + + context.Step("Switch Expression", switchInst); + switchInst.SetResultType(resultType); + foreach (var section in switchInst.Sections) { + var block = ((Branch)section.Body).TargetBlock; + if (block.Instructions.Count == 1) { + if (block.Instructions[0] is Throw t) { + t.resultType = resultType; + section.Body = t; + } else if (block.Instructions[0] is Leave leave) { + section.Body = leave.Value; + } else { + throw new InvalidOperationException(); + } + } else { + section.Body = ((StLoc)block.Instructions[0]).Value; + } + } + if (resultVariable != null) { + container.ReplaceWith(new StLoc(resultVariable, switchInst)); + } else { + container.ReplaceWith(new Leave(leaveTarget, switchInst)); + } + context.RequestRerun(); // new StLoc might trigger inlining + } + /// /// op is either add or remove/subtract: /// if (dynamic.isevent (target)) { @@ -641,28 +744,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms inst.ReplaceWith(new DynamicCompoundAssign(binaryOp.Operation, binaryOp.BinderFlags, binaryOp.Left, binaryOp.LeftArgumentInfo, binaryOp.Right, binaryOp.RightArgumentInfo)); } - IfInstruction HandleConditionalOperator(IfInstruction inst) - { - // if (cond) stloc (A, V1) else stloc (A, V2) --> stloc (A, if (cond) V1 else V2) - Block trueInst = inst.TrueInst as Block; - if (trueInst == null || trueInst.Instructions.Count != 1) - return inst; - Block falseInst = inst.FalseInst as Block; - if (falseInst == null || falseInst.Instructions.Count != 1) - return inst; - ILVariable v; - ILInstruction value1, value2; - if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) { - context.Step("conditional operator", inst); - var newIf = new IfInstruction(Comp.LogicNot(inst.Condition), value2, value1); - newIf.AddILRange(inst); - inst.ReplaceWith(new StLoc(v, newIf)); - context.RequestRerun(); // trigger potential inlining of the newly created StLoc - return newIf; - } - return inst; - } - protected internal override void VisitBinaryNumericInstruction(BinaryNumericInstruction inst) { base.VisitBinaryNumericInstruction(inst); @@ -670,8 +751,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms case BinaryNumericOperator.ShiftLeft: case BinaryNumericOperator.ShiftRight: if (inst.Right.MatchBinaryNumericInstruction(BinaryNumericOperator.BitAnd, out var lhs, out var rhs) - && rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31)) - { + && rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31)) { // a << (b & 31) => a << b context.Step("Combine bit.and into shift", inst); inst.Right = lhs; @@ -679,8 +759,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; case BinaryNumericOperator.BitAnd: if (inst.Left.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean) - && inst.Right.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean)) - { + && inst.Right.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean)) { if (new NullableLiftingTransform(context).Run(inst)) { // e.g. "(a.GetValueOrDefault() == b.GetValueOrDefault()) & (a.HasValue & b.HasValue)" } @@ -688,7 +767,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; } } - + protected internal override void VisitTryCatchHandler(TryCatchHandler inst) { base.VisitTryCatchHandler(inst); From 1a997fdb60cd1580a9f03863ce361f54232cd1a9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 2 Aug 2020 12:11:47 +0200 Subject: [PATCH 52/92] Enable aggressive inlining into switch expressions. --- .../TestCases/Pretty/SwitchExpressions.cs | 4 +-- .../IL/Transforms/ILInlining.cs | 26 ++++++------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs index 321e456c5..37b086cbc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs @@ -75,9 +75,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } - public static string SwitchOverNullableInt(int? i) + public static string SwitchOverNullableInt(int? i, int? j) { - return i switch { + return (i + j) switch { null => "null", 0 => "zero", 5 => "five", diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index ab26ec7b5..d821b934e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -418,6 +418,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms case OpCode.NumericCompoundAssign: case OpCode.UserDefinedCompoundAssign: case OpCode.Await: + case OpCode.SwitchInstruction: return true; case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { @@ -479,32 +480,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } break; + case OpCode.Leave: + case OpCode.YieldReturn: + return true; + case OpCode.SwitchInstruction: + //case OpCode.BinaryNumericInstruction when parent.SlotInfo == SwitchInstruction.ValueSlot: + case OpCode.StringToInt when parent.SlotInfo == SwitchInstruction.ValueSlot: + return true; } // decide based on the top-level target instruction into which we are inlining: switch (next.OpCode) { - case OpCode.Leave: - case OpCode.YieldReturn: - return parent == next; case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return parent == next; - case OpCode.BlockContainer: - if (((BlockContainer)next).EntryPoint.Instructions[0] is SwitchInstruction switchInst) { - next = switchInst; - goto case OpCode.SwitchInstruction; - } else { - return false; - } - case OpCode.SwitchInstruction: - if (parent == next) - return true; - if (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next) - return true; - if (parent is StringToInt stringToInt && stringToInt.Parent == next) - return true; - return false; default: return false; } From 5c949e6e207b0cf1b2f8504a9fc443b1c0ba9b9d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 2 Aug 2020 13:22:30 +0200 Subject: [PATCH 53/92] Fix #2086: Check that window belongs to ILSpy before sending it a WM_COPYDATA message. --- ILSpy.AddIn/ILSpyInstance.cs | 28 ++++++----- ILSpy.AddIn/Utils.cs | 95 ------------------------------------ ILSpy/App.xaml.cs | 24 ++++++--- ILSpy/NativeMethods.cs | 36 +++++++++++--- 4 files changed, 62 insertions(+), 121 deletions(-) diff --git a/ILSpy.AddIn/ILSpyInstance.cs b/ILSpy.AddIn/ILSpyInstance.cs index bc0d21c37..182ee3e9e 100644 --- a/ILSpy.AddIn/ILSpyInstance.cs +++ b/ILSpy.AddIn/ILSpyInstance.cs @@ -38,10 +38,10 @@ namespace ICSharpCode.ILSpy.AddIn public void Start() { var commandLineArguments = parameters?.AssemblyFileNames?.Concat(parameters.Arguments); - + string ilSpyExe = GetILSpyPath(); var process = new Process() { StartInfo = new ProcessStartInfo() { - FileName = GetILSpyPath(), + FileName = ilSpyExe, UseShellExecute = false, Arguments = "/navigateTo:none" } @@ -50,13 +50,14 @@ namespace ICSharpCode.ILSpy.AddIn if ((commandLineArguments != null) && commandLineArguments.Any()) { // Only need a message to started process if there are any parameters to pass - SendMessage(process, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true); + SendMessage(ilSpyExe, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "")] - void SendMessage(Process ilspyProcess, string message, bool activate) + void SendMessage(string ilSpyExe, string message, bool activate) { + string expectedProcessName = Path.GetFileNameWithoutExtension(ilSpyExe); // We wait asynchronously until target window can be found and try to find it multiple times Task.Run(async () => { bool success = false; @@ -66,14 +67,17 @@ namespace ICSharpCode.ILSpy.AddIn (hWnd, lParam) => { string windowTitle = NativeMethods.GetWindowText(hWnd, 100); if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) { - Debug.WriteLine("Found {0:x4}: {1}", hWnd, windowTitle); - IntPtr result = Send(hWnd, message); - Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); - if (result == (IntPtr)1) { - if (activate) - NativeMethods.SetForegroundWindow(hWnd); - success = true; - return false; // stop enumeration + string processName = NativeMethods.GetProcessNameFromWindow(hWnd); + Debug.WriteLine("Found {0:x4}: '{1}' in '{2}'", hWnd, windowTitle, processName); + if (string.Equals(processName, expectedProcessName, StringComparison.OrdinalIgnoreCase)) { + IntPtr result = Send(hWnd, message); + Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); + if (result == (IntPtr)1) { + if (activate) + NativeMethods.SetForegroundWindow(hWnd); + success = true; + return false; // stop enumeration + } } } return true; // continue enumeration diff --git a/ILSpy.AddIn/Utils.cs b/ILSpy.AddIn/Utils.cs index 74af2d797..65d3dc4b0 100644 --- a/ILSpy.AddIn/Utils.cs +++ b/ILSpy.AddIn/Utils.cs @@ -30,101 +30,6 @@ namespace ICSharpCode.ILSpy.AddIn static class Utils { - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")] - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - static extern unsafe char** CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")] - [DllImport("kernel32.dll")] - static extern IntPtr LocalFree(IntPtr hMem); - - #region CommandLine <-> Argument Array - /// - /// Decodes a command line into an array of arguments according to the CommandLineToArgvW rules. - /// - /// - /// Command line parsing rules: - /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument. - /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark. - /// - n backslashes not followed by a quotation mark simply produce n backslashes. - /// - public static unsafe string[] CommandLineToArgumentArray(string commandLine) - { - if (string.IsNullOrEmpty(commandLine)) - return new string[0]; - int numberOfArgs; - char** arr = CommandLineToArgvW(commandLine, out numberOfArgs); - if (arr == null) - throw new Win32Exception(); - try { - string[] result = new string[numberOfArgs]; - for (int i = 0; i < numberOfArgs; i++) { - result[i] = new string(arr[i]); - } - return result; - } finally { - // Free memory obtained by CommandLineToArgW. - LocalFree(new IntPtr(arr)); - } - } - - static readonly char[] charsNeedingQuoting = { ' ', '\t', '\n', '\v', '"' }; - - /// - /// Escapes a set of arguments according to the CommandLineToArgvW rules. - /// - /// - /// Command line parsing rules: - /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument. - /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark. - /// - n backslashes not followed by a quotation mark simply produce n backslashes. - /// - public static string ArgumentArrayToCommandLine(params string[] arguments) - { - if (arguments == null) - return null; - StringBuilder b = new StringBuilder(); - for (int i = 0; i < arguments.Length; i++) { - if (i > 0) - b.Append(' '); - AppendArgument(b, arguments[i]); - } - return b.ToString(); - } - - static void AppendArgument(StringBuilder b, string arg) - { - if (arg == null) { - return; - } - - if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) { - b.Append(arg); - } else { - b.Append('"'); - for (int j = 0; ; j++) { - int backslashCount = 0; - while (j < arg.Length && arg[j] == '\\') { - backslashCount++; - j++; - } - if (j == arg.Length) { - b.Append('\\', backslashCount * 2); - break; - } else if (arg[j] == '"') { - b.Append('\\', backslashCount * 2 + 1); - b.Append('"'); - } else { - b.Append('\\', backslashCount); - b.Append(arg[j]); - } - } - b.Append('"'); - } - } - #endregion - public static byte[] HexStringToBytes(string hex) { if (hex == null) diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index 0f578dc69..2fa17861a 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -196,19 +196,27 @@ namespace ICSharpCode.ILSpy #region Pass Command Line Arguments to previous instance bool SendToPreviousInstance(string message, bool activate) { + string ownProcessName; + using (var ownProcess = Process.GetCurrentProcess()) { + ownProcessName = ownProcess.ProcessName; + } + bool success = false; NativeMethods.EnumWindows( (hWnd, lParam) => { string windowTitle = NativeMethods.GetWindowText(hWnd, 100); if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) { - Debug.WriteLine("Found {0:x4}: {1}", hWnd, windowTitle); - IntPtr result = Send(hWnd, message); - Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); - if (result == (IntPtr)1) { - if (activate) - NativeMethods.SetForegroundWindow(hWnd); - success = true; - return false; // stop enumeration + string processName = NativeMethods.GetProcessNameFromWindow(hWnd); + Debug.WriteLine("Found {0:x4}: '{1}' in '{2}'", hWnd, windowTitle, processName); + if (string.Equals(processName, ownProcessName, StringComparison.OrdinalIgnoreCase)) { + IntPtr result = Send(hWnd, message); + Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); + if (result == (IntPtr)1) { + if (activate) + NativeMethods.SetForegroundWindow(hWnd); + success = true; + return false; // stop enumeration + } } } return true; // continue enumeration diff --git a/ILSpy/NativeMethods.cs b/ILSpy/NativeMethods.cs index 9487743d6..3805f3a23 100644 --- a/ILSpy/NativeMethods.cs +++ b/ILSpy/NativeMethods.cs @@ -20,20 +20,24 @@ using System; using System.Text; using System.Runtime.InteropServices; using System.ComponentModel; +using System.Diagnostics; namespace ICSharpCode.ILSpy { static class NativeMethods { public const uint WM_COPYDATA = 0x4a; - + [DllImport("user32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); - + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + internal static extern unsafe int GetWindowThreadProcessId(IntPtr hWnd, int* lpdwProcessId); + [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder title, int size); - + public static string GetWindowText(IntPtr hWnd, int maxLength) { StringBuilder b = new StringBuilder(maxLength + 1); @@ -42,12 +46,12 @@ namespace ICSharpCode.ILSpy else return string.Empty; } - + [DllImport("user32.dll", CharSet = CharSet.Auto)] internal static extern IntPtr SendMessageTimeout( IntPtr hWnd, uint msg, IntPtr wParam, ref CopyDataStruct lParam, uint flags, uint timeout, out IntPtr result); - + [DllImport("user32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetForegroundWindow(IntPtr hWnd); @@ -145,11 +149,31 @@ namespace ICSharpCode.ILSpy } } #endregion + + public unsafe static string GetProcessNameFromWindow(IntPtr hWnd) + { + int processId; + GetWindowThreadProcessId(hWnd, &processId); + try { + using (var p = Process.GetProcessById(processId)) { + return p.ProcessName; + } + } catch (ArgumentException ex) { + Debug.WriteLine(ex.Message); + return null; + } catch (InvalidOperationException ex) { + Debug.WriteLine(ex.Message); + return null; + } catch (Win32Exception ex) { + Debug.WriteLine(ex.Message); + return null; + } + } } [return: MarshalAs(UnmanagedType.Bool)] delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); - + [StructLayout(LayoutKind.Sequential)] struct CopyDataStruct { From 28a1382a52dbba8f7891b86806524724ed7932a9 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Sun, 2 Aug 2020 12:11:47 -0700 Subject: [PATCH 54/92] Some changes I wanted --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 4 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 57 +++++++------------ ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 2 + ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 14 ++++- ILSpy.ReadyToRun/ReadyToRunOptions.cs | 24 ++++++-- ILSpy/ILSpy.csproj | 4 +- 6 files changed, 57 insertions(+), 48 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index a31d53184..aacd89197 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -37,9 +37,6 @@ False - - ..\..\..\Desktop\r2r\ILCompiler.Reflection.ReadyToRun\bin\Debug\netstandard2.0\ILCompiler.Reflection.ReadyToRun.dll - @@ -60,6 +57,7 @@ + diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 1437df604..18355d985 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -86,8 +86,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun .GroupBy(m => m.MethodHandle) .ToDictionary(g => g.Key, g => g.ToArray()); } - - bool showMetadataTokens = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens; bool showMetadataTokensInBase10 = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10; if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) { @@ -115,7 +113,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { var varLoc = debugInfo.VariablesList[i]; try { - HashSet > typeSet = new HashSet>(); + HashSet> typeSet = new HashSet>(); bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); if (found) { typeSet.Add(new Tuple(debugInfo, varLoc)); @@ -124,14 +122,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); typeSet.Add(new Tuple(debugInfo, varLoc)); } - } catch (ArgumentNullException) { output.WriteLine("Failed to find hash set of Debug info type"); } if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) { - //debugInfoDict.Add(varLoc.VariableLocation.VarLocType, ) output.WriteLine($" Variable Number: {varLoc.VariableNumber}"); output.WriteLine($" Start Offset: 0x{varLoc.StartOffset:X}"); output.WriteLine($" End Offset: 0x{varLoc.EndOffset:X}"); @@ -142,7 +138,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun case VarLocType.VLT_REG_BYREF: output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; - case VarLocType.VLT_STK: case VarLocType.VLT_STK_BYREF: output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); @@ -172,25 +167,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun case VarLocType.VLT_FIXED_VA: output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; - default: throw new BadImageFormatException("Unexpected var loc type"); } - output.WriteLine(""); } } - } } return debugInfoDict; } - - private Dictionary> WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) - + private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) { - Dictionary> unwindCodes = new Dictionary>(); + Dictionary unwindCodes = new Dictionary(); if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { @@ -210,13 +200,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun WriteCommentLine(output, $"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}"); WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString())}"); for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) { - if (unwindCodes.ContainsKey((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset))) { - unwindCodes[(ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset)].Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - } else { - HashSet codeSet = new HashSet(); - codeSet.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), codeSet); - } + unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); } } return unwindCodes; @@ -224,19 +208,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) { - WriteCommentLine(output, readyToRunMethod.SignatureString); - Dictionary> unwindInfo = null; + + Dictionary unwindInfo = null; if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { unwindInfo = WriteUnwindInfo(runtimeFunction, output); } - Dictionary>> debugInfo = WriteDebugInfo(readyToRunMethod, output); + + bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null); + Dictionary>> debugInfo = null; + if (isShowDebugInfo) { + debugInfo = WriteDebugInfo(readyToRunMethod, output); + } + byte[] codeBytes = new byte[runtimeFunction.Size]; for (int i = 0; i < runtimeFunction.Size; i++) { codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i]; } - // TODO: Decorate the disassembly with GC + // TODO: Decorate the disassembly with GCInfo var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; @@ -259,12 +249,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; - int counter = -1; foreach (var instr in instructions) { - counter++; - int byteBaseIndex = (int)(instr.IP - address); - if (runtimeFunction.DebugInfo != null) { + if (isShowDebugInfo && runtimeFunction.DebugInfo != null) { foreach (var bound in runtimeFunction.DebugInfo.BoundsList) { if (bound.NativeOffset == byteBaseIndex) { if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) { @@ -277,7 +264,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } } - formatter.Format(instr, tempOutput); output.Write(instr.IP.ToString("X16")); output.Write(" "); @@ -286,8 +272,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.Write(codeBytes[byteBaseIndex + i].ToString("X2")); } int missingBytes = 10 - instrLen; - for (int i = 0; i < missingBytes; i++) + for (int i = 0; i < missingBytes; i++) { output.Write(" "); + } output.Write(" "); output.Write(tempOutput.ToStringAndReset()); DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); @@ -297,13 +284,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine(); } - private static void DecorateUnwindInfo(ITextOutput output, Dictionary> unwindInfo, ulong baseInstrIP, Instruction instr) + private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) { ulong nextInstructionOffset = instr.NextIP - baseInstrIP; if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) { - foreach (var unwindCode in unwindInfo[nextInstructionOffset]) { - output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); - } + UnwindCode unwindCode = unwindInfo[nextInstructionOffset]; + output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); } } @@ -338,7 +324,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Base.ToString() && adjOffset == usedMemInfo.Displacement) { - output.Write($"; [{usedMemInfo.Base.ToString()}{(negativeOffset ? '-' : '+')}{Math.Abs(stackOffset)}] = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } @@ -361,7 +346,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun var varInfo = tuple.Item2; if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { - output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } @@ -402,7 +386,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine(reader.ImportCellNames[importCellAddress]); break; } - output.WriteLine(); } else { output.WriteLine(); diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 55fcf2fb6..7fb149cbe 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -15,5 +15,7 @@ Show Unwind Info + Show Debug Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 3e81b1c7c..3bf810d85 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -36,6 +36,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun Options s = new Options(); s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings); + s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings); this.DataContext = s; } @@ -48,7 +49,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun public void Save(XElement root) { Options s = (Options)this.DataContext; - ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo); + ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo, s.IsShowDebugInfo); } } @@ -71,6 +72,17 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } + private bool isShowDebugInfo; + + public bool IsShowDebugInfo { + get { + return isShowDebugInfo; + } + set { + isShowDebugInfo = value; + OnPropertyChanged(nameof(IsShowDebugInfo)); + } + } private string disassemblyFormat; diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index 5eddd6789..f82535e63 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -43,7 +43,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun } public static bool GetIsShowUnwindInfo(ILSpySettings settings) - { if (settings == null) { settings = ILSpySettings.Load(); @@ -58,11 +57,27 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool IsShowUnwindInfo) + public static bool GetIsShowDebugInfo(ILSpySettings settings) + { + if (settings == null) { + settings = ILSpySettings.Load(); + } + XElement e = settings[ns + "ReadyToRunOptions"]; + XAttribute a = e.Attribute("IsShowDebugInfo"); + + if (a == null) { + return true; + } else { + return (bool)a; + } + } + + public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isShowUnwindInfo, bool isShowDebugInfo) { XElement section = new XElement(ns + "ReadyToRunOptions"); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); - section.SetAttributeValue("IsShowUnwindInfo", IsShowUnwindInfo); + section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo); + section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); if (existingElement != null) { existingElement.ReplaceWith(section); @@ -70,8 +85,5 @@ namespace ICSharpCode.ILSpy.ReadyToRun root.Add(section); } } - - } - } diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 4d4ee4e3a..71414747b 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -128,7 +128,9 @@ - + + Form + From ced4b8d3d359d7e6d2f74e607ce2710e72b5816c Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 3 Aug 2020 09:58:31 +0200 Subject: [PATCH 55/92] Implementation for https://github.com/icsharpcode/ILSpy/issues/1933#issuecomment-663998595 Uses https://github.com/marketplace/actions/lock-threads Settings: issues only, run once a day, lock after 365 days, add comment why it was locked --- .github/workflows/lock.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/lock.yml diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 000000000..04cffa91a --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,22 @@ +name: 'Lock threads' + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2.0.1 + with: + github-token: ${{ github.token }} + issue-lock-inactive-days: '365' + issue-lock-comment: > + This issue has been automatically locked since there + has not been any recent activity after it was closed. + Please open a new issue for related bugs. + issue-lock-reason: 'resolved' + process-only: 'issues' + # pr-lock-inactive-days: '365' + # pr-lock-reason: 'resolved' \ No newline at end of file From aaca0e92b81bc3f40f4588371c784e4de1e0a46c Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 3 Aug 2020 19:08:35 +0200 Subject: [PATCH 56/92] Remove gitter.im, we are now using Discussions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9aa68fc0..6b97ca8f6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ILSpy [![Join the chat at https://gitter.im/icsharpcode/ILSpy](https://badges.gitter.im/icsharpcode/ILSpy.svg)](https://gitter.im/icsharpcode/ILSpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NuGet](https://img.shields.io/nuget/v/ICSharpCode.Decompiler.svg)](https://nuget.org/packages/ICSharpCode.Decompiler) [![Build status](https://ci.appveyor.com/api/projects/status/imgec05g0wwv25ij/branch/master?svg=true)](https://ci.appveyor.com/project/icsharpcode/ilspy/branch/master) [![Twitter Follow](https://img.shields.io/twitter/follow/ILSpy.svg?label=Follow%20@ILSpy)](https://twitter.com/ilspy) [![ILSpy VS extension](https://img.shields.io/badge/VS%20Extension-ILSpy-blue.svg)](https://visualstudiogallery.msdn.microsoft.com/8ef1d688-f80c-4380-8004-2ec7f814e7de) [![Build Status](https://icsharpcode.visualstudio.com/icsharpcode-pipelines/_apis/build/status/icsharpcode.ILSpy?branchName=master)](https://icsharpcode.visualstudio.com/icsharpcode-pipelines/_build/latest?definitionId=1&branchName=master) +# ILSpy [![NuGet](https://img.shields.io/nuget/v/ICSharpCode.Decompiler.svg)](https://nuget.org/packages/ICSharpCode.Decompiler) [![Build status](https://ci.appveyor.com/api/projects/status/imgec05g0wwv25ij/branch/master?svg=true)](https://ci.appveyor.com/project/icsharpcode/ilspy/branch/master) [![Twitter Follow](https://img.shields.io/twitter/follow/ILSpy.svg?label=Follow%20@ILSpy)](https://twitter.com/ilspy) [![ILSpy VS extension](https://img.shields.io/badge/VS%20Extension-ILSpy-blue.svg)](https://visualstudiogallery.msdn.microsoft.com/8ef1d688-f80c-4380-8004-2ec7f814e7de) [![Build Status](https://icsharpcode.visualstudio.com/icsharpcode-pipelines/_apis/build/status/icsharpcode.ILSpy?branchName=master)](https://icsharpcode.visualstudio.com/icsharpcode-pipelines/_build/latest?definitionId=1&branchName=master) ILSpy is the open-source .NET assembly browser and decompiler. From 8b49cc0f5451c599805839536fee760b7583d1cb Mon Sep 17 00:00:00 2001 From: Edward Carlson Date: Wed, 5 Aug 2020 12:37:23 -0700 Subject: [PATCH 57/92] backup --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 36 ++++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 18355d985..7b8b62a8b 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -103,9 +103,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine("; " + comment); } - private Dictionary>> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + private Dictionary> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) { - Dictionary>> debugInfoDict = new Dictionary>>(); + Dictionary> debugInfoDict = new Dictionary>(); IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; foreach (RuntimeFunction runtimeFunction in runTimeList) { DebugInfo debugInfo = runtimeFunction.DebugInfo; @@ -113,14 +113,16 @@ namespace ICSharpCode.ILSpy.ReadyToRun for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { var varLoc = debugInfo.VariablesList[i]; try { - HashSet> typeSet = new HashSet>(); + var typeSet = new HashSet>(); bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); if (found) { - typeSet.Add(new Tuple(debugInfo, varLoc)); + (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); + typeSet.Add(newTuple); } else { - typeSet = new HashSet>(); + typeSet = new HashSet>(); debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); - typeSet.Add(new Tuple(debugInfo, varLoc)); + (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); + typeSet.Add(newTuple); } } catch (ArgumentNullException) { output.WriteLine("Failed to find hash set of Debug info type"); @@ -168,7 +170,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; default: - throw new BadImageFormatException("Unexpected var loc type"); + throw new BadImageFormatException("Unexpected variable type"); } output.WriteLine(""); } @@ -216,7 +218,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun } bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null); - Dictionary>> debugInfo = null; + Dictionary>> debugInfo = null; if (isShowDebugInfo) { debugInfo = WriteDebugInfo(readyToRunMethod, output); } @@ -293,12 +295,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary>> debugInfoDict, ulong baseInstrIP) + private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary> debugInfoDict, ulong baseInstrIP) { if (debugInfoDict != null) { InstructionInfoFactory factory = new InstructionInfoFactory(); InstructionInfo info = factory.GetInfo(instr); - HashSet> stkSet = new HashSet>(); + HashSet> stkSet = new HashSet>(); if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) { stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK]); } @@ -307,9 +309,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun } if (stkSet != null) { foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) { //for each time a [register +- value] is used - foreach (Tuple tuple in stkSet) { //for each VLT_STK variable - var debugInfo = tuple.Item1; - var varInfo = tuple.Item2; + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in stkSet) { //for each VLT_STK variable + var debugInfo = tuple.debugInfo; + var varInfo = tuple.varLoc; int stackOffset = varInfo.VariableLocation.Data2; ulong adjOffset; bool negativeOffset; @@ -329,7 +331,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } } - HashSet> regSet = new HashSet>(); + HashSet> regSet = new HashSet>(); if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) { regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG]); } @@ -341,9 +343,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun } if (regSet != null) { foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) { - foreach (Tuple tuple in regSet) { - var debugInfo = tuple.Item1; - var varInfo = tuple.Item2; + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in regSet) { + var debugInfo = tuple.debugInfo; + var varInfo = tuple.varLoc; if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); From 2403548ce3479a7481c866ed17da3b551f0d81bf Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 5 Aug 2020 22:10:32 +0200 Subject: [PATCH 58/92] Add tests for C# 9.0 lambda parameter discards --- ICSharpCode.Decompiler.Tests/Helpers/Tester.cs | 7 ++++--- ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs | 2 +- .../TestCases/Pretty/DelegateConstruction.cs | 12 ++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index b177b7ef9..6bc3c6a9f 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -251,15 +251,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers preprocessorSymbols.Add("VB11"); preprocessorSymbols.Add("VB14"); preprocessorSymbols.Add("VB15"); + + if (flags.HasFlag(CompilerOptions.Preview)) { + preprocessorSymbols.Add("CS90"); + } } else if (flags.HasFlag(CompilerOptions.UseMcs)) { preprocessorSymbols.Add("MCS"); } else { preprocessorSymbols.Add("LEGACY_CSC"); preprocessorSymbols.Add("LEGACY_VBC"); } - if (flags.HasFlag(CompilerOptions.Preview)) { - preprocessorSymbols.Add("CS90"); - } return preprocessorSymbols; } diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index ceeae1d1a..fa6fc7ccf 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -155,7 +155,7 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void DelegateConstruction([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions) { - RunForLibrary(cscOptions: cscOptions); + RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs index a73252ee0..8d5f6fdab 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs @@ -428,6 +428,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return () => valueTuple.RenamedString; } #endif + + public static Func Identity() + { + return (T _) => _; + } + +#if CS90 + public static Func LambdaParameterDiscard() + { + return (int _, int _, int _) => 0; + } +#endif } public class Issue1867 From ef96d178bfffee40276f38247a7254a660c3cfec Mon Sep 17 00:00:00 2001 From: Edward Carlson Date: Thu, 6 Aug 2020 10:26:14 -0700 Subject: [PATCH 59/92] change from tuple to valuetuple --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 7b8b62a8b..f10c40941 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -210,6 +210,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) { + // TODO: Decorate the disassembly with GCInfo WriteCommentLine(output, readyToRunMethod.SignatureString); Dictionary unwindInfo = null; @@ -228,7 +229,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i]; } - // TODO: Decorate the disassembly with GCInfo var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; From c6b10d3ec3633c6b803d2f994f71db60a7a5e141 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 21:44:24 +0200 Subject: [PATCH 60/92] Fix #2094: ByteOffset() arguments passed in wrong order --- ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs | 2 +- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index 777dcedd1..4bac5c052 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -228,7 +228,7 @@ namespace System.Runtime.CompilerServices [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr ByteOffset(ref T origin, ref T target) { - return Unsafe.ByteOffset(ref target, ref origin); + return Unsafe.ByteOffset(target: ref target, origin: ref origin); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index ee0d112dc..b01e80a3a 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1076,7 +1076,11 @@ namespace ICSharpCode.Decompiler.CSharp return null; if (inst.Operator == BinaryNumericOperator.Sub && inst.LeftInputType == StackType.Ref && inst.RightInputType == StackType.Ref) { // ref - ref => i - return CallUnsafeIntrinsic("ByteOffset", new[] { left.Expression, right.Expression }, compilation.FindType(KnownTypeCode.IntPtr), inst); + return CallUnsafeIntrinsic("ByteOffset", new[] { + // ByteOffset() expects the parameters the wrong way around, so order using named arguments + new NamedArgumentExpression("target", left.Expression), + new NamedArgumentExpression("origin", right.Expression) + }, compilation.FindType(KnownTypeCode.IntPtr), inst); } if (inst.LeftInputType == StackType.Ref && inst.RightInputType.IsIntegerType() && left.Type is ByReferenceType brt) { From 40e2776f021007526ed480c2959e2dbf82c8721d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 21:51:59 +0200 Subject: [PATCH 61/92] #2089: Handle invalid attribute/reference metadata in `DetectTargetFrameworkId` --- .../DotNetCorePathFinderExtensions.cs | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index b29fae6e5..dd7aee077 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -55,44 +55,52 @@ namespace ICSharpCode.Decompiler.Metadata var reader = assembly.GetMetadataReader(); foreach (var h in reader.GetCustomAttributes(Handle.AssemblyDefinition)) { - var attribute = reader.GetCustomAttribute(h); - if (attribute.GetAttributeType(reader).GetFullTypeName(reader).ToString() != TargetFrameworkAttributeName) - continue; - var blobReader = reader.GetBlobReader(attribute.Value); - if (blobReader.ReadUInt16() == 0x0001) { - return blobReader.ReadSerializedString(); + try { + var attribute = reader.GetCustomAttribute(h); + if (attribute.GetAttributeType(reader).GetFullTypeName(reader).ToString() != TargetFrameworkAttributeName) + continue; + var blobReader = reader.GetBlobReader(attribute.Value); + if (blobReader.ReadUInt16() == 0x0001) { + return blobReader.ReadSerializedString(); + } + } catch (BadImageFormatException) { + // ignore malformed attributes } } foreach (var h in reader.AssemblyReferences) { - var r = reader.GetAssemblyReference(h); - if (r.PublicKeyOrToken.IsNil) - continue; - string version; - switch (reader.GetString(r.Name)) { - case "netstandard": - version = r.Version.ToString(3); - return $".NETStandard,Version=v{version}"; - case "System.Runtime": - // System.Runtime.dll uses the following scheme: - // 4.2.0 => .NET Core 2.0 - // 4.2.1 => .NET Core 2.1 / 3.0 - // 4.2.2 => .NET Core 3.1 - if (r.Version >= new Version(4, 2, 0)) { - version = "2.0"; - if (r.Version >= new Version(4, 2, 1)) { - version = "3.0"; + try { + var r = reader.GetAssemblyReference(h); + if (r.PublicKeyOrToken.IsNil) + continue; + string version; + switch (reader.GetString(r.Name)) { + case "netstandard": + version = r.Version.ToString(3); + return $".NETStandard,Version=v{version}"; + case "System.Runtime": + // System.Runtime.dll uses the following scheme: + // 4.2.0 => .NET Core 2.0 + // 4.2.1 => .NET Core 2.1 / 3.0 + // 4.2.2 => .NET Core 3.1 + if (r.Version >= new Version(4, 2, 0)) { + version = "2.0"; + if (r.Version >= new Version(4, 2, 1)) { + version = "3.0"; + } + if (r.Version >= new Version(4, 2, 2)) { + version = "3.1"; + } + return $".NETCoreApp,Version=v{version}"; + } else { + continue; } - if (r.Version >= new Version(4, 2, 2)) { - version = "3.1"; - } - return $".NETCoreApp,Version=v{version}"; - } else { - continue; - } - case "mscorlib": - version = r.Version.ToString(2); - return $".NETFramework,Version=v{version}"; + case "mscorlib": + version = r.Version.ToString(2); + return $".NETFramework,Version=v{version}"; + } + } catch (BadImageFormatException) { + // ignore malformed references } } From b6b5f1e8e63d527f687357fec11ab954e9cf5358 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 22:14:47 +0200 Subject: [PATCH 62/92] #2092: ILFunction.Parameters / ILFunction.ReturnType should never be null. --- ICSharpCode.Decompiler.Tests/DataFlowTest.cs | 12 ++++++++---- .../IL/Instructions/ILFunction.cs | 17 +++++++---------- .../IL/Transforms/TransformExpressionTrees.cs | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs index 3c599ccc2..8c49c3949 100644 --- a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs +++ b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs @@ -55,10 +55,14 @@ namespace ICSharpCode.Decompiler.Tests public void TryFinallyWithAssignmentInFinally() { ILVariable v = new ILVariable(VariableKind.Local, SpecialType.UnknownType, 0); - ILFunction f = new ILFunction((IMethod)null, 0, new GenericContext(), new TryFinally( - new Nop(), - new StLoc(v, new LdcI4(0)) - )); + ILFunction f = new ILFunction( + returnType: SpecialType.UnknownType, + parameters: new IParameter[0], + genericContext: new GenericContext(), + body: new TryFinally( + new Nop(), + new StLoc(v, new LdcI4(0)) + )); f.AddRef(); f.Variables.Add(v); f.Body.AcceptVisitor(new RDTest(f, v)); diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs index daaeb214a..d66248133 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs @@ -166,13 +166,11 @@ namespace ICSharpCode.Decompiler.IL /// /// Return type of this function. - /// Might be null, if this function was not created from metadata. /// public readonly IType ReturnType; /// /// List of parameters of this function. - /// Might be null, if this function was not created from metadata. /// public readonly IReadOnlyList Parameters; @@ -188,17 +186,16 @@ namespace ICSharpCode.Decompiler.IL /// /// /// Use to create ILAst. - /// may be null. /// public ILFunction(IMethod method, int codeSize, GenericContext genericContext, ILInstruction body, ILFunctionKind kind = ILFunctionKind.TopLevelFunction) : base(OpCode.ILFunction) { this.Method = method; - this.Name = Method?.Name; + this.Name = method.Name; this.CodeSize = codeSize; this.GenericContext = genericContext; this.Body = body; - this.ReturnType = Method?.ReturnType; - this.Parameters = Method?.Parameters; + this.ReturnType = method.ReturnType; + this.Parameters = method.Parameters; this.Variables = new ILVariableCollection(this); this.LocalFunctions = new InstructionCollection(this, 1); this.kind = kind; @@ -207,15 +204,15 @@ namespace ICSharpCode.Decompiler.IL /// /// This constructor is only to be used by the TransformExpressionTrees step. /// - internal ILFunction(IType returnType, IReadOnlyList parameters, GenericContext genericContext, ILInstruction body) : base(OpCode.ILFunction) + internal ILFunction(IType returnType, IReadOnlyList parameters, GenericContext genericContext, ILInstruction body, ILFunctionKind kind = ILFunctionKind.TopLevelFunction) : base(OpCode.ILFunction) { this.GenericContext = genericContext; this.Body = body; - this.ReturnType = returnType; - this.Parameters = parameters; + this.ReturnType = returnType ?? throw new ArgumentNullException(nameof(returnType)); + this.Parameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); this.Variables = new ILVariableCollection(this); this.LocalFunctions = new InstructionCollection(this, 1); - this.kind = ILFunctionKind.ExpressionTree; + this.kind = kind; } internal override void CheckInvariant(ILPhase phase) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index 4ed88e0c7..725bce082 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -156,8 +156,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var container = new BlockContainer(); container.AddILRange(instruction); var functionType = instruction.Method.ReturnType.TypeArguments[0]; - var returnType = functionType.GetDelegateInvokeMethod()?.ReturnType; - var function = new ILFunction(returnType, parameterList, context.Function.GenericContext, container); + var returnType = functionType.GetDelegateInvokeMethod()?.ReturnType ?? SpecialType.UnknownType; + var function = new ILFunction(returnType, parameterList, context.Function.GenericContext, container, ILFunctionKind.ExpressionTree); function.DelegateType = functionType; function.Kind = IsExpressionTree(functionType) ? ILFunctionKind.ExpressionTree : ILFunctionKind.Delegate; function.Variables.AddRange(parameterVariablesList); From 440ef75898b8b2001d047f572d36262f2ea2988a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 22:39:55 +0200 Subject: [PATCH 63/92] Avoid pointless UnknownType->object->UnknownType casts. --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index b01e80a3a..7bbd4f964 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1793,6 +1793,15 @@ namespace ICSharpCode.Decompiler.CSharp // Case 4 (left-over extension from implicit conversion) can also be handled by our caller. return arg.WithILInstruction(inst); } + case ConversionKind.Invalid: + if (inst.InputType == StackType.Unknown && inst.TargetType == IL.PrimitiveType.None && arg.Type.Kind == TypeKind.Unknown) { + // Unknown -> O conversion. + // Our post-condition allows us to also use expressions with unknown type where O is expected, + // so avoid introducing an `(object)` cast because we're likely to cast back to the same unknown type, + // just in a signature context where we know that it's a class type. + return arg.WithILInstruction(inst); + } + goto default; default: { // We need to convert to inst.TargetType, or to an equivalent type. IType targetType; From 5bd47c171fd4d14026a329ec5b33a459c7bfee22 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 22:50:31 +0200 Subject: [PATCH 64/92] Don't require a definition for the task builder type, also accept an UnknownType. --- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 27 ++++++++++++------- .../TypeSystem/Implementation/UnknownType.cs | 4 ++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index e290f4d95..3a69d5859 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -20,6 +20,7 @@ using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; using System; using System.Collections.Generic; @@ -74,7 +75,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow IType underlyingReturnType; // return type of the method (only the "T" for Task{T}), for async enumerators this is the type being yielded AsyncMethodType methodType; ITypeDefinition stateMachineType; - ITypeDefinition builderType; + IType builderType; IField builderField; IField stateField; int initialState; @@ -218,24 +219,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (startCall.Method.Name != "Start") return false; taskType = function.Method.ReturnType; - builderType = startCall.Method.DeclaringTypeDefinition; + builderType = startCall.Method.DeclaringType; + FullTypeName builderTypeName; + if (builderType?.GetDefinition() is { } builderTypeDef) { + builderTypeName = builderTypeDef.FullTypeName; + } else if (builderType is UnknownType unknownBuilderType) { + builderTypeName = unknownBuilderType.FullTypeName; + } else { + return false; + } if (taskType.IsKnownType(KnownTypeCode.Void)) { methodType = AsyncMethodType.Void; underlyingReturnType = taskType; - if (builderType?.FullTypeName != new TopLevelTypeName("System.Runtime.CompilerServices", "AsyncVoidMethodBuilder")) + if (builderTypeName != new TopLevelTypeName("System.Runtime.CompilerServices", "AsyncVoidMethodBuilder")) return false; - } else if (TaskType.IsNonGenericTaskType(taskType, out var builderTypeName)) { + } else if (TaskType.IsNonGenericTaskType(taskType, out var builderTypeNameFromTask)) { methodType = AsyncMethodType.Task; underlyingReturnType = context.TypeSystem.FindType(KnownTypeCode.Void); - if (builderType?.FullTypeName != builderTypeName) + if (builderTypeNameFromTask != builderTypeName) return false; - } else if (TaskType.IsGenericTaskType(taskType, out builderTypeName)) { + } else if (TaskType.IsGenericTaskType(taskType, out builderTypeNameFromTask)) { methodType = AsyncMethodType.TaskOfT; if (taskType.IsKnownType(KnownTypeCode.TaskOfT)) underlyingReturnType = TaskType.UnpackTask(context.TypeSystem, taskType); else underlyingReturnType = startCall.Method.DeclaringType.TypeArguments[0]; - if (builderType?.FullTypeName != builderTypeName) + if (builderTypeNameFromTask != builderTypeName) return false; } else { return false; @@ -484,7 +493,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; } - static void AnalyzeEnumeratorCtor(IMethod ctor, ILTransformContext context, out IField builderField, out ITypeDefinition builderType, out IField stateField) + static void AnalyzeEnumeratorCtor(IMethod ctor, ILTransformContext context, out IField builderField, out IType builderType, out IField stateField) { builderField = null; stateField = null; @@ -515,7 +524,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (stateField == null || builderField == null) throw new SymbolicAnalysisFailedException(); - builderType = builderField.Type.GetDefinition(); + builderType = builderField.Type; if (builderType == null) throw new SymbolicAnalysisFailedException(); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs index 018276115..84d483df2 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs @@ -86,7 +86,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override string ReflectionName { get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; } } - + + public FullTypeName FullTypeName => fullTypeName; + public override int TypeParameterCount => fullTypeName.TypeParameterCount; public override IReadOnlyList TypeParameters => DummyTypeParameter.GetClassTypeParameterList(TypeParameterCount); public override IReadOnlyList TypeArguments => TypeParameters; From b788441c78cbbdaaf1d33e15837bfdbfee2e6fcd Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 23:17:25 +0200 Subject: [PATCH 65/92] DecompilerTypeSystem: If some known types are present in referenced assemblies but others are missing; add the missing known types to the compilation. This ensures that FindType(KnownTypeCode).GetDefinition() always returns a usable definition. --- .../TypeSystem/DecompilerTypeSystem.cs | 18 ++++++----- .../Implementation/MinimalCorlib.cs | 30 ++++++++++++------- .../TypeSystem/KnownTypeReference.cs | 12 ++++++++ 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 98fd65194..9c126bbcf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -224,24 +224,26 @@ namespace ICSharpCode.Decompiler.TypeSystem var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions); var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions)); // Primitive types are necessary to avoid assertions in ILReader. - // Fallback to MinimalCorlib to provide the primitive types. - if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) { - Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance })); + // Other known types are necessary in order for transforms to work (e.g. Task for async transform). + // Figure out which known types are missing from our type system so far: + var missingKnownTypes = KnownTypeReference.AllKnownTypes.Where(IsMissing).ToList(); + if (missingKnownTypes.Count > 0) { + Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.CreateWithTypes(missingKnownTypes) })); } else { Init(mainModuleWithOptions, referencedAssembliesWithOptions); } this.MainModule = (MetadataModule)base.MainModule; - bool HasType(KnownTypeCode code) + bool IsMissing(KnownTypeReference knownType) { - TopLevelTypeName name = KnownTypeReference.Get(code).TypeName; + var name = knownType.TypeName; if (!mainModule.GetTypeDefinition(name).IsNil) - return true; + return false; foreach (var file in referencedAssemblies) { if (!file.GetTypeDefinition(name).IsNil) - return true; + return false; } - return false; + return true; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs index fbab0db4b..d98fe5d54 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs @@ -31,22 +31,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation /// public sealed class MinimalCorlib : IModule { - public static readonly IModuleReference Instance = new CorlibModuleReference(); + /// + /// Minimal corlib instance containing all known types. + /// + public static readonly IModuleReference Instance = new CorlibModuleReference(KnownTypeReference.AllKnownTypes); + + public static IModuleReference CreateWithTypes(IEnumerable types) + { + return new CorlibModuleReference(types); + } public ICompilation Compilation { get; } CorlibTypeDefinition[] typeDefinitions; readonly CorlibNamespace rootNamespace; - private MinimalCorlib(ICompilation compilation) + private MinimalCorlib(ICompilation compilation, IEnumerable types) { this.Compilation = compilation; - this.typeDefinitions = new CorlibTypeDefinition[KnownTypeReference.KnownTypeCodeCount]; + this.typeDefinitions = types.Select(ktr => new CorlibTypeDefinition(this, ktr.KnownTypeCode)).ToArray(); this.rootNamespace = new CorlibNamespace(this, null, string.Empty, string.Empty); - for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) { - if (KnownTypeReference.Get((KnownTypeCode)i) != null) { - typeDefinitions[i] = new CorlibTypeDefinition(this, (KnownTypeCode)i); - } - } } bool IModule.IsMainModule => Compilation.MainModule == this; @@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) { foreach (var typeDef in typeDefinitions) { - if (typeDef != null && typeDef.FullTypeName == topLevelTypeName) + if (typeDef.FullTypeName == topLevelTypeName) return typeDef; } return null; @@ -81,9 +84,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation sealed class CorlibModuleReference : IModuleReference { + readonly IEnumerable types; + + public CorlibModuleReference(IEnumerable types) + { + this.types = types; + } + IModule IModuleReference.Resolve(ITypeResolveContext context) { - return new MinimalCorlib(context.Compilation); + return new MinimalCorlib(context.Compilation, types); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs index a6981f2b2..d3a121ffc 100644 --- a/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; namespace ICSharpCode.Decompiler.TypeSystem { @@ -235,6 +236,17 @@ namespace ICSharpCode.Decompiler.TypeSystem return knownTypeReferences[(int)typeCode]; } + public static IEnumerable AllKnownTypes { + get { + for (int i = 0; i < KnownTypeCodeCount; i++) { + var ktr = Get((KnownTypeCode)i); + if (ktr == null) + continue; + yield return ktr; + } + } + } + readonly KnownTypeCode knownTypeCode; readonly string namespaceName; readonly string name; From 1751c9922cfd157ee2ed15fc14eeb1fba0b9880a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 6 Aug 2020 23:33:07 +0200 Subject: [PATCH 66/92] Avoid constructing a GetClassTypeReference instance in TypeProvider.GetTypeFromReference. --- .../Implementation/GetClassTypeReference.cs | 7 +++---- ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs | 13 ++++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs index 107c2eb76..b8b3f368a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs @@ -84,9 +84,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation /// public FullTypeName FullTypeName { get { return fullTypeName; } } - IType ResolveInAllAssemblies(ITypeResolveContext context) + internal static IType ResolveInAllAssemblies(ICompilation compilation, in FullTypeName fullTypeName) { - var compilation = context.Compilation; foreach (var asm in compilation.Modules) { IType type = asm.GetTypeDefinition(fullTypeName); if (type != null) @@ -107,7 +106,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation type = context.CurrentModule.GetTypeDefinition(fullTypeName); } if (type == null) { - type = ResolveInAllAssemblies(context); + type = ResolveInAllAssemblies(context.Compilation, in fullTypeName); } } else { // Assembly specified: only look in the specified assembly. @@ -118,7 +117,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if (asm != null) { type = asm.GetTypeDefinition(fullTypeName); } else { - type = ResolveInAllAssemblies(context); + type = ResolveInAllAssemblies(context.Compilation, in fullTypeName); } } return type ?? new UnknownType(fullTypeName, isReferenceType); diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs index 0ab8f4faa..8367205ce 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs @@ -131,9 +131,16 @@ namespace ICSharpCode.Decompiler.TypeSystem public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind) { - bool? isReferenceType = IsReferenceType(reader, handle, rawTypeKind); - var gctr = new GetClassTypeReference(handle.GetFullTypeName(reader), handle.GetDeclaringModule(reader), isReferenceType); - return gctr.Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); + IModuleReference moduleReference = handle.GetDeclaringModule(reader); + IModule resolvedModule = moduleReference.Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); + var fullTypeName = handle.GetFullTypeName(reader); + IType type; + if (resolvedModule != null) { + type = resolvedModule.GetTypeDefinition(fullTypeName); + } else { + type = GetClassTypeReference.ResolveInAllAssemblies(compilation, in fullTypeName); + } + return type ?? new UnknownType(fullTypeName, IsReferenceType(reader, handle, rawTypeKind)); } public IType GetTypeFromSerializedName(string name) From 8061634e6762b02994c7ee05f91e305e8aff969c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 7 Aug 2020 00:03:07 +0200 Subject: [PATCH 67/92] #1203, #2092: New logic for resolving assembly references within the type system. We now avoid the old `IModuleReference` interface which required allocating for every type being resolved. Instead `MetadataModule.ResolveModule` now combines decoding+resolving assembly references into a single step. This allows the type system to maintain a cache indexed by row number. This also changes the behavior of resolving references within a compilation: We now prefer an exact match (name + version + publickeytoken) first; and fall back to a name-only match only if no exact match exists. This somewhat improves the decompilation of assemblies created by using ilmerge to combine assemblies with different target frameworks. --- .../Metadata/MetadataExtensions.cs | 1 + .../TypeSystem/MetadataModule.cs | 60 +++++++++++++++++++ .../TypeSystem/TypeProvider.cs | 3 +- .../TypeSystem/TypeSystemExtensions.cs | 59 +++++++++--------- 4 files changed, 94 insertions(+), 29 deletions(-) diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index 8d304cc29..a3f39db83 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -147,6 +147,7 @@ namespace ICSharpCode.Decompiler.Metadata return Disassembler.DisassemblerHelpers.Escape(name); } + [Obsolete("Use MetadataModule.GetDeclaringModule() instead")] public static IModuleReference GetDeclaringModule(this TypeReferenceHandle handle, MetadataReader reader) { var tr = reader.GetTypeReference(handle); diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index 5d8d4bd3a..10f6a17fd 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -48,6 +48,7 @@ namespace ICSharpCode.Decompiler.TypeSystem readonly MetadataMethod[] methodDefs; readonly MetadataProperty[] propertyDefs; readonly MetadataEvent[] eventDefs; + readonly IModule[] referencedAssemblies; internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options) { @@ -79,6 +80,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1]; this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1]; this.eventDefs = new MetadataEvent[metadata.EventDefinitions.Count + 1]; + this.referencedAssemblies = new IModule[metadata.AssemblyReferences.Count + 1]; } } @@ -270,6 +272,64 @@ namespace ICSharpCode.Decompiler.TypeSystem } #endregion + #region Resolve Module + + public IModule ResolveModule(AssemblyReferenceHandle handle) + { + if (handle.IsNil) + return null; + + if (referencedAssemblies == null) + return ResolveModuleUncached(handle); + int row = MetadataTokens.GetRowNumber(handle); + Debug.Assert(row != 0); + if (row >= referencedAssemblies.Length) + HandleOutOfRange(handle); + var module = LazyInit.VolatileRead(ref referencedAssemblies[row]); + if (module != null) + return module; + module = ResolveModuleUncached(handle); + return LazyInit.GetOrSet(ref referencedAssemblies[row], module); + } + + IModule ResolveModuleUncached(AssemblyReferenceHandle handle) + { + var asmRef = new Metadata.AssemblyReference(metadata, handle); + return Compilation.FindModuleByReference(asmRef); + } + + public IModule ResolveModule(ModuleReferenceHandle handle) + { + if (handle.IsNil) + return null; + var modRef = metadata.GetModuleReference(handle); + string name = metadata.GetString(modRef.Name); + foreach (var mod in Compilation.Modules) { + if (mod.Name == name) { + return mod; + } + } + return null; + } + + public IModule GetDeclaringModule(TypeReferenceHandle handle) + { + if (handle.IsNil) + return null; + var tr = metadata.GetTypeReference(handle); + switch (tr.ResolutionScope.Kind) { + case HandleKind.TypeReference: + return GetDeclaringModule((TypeReferenceHandle)tr.ResolutionScope); + case HandleKind.AssemblyReference: + return ResolveModule((AssemblyReferenceHandle)tr.ResolutionScope); + case HandleKind.ModuleReference: + return ResolveModule((ModuleReferenceHandle)tr.ResolutionScope); + default: + return this; + } + } + #endregion + #region Resolve Type public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context, CustomAttributeHandleCollection? typeAttributes = null, Nullability nullableContext = Nullability.Oblivious) { diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs index 8367205ce..5c2924d8c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs @@ -131,8 +131,7 @@ namespace ICSharpCode.Decompiler.TypeSystem public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind) { - IModuleReference moduleReference = handle.GetDeclaringModule(reader); - IModule resolvedModule = moduleReference.Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); + IModule resolvedModule = module.GetDeclaringModule(handle); var fullTypeName = handle.GetFullTypeName(reader); IType type; if (resolvedModule != null) { diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 64684e8f6..26da4cdd9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem collector.CollectBaseTypes(type); return collector; } - + /// /// Gets all non-interface base types. /// @@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return collector; } #endregion - + #region GetAllBaseTypeDefinitions /// /// Gets all base type definitions. @@ -82,10 +82,10 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (type == null) throw new ArgumentNullException(nameof(type)); - + return type.GetAllBaseTypes().Select(t => t.GetDefinition()).Where(d => d != null).Distinct(); } - + /// /// Gets whether this type definition is derived from the base type definition. /// @@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return type.GetAllBaseTypeDefinitions().Contains(baseType); } - + /// /// Gets whether this type definition is derived from a given known type. /// @@ -138,7 +138,7 @@ namespace ICSharpCode.Decompiler.TypeSystem internal bool isOpen; internal IEntity typeParameterOwner; int typeParameterOwnerNestingLevel; - + public override IType VisitTypeParameter(ITypeParameter type) { isOpen = true; @@ -151,7 +151,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return base.VisitTypeParameter(type); } - + static int GetNestingLevel(IEntity entity) { int level = 0; @@ -162,7 +162,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return level; } } - + /// /// Gets whether the type is an open type (contains type parameters). /// @@ -184,7 +184,7 @@ namespace ICSharpCode.Decompiler.TypeSystem type.AcceptVisitor(v); return v.isOpen; } - + /// /// Gets the entity that owns the type parameters occurring in the specified type. /// If both class and method type parameters are present, the method is returned. @@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.TypeSystem type.AcceptVisitor(v); return v.typeParameterOwner; } - + /// /// Gets whether the type is unbound (is a generic type, but no type arguments were provided). /// @@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(type)); return (type is ITypeDefinition || type is UnknownType) && type.TypeParameterCount > 0; } - + /// /// Gets whether the type is the specified known type. /// For generic known types, this returns true for any parameterization of the type (and also for the definition itself). @@ -273,7 +273,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; } #endregion - + public static IType SkipModifiers(this IType ty) { while (ty is ModifiedType mt) { @@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets all type definitions in the compilation. /// This may include types from referenced assemblies that are not accessible in the main assembly. /// - public static IEnumerable GetAllTypeDefinitions (this ICompilation compilation) + public static IEnumerable GetAllTypeDefinitions(this ICompilation compilation) { return compilation.Modules.SelectMany(a => a.TypeDefinitions); } @@ -301,12 +301,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets all top level type definitions in the compilation. /// This may include types from referenced assemblies that are not accessible in the main assembly. /// - public static IEnumerable GetTopLevelTypeDefinitions (this ICompilation compilation) + public static IEnumerable GetTopLevelTypeDefinitions(this ICompilation compilation) { return compilation.Modules.SelectMany(a => a.TopLevelTypeDefinitions); } #endregion - + #region Resolve on collections public static IReadOnlyList Resolve(this IList typeReferences, ITypeResolveContext context) { @@ -317,11 +317,11 @@ namespace ICSharpCode.Decompiler.TypeSystem else return new ProjectedList(context, typeReferences, (c, t) => t.Resolve(c)); } - + // There is intentionally no Resolve() overload for IList: the resulting IList would // contains nulls when there are resolve errors. #endregion - + #region IAssembly.GetTypeDefinition() /// /// Retrieves the specified type in this compilation. @@ -345,7 +345,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return new UnknownType(fullTypeName); } - + /// /// Gets the type definition for the specified unresolved type. /// Returns null if the unresolved type does not belong to this assembly. @@ -368,7 +368,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return typeDef; } - + static ITypeDefinition FindNestedType(ITypeDefinition typeDef, string name, int typeParameterCount) { foreach (var nestedType in typeDef.NestedTypes) { @@ -378,7 +378,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; } #endregion - + #region IEntity.GetAttribute /// /// Gets whether the entity has an attribute of the specified attribute type (or derived attribute types). @@ -390,7 +390,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// (if the given in an override) /// should be returned. /// - public static bool HasAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit=false) + public static bool HasAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = false) { return GetAttribute(entity, attributeType, inherit) != null; } @@ -410,7 +410,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// If inherit is true, an from the entity itself will be returned if possible; /// and the base entity will only be searched if none exists. /// - public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit=false) + public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = false) { return GetAttributes(entity, inherit).FirstOrDefault(a => a.AttributeType.IsKnownType(attributeType)); } @@ -478,11 +478,11 @@ namespace ICSharpCode.Decompiler.TypeSystem public static ITypeDefinition GetTypeDefinition(this IModule module, string namespaceName, string name, int typeParameterCount = 0) { if (module == null) - throw new ArgumentNullException ("assembly"); - return module.GetTypeDefinition (new TopLevelTypeName (namespaceName, name, typeParameterCount)); + throw new ArgumentNullException("assembly"); + return module.GetTypeDefinition(new TopLevelTypeName(namespaceName, name, typeParameterCount)); } #endregion - + #region ResolveResult public static ISymbol GetSymbol(this ResolveResult rr) { @@ -495,7 +495,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } else if (rr is ConversionResolveResult) { return ((ConversionResolveResult)rr).Input.GetSymbol(); } - + return null; } #endregion @@ -560,7 +560,12 @@ namespace ICSharpCode.Decompiler.TypeSystem public static IModule FindModuleByReference(this ICompilation compilation, IAssemblyReference assemblyName) { foreach (var module in compilation.Modules) { - if (module.FullAssemblyName == assemblyName.FullName) { + if (string.Equals(module.FullAssemblyName, assemblyName.FullName, StringComparison.OrdinalIgnoreCase)) { + return module; + } + } + foreach (var module in compilation.Modules) { + if (string.Equals(module.Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase)) { return module; } } From 62b8ab39f1063ecf5ed050dcfc2e5b1f038434dd Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 7 Aug 2020 12:51:21 +0200 Subject: [PATCH 68/92] Fix oversight from b788441c78cbbdaaf1d33e15837bfdbfee2e6fcd --- .../TypeSystem/Implementation/MinimalCorlib.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs index d98fe5d54..5874e8c29 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs @@ -206,7 +206,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation get { var baseType = KnownTypeReference.Get(typeCode).baseType; if (baseType != KnownTypeCode.None) - return new[] { corlib.typeDefinitions[(int)baseType] }; + return new[] { corlib.Compilation.FindType(baseType) }; else return EmptyList.Instance; } From 1c563a62a900091be68bd6225cbbb7d053ab4bef Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 7 Aug 2020 12:53:46 +0200 Subject: [PATCH 69/92] Fix #2090: ignore mscorlib references without public key token, when trying to resolve mscorlib. This will automatically fallback to .NET 4.0's mscorlib.dll. --- ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs | 3 +++ ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index a3f39db83..dcb2013bd 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -95,6 +95,9 @@ namespace ICSharpCode.Decompiler.Metadata public static string ToHexString(this IEnumerable bytes, int estimatedLength) { + if (bytes == null) + throw new ArgumentNullException(nameof(bytes)); + StringBuilder sb = new StringBuilder(estimatedLength * 2); foreach (var b in bytes) sb.AppendFormat("{0:x2}", b); diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 0b30cbfc4..f5245a5a2 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -398,6 +398,9 @@ namespace ICSharpCode.Decompiler.Metadata return typeof(object).Module.FullyQualifiedName; } + if (reference.PublicKeyToken == null) + return null; + string path; if (decompilerRuntime == DecompilerRuntime.Mono) { path = GetMonoMscorlibBasePath(version); From 8e67a22896095571f3ea89b90dba3fa91c3457a1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 7 Aug 2020 22:58:25 +0200 Subject: [PATCH 70/92] Update to Roslyn 3.7.0 --- .../ICSharpCode.Decompiler.Tests.csproj | 4 ++-- ILSpy.Tests/ILSpy.Tests.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index 915b06889..62b9b5535 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -42,8 +42,8 @@ - - + + diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj index 8dc71b75d..fb4a483a6 100644 --- a/ILSpy.Tests/ILSpy.Tests.csproj +++ b/ILSpy.Tests/ILSpy.Tests.csproj @@ -46,8 +46,8 @@ - - + + From cc850c27aaf3db8a967a8627726e9fd65abb13fc Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 7 Aug 2020 23:36:10 +0200 Subject: [PATCH 71/92] Add "Aggressive inlining" option --- ICSharpCode.Decompiler/DecompilerSettings.cs | 19 +++++++++++++++++++ .../IL/Transforms/ILInlining.cs | 10 +++++----- .../IL/Transforms/NamedArgumentTransform.cs | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 41dbedea1..32623ecd6 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -1423,6 +1423,25 @@ namespace ICSharpCode.Decompiler } } + bool aggressiveInlining = false; + + /// + /// If set to false (the default), the decompiler will inline local variables only when they occur + /// in a context where the C# compiler is known to emit compiler-generated locals. + /// If set to true, the decompiler will inline local variables whenever possible. + /// + [Category("DecompilerSettings.Other")] + [Description("DecompilerSettings.AggressiveInlining")] + public bool AggressiveInlining { + get { return aggressiveInlining; } + set { + if (aggressiveInlining != value) { + aggressiveInlining = value; + OnPropertyChanged(); + } + } + } + CSharpFormattingOptions csharpFormattingOptions; [Browsable(false)] diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index d821b934e..db93a64bc 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -53,15 +53,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms public void Run(Block block, int pos, StatementTransformContext context) { - InlineOneIfPossible(block, pos, OptionsForBlock(block, pos), context: context); + InlineOneIfPossible(block, pos, OptionsForBlock(block, pos, context), context: context); } - internal static InliningOptions OptionsForBlock(Block block, int pos) + internal static InliningOptions OptionsForBlock(Block block, int pos, ILTransformContext context) { InliningOptions options = InliningOptions.None; - if (IsCatchWhenBlock(block)) + if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block)) { options |= InliningOptions.Aggressive; - else { + } else { var function = block.Ancestors.OfType().FirstOrDefault(); var inst = block.Instructions[pos]; if (IsInConstructorInitializer(function, inst)) @@ -77,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms for (int i = instructions.Count - 1; i >= 0; i--) { if (instructions[i] is StLoc inst) { InliningOptions options = InliningOptions.None; - if (IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst)) + if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst)) options = InliningOptions.Aggressive; if (InlineOneIfPossible(block, i, options, context)) { modified = true; diff --git a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs index a1b74147a..3b4c2c3dd 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs @@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!context.Settings.NamedArguments) return; - var options = ILInlining.OptionsForBlock(block, pos); + var options = ILInlining.OptionsForBlock(block, pos, context); options |= InliningOptions.IntroduceNamedArguments; ILInlining.InlineOneIfPossible(block, pos, options, context: context); } From 4cc1d1f3ec06ff838dac3d6437d4d26d854adf35 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 13:57:35 +0200 Subject: [PATCH 72/92] Add resources for new options. --- ILSpy/Properties/Resources.Designer.cs | 583 +++++++++++++------------ ILSpy/Properties/Resources.resx | 9 + 2 files changed, 314 insertions(+), 278 deletions(-) diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 62e6bfb9b..32289de3d 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace ICSharpCode.ILSpy.Properties { /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 返回此类使用的缓存的 ResourceManager 实例。 + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 重写当前线程的 CurrentUICulture 属性 - /// 重写当前线程的 CurrentUICulture 属性。 + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _About 的本地化字符串。 + /// Looks up a localized string similar to _About. /// public static string _About { get { @@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Add To Main List 的本地化字符串。 + /// Looks up a localized string similar to _Add To Main List. /// public static string _AddMainList { get { @@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Check for Updates 的本地化字符串。 + /// Looks up a localized string similar to _Check for Updates. /// public static string _CheckUpdates { get { @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Collapse all tree nodes 的本地化字符串。 + /// Looks up a localized string similar to _Collapse all tree nodes. /// public static string _CollapseTreeNodes { get { @@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _File 的本地化字符串。 + /// Looks up a localized string similar to _File. /// public static string _File { get { @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Help 的本地化字符串。 + /// Looks up a localized string similar to _Help. /// public static string _Help { get { @@ -115,7 +115,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Load Dependencies 的本地化字符串。 + /// Looks up a localized string similar to _Load Dependencies. /// public static string _LoadDependencies { get { @@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _New 的本地化字符串。 + /// Looks up a localized string similar to _New. /// public static string _New { get { @@ -133,7 +133,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Open... 的本地化字符串。 + /// Looks up a localized string similar to _Open.... /// public static string _Open { get { @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Open Command Line Here 的本地化字符串。 + /// Looks up a localized string similar to _Open Command Line Here. /// public static string _OpenCommandLineHere { get { @@ -151,7 +151,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Open Containing Folder 的本地化字符串。 + /// Looks up a localized string similar to _Open Containing Folder. /// public static string _OpenContainingFolder { get { @@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Options... 的本地化字符串。 + /// Looks up a localized string similar to _Options.... /// public static string _Options { get { @@ -169,7 +169,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Reload 的本地化字符串。 + /// Looks up a localized string similar to _Reload. /// public static string _Reload { get { @@ -178,7 +178,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Remove 的本地化字符串。 + /// Looks up a localized string similar to _Remove. /// public static string _Remove { get { @@ -187,7 +187,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Remove Assemblies with load errors 的本地化字符串。 + /// Looks up a localized string similar to _Remove Assemblies with load errors. /// public static string _RemoveAssembliesWithLoadErrors { get { @@ -196,7 +196,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Reset 的本地化字符串。 + /// Looks up a localized string similar to _Reset. /// public static string _Reset { get { @@ -205,7 +205,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Resources 的本地化字符串。 + /// Looks up a localized string similar to Resources. /// public static string _Resources { get { @@ -214,7 +214,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Save Code... 的本地化字符串。 + /// Looks up a localized string similar to _Save Code.... /// public static string _SaveCode { get { @@ -223,7 +223,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Search: 的本地化字符串。 + /// Looks up a localized string similar to _Search:. /// public static string _Search { get { @@ -232,7 +232,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Search for: 的本地化字符串。 + /// Looks up a localized string similar to _Search for:. /// public static string _SearchFor { get { @@ -241,7 +241,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Show debug steps 的本地化字符串。 + /// Looks up a localized string similar to _Show debug steps. /// public static string _ShowDebugSteps { get { @@ -250,7 +250,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Toggle Folding 的本地化字符串。 + /// Looks up a localized string similar to Toggle Folding. /// public static string _ToggleFolding { get { @@ -259,7 +259,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _View 的本地化字符串。 + /// Looks up a localized string similar to _View. /// public static string _View { get { @@ -268,7 +268,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Window 的本地化字符串。 + /// Looks up a localized string similar to _Window. /// public static string _Window { get { @@ -277,7 +277,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 About 的本地化字符串。 + /// Looks up a localized string similar to About. /// public static string About { get { @@ -286,7 +286,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Add preconfigured list... 的本地化字符串。 + /// Looks up a localized string similar to Add preconfigured list.... /// public static string AddPreconfiguredList { get { @@ -295,7 +295,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Add shell integration 的本地化字符串。 + /// Looks up a localized string similar to Add shell integration. /// public static string AddShellIntegration { get { @@ -304,9 +304,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. + /// Looks up a localized string similar to This will add "{0}" to the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command" to allow opening .dll and .exe files from the Windows Explorer context menu. /// - ///Do you want to continue? 的本地化字符串。 + ///Do you want to continue?. /// public static string AddShellIntegrationMessage { get { @@ -315,7 +315,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 |All Files|*.* 的本地化字符串。 + /// Looks up a localized string similar to |All Files|*.*. /// public static string AllFiles { get { @@ -324,7 +324,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Allow multiple instances 的本地化字符串。 + /// Looks up a localized string similar to Allow multiple instances. /// public static string AllowMultipleInstances { get { @@ -333,7 +333,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Always use braces 的本地化字符串。 + /// Looks up a localized string similar to Always use braces. /// public static string AlwaysBraces { get { @@ -342,7 +342,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Analyze 的本地化字符串。 + /// Looks up a localized string similar to Analyze. /// public static string Analyze { get { @@ -351,7 +351,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Assemblies 的本地化字符串。 + /// Looks up a localized string similar to Assemblies. /// public static string Assemblies { get { @@ -360,7 +360,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Assembly 的本地化字符串。 + /// Looks up a localized string similar to Assembly. /// public static string Assembly { get { @@ -369,8 +369,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 The directory is not empty. File will be overwritten. - ///Are you sure you want to continue? 的本地化字符串。 + /// Looks up a localized string similar to The directory is not empty. File will be overwritten. + ///Are you sure you want to continue?. /// public static string AssemblySaveCodeDirectoryNotEmpty { get { @@ -379,7 +379,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Project Directory not empty 的本地化字符串。 + /// Looks up a localized string similar to Project Directory not empty. /// public static string AssemblySaveCodeDirectoryNotEmptyTitle { get { @@ -388,7 +388,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Automatically check for updates every week 的本地化字符串。 + /// Looks up a localized string similar to Automatically check for updates every week. /// public static string AutomaticallyCheckUpdatesEveryWeek { get { @@ -397,7 +397,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Back 的本地化字符串。 + /// Looks up a localized string similar to Back. /// public static string Back { get { @@ -406,7 +406,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Base Types 的本地化字符串。 + /// Looks up a localized string similar to Base Types. /// public static string BaseTypes { get { @@ -415,7 +415,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 C_lone 的本地化字符串。 + /// Looks up a localized string similar to C_lone. /// public static string C_lone { get { @@ -424,7 +424,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Cancel 的本地化字符串。 + /// Looks up a localized string similar to Cancel. /// public static string Cancel { get { @@ -433,7 +433,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. 的本地化字符串。 + /// Looks up a localized string similar to Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again.. /// public static string CannotAnalyzeMissingRef { get { @@ -442,7 +442,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'. 的本地化字符串。 + /// Looks up a localized string similar to Cannot create PDB file for {0}, because it does not contain a PE Debug Directory Entry of type 'CodeView'.. /// public static string CannotCreatePDBFile { get { @@ -451,7 +451,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Check again 的本地化字符串。 + /// Looks up a localized string similar to Check again. /// public static string CheckAgain { get { @@ -460,7 +460,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Checking... 的本地化字符串。 + /// Looks up a localized string similar to Checking.... /// public static string Checking { get { @@ -469,7 +469,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Check for updates 的本地化字符串。 + /// Looks up a localized string similar to Check for updates. /// public static string CheckUpdates { get { @@ -478,7 +478,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Close 的本地化字符串。 + /// Looks up a localized string similar to Close. /// public static string Close { get { @@ -487,7 +487,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Collapse all tree nodes 的本地化字符串。 + /// Looks up a localized string similar to Collapse all tree nodes. /// public static string CollapseTreeNodes { get { @@ -496,7 +496,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Copy 的本地化字符串。 + /// Looks up a localized string similar to Copy. /// public static string Copy { get { @@ -505,7 +505,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Copy error message 的本地化字符串。 + /// Looks up a localized string similar to Copy error message. /// public static string CopyErrorMessage { get { @@ -514,7 +514,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Copy FQ Name 的本地化字符串。 + /// Looks up a localized string similar to Copy FQ Name. /// public static string CopyName { get { @@ -523,7 +523,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Create 的本地化字符串。 + /// Looks up a localized string similar to Create. /// public static string Create { get { @@ -532,7 +532,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Culture 的本地化字符串。 + /// Looks up a localized string similar to Culture. /// public static string CultureLabel { get { @@ -541,7 +541,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 DEBUG -- Decompile All 的本地化字符串。 + /// Looks up a localized string similar to DEBUG -- Decompile All. /// public static string DEBUGDecompile { get { @@ -550,7 +550,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 DEBUG -- Decompile 100x 的本地化字符串。 + /// Looks up a localized string similar to DEBUG -- Decompile 100x. /// public static string DEBUGDecompile100x { get { @@ -559,7 +559,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 DEBUG -- Disassemble All 的本地化字符串。 + /// Looks up a localized string similar to DEBUG -- Disassemble All. /// public static string DEBUGDisassemble { get { @@ -568,7 +568,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 DEBUG -- Dump PDB as XML 的本地化字符串。 + /// Looks up a localized string similar to DEBUG -- Dump PDB as XML. /// public static string DEBUGDumpPDBAsXML { get { @@ -577,7 +577,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Debug Steps 的本地化字符串。 + /// Looks up a localized string similar to Debug Steps. /// public static string DebugSteps { get { @@ -586,7 +586,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Debug this step 的本地化字符串。 + /// Looks up a localized string similar to Debug this step. /// public static string DebugThisStep { get { @@ -595,7 +595,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile 的本地化字符串。 + /// Looks up a localized string similar to Decompile. /// public static string Decompile { get { @@ -604,7 +604,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompiler 的本地化字符串。 + /// Looks up a localized string similar to Decompiler. /// public static string Decompiler { get { @@ -613,7 +613,16 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Allow extension 'Add' methods in collection initializer expressions 的本地化字符串。 + /// Looks up a localized string similar to Always inline local variables if possible. + /// + public static string DecompilerSettings_AggressiveInlining { + get { + return ResourceManager.GetString("DecompilerSettings.AggressiveInlining", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Allow extension 'Add' methods in collection initializer expressions. /// public static string DecompilerSettings_AllowExtensionAddMethodsInCollectionInitializerExpressions { get { @@ -622,7 +631,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use 'ref' extension methods 的本地化字符串。 + /// Looks up a localized string similar to Use 'ref' extension methods. /// public static string DecompilerSettings_AllowExtensionMethodSyntaxOnRef { get { @@ -631,7 +640,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Always cast targets of explicit interface implementation calls 的本地化字符串。 + /// Looks up a localized string similar to Always cast targets of explicit interface implementation calls. /// public static string DecompilerSettings_AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { get { @@ -640,7 +649,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Always show enum member values 的本地化字符串。 + /// Looks up a localized string similar to Always show enum member values. /// public static string DecompilerSettings_AlwaysShowEnumMemberValues { get { @@ -649,7 +658,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Always use braces 的本地化字符串。 + /// Looks up a localized string similar to Always use braces. /// public static string DecompilerSettings_AlwaysUseBraces { get { @@ -658,7 +667,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Apply Windows Runtime projections on loaded assemblies 的本地化字符串。 + /// Looks up a localized string similar to Apply Windows Runtime projections on loaded assemblies. /// public static string DecompilerSettings_ApplyWindowsRuntimeProjectionsOnLoadedAssemblies { get { @@ -667,7 +676,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Array initializer expressions 的本地化字符串。 + /// Looks up a localized string similar to Array initializer expressions. /// public static string DecompilerSettings_ArrayInitializerExpressions { get { @@ -676,7 +685,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile async IAsyncEnumerator methods 的本地化字符串。 + /// Looks up a localized string similar to Decompile async IAsyncEnumerator methods. /// public static string DecompilerSettings_AsyncEnumerator { get { @@ -685,7 +694,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile ?. and ?[] operators 的本地化字符串。 + /// Looks up a localized string similar to Decompile ?. and ?[] operators. /// public static string DecompilerSettings_DecompileAndOperators { get { @@ -694,7 +703,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile anonymous methods/lambdas 的本地化字符串。 + /// Looks up a localized string similar to Decompile anonymous methods/lambdas. /// public static string DecompilerSettings_DecompileAnonymousMethodsLambdas { get { @@ -703,7 +712,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile anonymous types 的本地化字符串。 + /// Looks up a localized string similar to Decompile anonymous types. /// public static string DecompilerSettings_DecompileAnonymousTypes { get { @@ -712,7 +721,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile async methods 的本地化字符串。 + /// Looks up a localized string similar to Decompile async methods. /// public static string DecompilerSettings_DecompileAsyncMethods { get { @@ -721,7 +730,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile automatic events 的本地化字符串。 + /// Looks up a localized string similar to Decompile automatic events. /// public static string DecompilerSettings_DecompileAutomaticEvents { get { @@ -730,7 +739,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile automatic properties 的本地化字符串。 + /// Looks up a localized string similar to Decompile automatic properties. /// public static string DecompilerSettings_DecompileAutomaticProperties { get { @@ -739,7 +748,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile await in catch/finally blocks 的本地化字符串。 + /// Looks up a localized string similar to Decompile await in catch/finally blocks. /// public static string DecompilerSettings_DecompileAwaitInCatchFinallyBlocks { get { @@ -748,7 +757,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile C# 1.0 'public unsafe fixed int arr[10];' members 的本地化字符串。 + /// Looks up a localized string similar to Decompile C# 1.0 'public unsafe fixed int arr[10];' members. /// public static string DecompilerSettings_DecompileC10PublicUnsafeFixedIntArr10Members { get { @@ -757,7 +766,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile [DecimalConstant(...)] as simple literal values 的本地化字符串。 + /// Looks up a localized string similar to Decompile [DecimalConstant(...)] as simple literal values. /// public static string DecompilerSettings_DecompileDecimalConstantAsSimpleLiteralValues { get { @@ -766,7 +775,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile enumerators (yield return) 的本地化字符串。 + /// Looks up a localized string similar to Decompile enumerators (yield return). /// public static string DecompilerSettings_DecompileEnumeratorsYieldReturn { get { @@ -775,7 +784,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile expression trees 的本地化字符串。 + /// Looks up a localized string similar to Decompile expression trees. /// public static string DecompilerSettings_DecompileExpressionTrees { get { @@ -784,7 +793,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile use of the 'dynamic' type 的本地化字符串。 + /// Looks up a localized string similar to Decompile use of the 'dynamic' type. /// public static string DecompilerSettings_DecompileUseOfTheDynamicType { get { @@ -793,7 +802,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect awaited using and foreach statements 的本地化字符串。 + /// Looks up a localized string similar to Detect awaited using and foreach statements. /// public static string DecompilerSettings_DetectAsyncUsingAndForeachStatements { get { @@ -802,7 +811,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect foreach statements 的本地化字符串。 + /// Looks up a localized string similar to Detect foreach statements. /// public static string DecompilerSettings_DetectForeachStatements { get { @@ -811,7 +820,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect lock statements 的本地化字符串。 + /// Looks up a localized string similar to Detect lock statements. /// public static string DecompilerSettings_DetectLockStatements { get { @@ -820,7 +829,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect switch on string 的本地化字符串。 + /// Looks up a localized string similar to Detect switch on string. /// public static string DecompilerSettings_DetectSwitchOnString { get { @@ -829,7 +838,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect tuple comparisons 的本地化字符串。 + /// Looks up a localized string similar to Detect tuple comparisons. /// public static string DecompilerSettings_DetectTupleComparisons { get { @@ -838,7 +847,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Detect using statements 的本地化字符串。 + /// Looks up a localized string similar to Detect using statements. /// public static string DecompilerSettings_DetectUsingStatements { get { @@ -847,7 +856,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Dictionary initializer expressions 的本地化字符串。 + /// Looks up a localized string similar to Dictionary initializer expressions. /// public static string DecompilerSettings_DictionaryInitializerExpressions { get { @@ -856,7 +865,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Transform to do-while, if possible 的本地化字符串。 + /// Looks up a localized string similar to Transform to do-while, if possible. /// public static string DecompilerSettings_DoWhileStatement { get { @@ -865,7 +874,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Transform to for, if possible 的本地化字符串。 + /// Looks up a localized string similar to Transform to for, if possible. /// public static string DecompilerSettings_ForStatement { get { @@ -874,7 +883,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 F#-specific options 的本地化字符串。 + /// Looks up a localized string similar to F#-specific options. /// public static string DecompilerSettings_FSpecificOptions { get { @@ -883,7 +892,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Include XML documentation comments in the decompiled code 的本地化字符串。 + /// Looks up a localized string similar to Include XML documentation comments in the decompiled code. /// public static string DecompilerSettings_IncludeXMLDocumentationCommentsInTheDecompiledCode { get { @@ -892,7 +901,16 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Insert using declarations 的本地化字符串。 + /// Looks up a localized string similar to Allow init; accessors. + /// + public static string DecompilerSettings_InitAccessors { + get { + return ResourceManager.GetString("DecompilerSettings.InitAccessors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Insert using declarations. /// public static string DecompilerSettings_InsertUsingDeclarations { get { @@ -901,7 +919,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Introduce local functions 的本地化字符串。 + /// Looks up a localized string similar to Introduce local functions. /// public static string DecompilerSettings_IntroduceLocalFunctions { get { @@ -910,7 +928,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Introduce static local functions 的本地化字符串。 + /// Looks up a localized string similar to Introduce static local functions. /// public static string DecompilerSettings_IntroduceStaticLocalFunctions { get { @@ -919,7 +937,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs 的本地化字符串。 + /// Looks up a localized string similar to IsByRefLikeAttribute should be replaced with 'ref' modifiers on structs. /// public static string DecompilerSettings_IsByRefLikeAttributeShouldBeReplacedWithRefModifiersOnStructs { get { @@ -928,7 +946,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters 的本地化字符串。 + /// Looks up a localized string similar to IsReadOnlyAttribute should be replaced with 'readonly'/'in' modifiers on structs/parameters. /// public static string DecompilerSettings_IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters { get { @@ -938,7 +956,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints 的本地化字符串。 + /// Looks up a localized string similar to IsUnmanagedAttribute on type parameters should be replaced with 'unmanaged' constraints. /// public static string DecompilerSettings_IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints { get { @@ -948,7 +966,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use nint/nuint types 的本地化字符串。 + /// Looks up a localized string similar to Use nint/nuint types. /// public static string DecompilerSettings_NativeIntegers { get { @@ -957,7 +975,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Nullable reference types 的本地化字符串。 + /// Looks up a localized string similar to Nullable reference types. /// public static string DecompilerSettings_NullableReferenceTypes { get { @@ -966,7 +984,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Object/collection initializer expressions 的本地化字符串。 + /// Looks up a localized string similar to Object/collection initializer expressions. /// public static string DecompilerSettings_ObjectCollectionInitializerExpressions { get { @@ -975,7 +993,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Other 的本地化字符串。 + /// Looks up a localized string similar to Other. /// public static string DecompilerSettings_Other { get { @@ -984,7 +1002,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Ranges 的本地化字符串。 + /// Looks up a localized string similar to Ranges. /// public static string DecompilerSettings_Ranges { get { @@ -993,7 +1011,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Read-only methods 的本地化字符串。 + /// Looks up a localized string similar to Read-only methods. /// public static string DecompilerSettings_ReadOnlyMethods { get { @@ -1002,7 +1020,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove dead and side effect free code (use with caution!) 的本地化字符串。 + /// Looks up a localized string similar to Remove dead and side effect free code (use with caution!). /// public static string DecompilerSettings_RemoveDeadAndSideEffectFreeCodeUseWithCaution { get { @@ -1011,7 +1029,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove dead stores (use with caution!) 的本地化字符串。 + /// Looks up a localized string similar to Remove dead stores (use with caution!). /// public static string DecompilerSettings_RemoveDeadStores { get { @@ -1020,7 +1038,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove optional arguments, if possible 的本地化字符串。 + /// Looks up a localized string similar to Remove optional arguments, if possible. /// public static string DecompilerSettings_RemoveOptionalArgumentsIfPossible { get { @@ -1029,7 +1047,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible 的本地化字符串。 + /// Looks up a localized string similar to Separate local variable declarations and initializers (int x = 5; -> int x; x = 5;), if possible. /// public static string DecompilerSettings_SeparateLocalVariableDeclarations { get { @@ -1038,7 +1056,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 + /// Looks up a localized string similar to Show info from debug symbols, if available. /// public static string DecompilerSettings_ShowInfoFromDebugSymbolsIfAvailable { get { @@ -1047,7 +1065,16 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use discards 的本地化字符串。 + /// Looks up a localized string similar to Switch expressions. + /// + public static string DecompilerSettings_SwitchExpressions { + get { + return ResourceManager.GetString("DecompilerSettings.SwitchExpressions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use discards. /// public static string DecompilerSettings_UseDiscards { get { @@ -1056,7 +1083,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use expression-bodied member syntax for get-only properties 的本地化字符串。 + /// Looks up a localized string similar to Use expression-bodied member syntax for get-only properties. /// public static string DecompilerSettings_UseExpressionBodiedMemberSyntaxForGetOnlyProperties { get { @@ -1065,7 +1092,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use extension method syntax 的本地化字符串。 + /// Looks up a localized string similar to Use extension method syntax. /// public static string DecompilerSettings_UseExtensionMethodSyntax { get { @@ -1074,7 +1101,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use implicit conversions between tuple types 的本地化字符串。 + /// Looks up a localized string similar to Use implicit conversions between tuple types. /// public static string DecompilerSettings_UseImplicitConversionsBetweenTupleTypes { get { @@ -1083,7 +1110,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use implicit method group conversions 的本地化字符串。 + /// Looks up a localized string similar to Use implicit method group conversions. /// public static string DecompilerSettings_UseImplicitMethodGroupConversions { get { @@ -1092,7 +1119,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use lambda syntax, if possible 的本地化字符串。 + /// Looks up a localized string similar to Use lambda syntax, if possible. /// public static string DecompilerSettings_UseLambdaSyntaxIfPossible { get { @@ -1101,7 +1128,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use lifted operators for nullables 的本地化字符串。 + /// Looks up a localized string similar to Use lifted operators for nullables. /// public static string DecompilerSettings_UseLiftedOperatorsForNullables { get { @@ -1110,7 +1137,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use LINQ expression syntax 的本地化字符串。 + /// Looks up a localized string similar to Use LINQ expression syntax. /// public static string DecompilerSettings_UseLINQExpressionSyntax { get { @@ -1119,7 +1146,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use named arguments 的本地化字符串。 + /// Looks up a localized string similar to Use named arguments. /// public static string DecompilerSettings_UseNamedArguments { get { @@ -1128,7 +1155,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use non-trailing named arguments 的本地化字符串。 + /// Looks up a localized string similar to Use non-trailing named arguments. /// public static string DecompilerSettings_UseNonTrailingNamedArguments { get { @@ -1137,7 +1164,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use out variable declarations 的本地化字符串。 + /// Looks up a localized string similar to Use out variable declarations. /// public static string DecompilerSettings_UseOutVariableDeclarations { get { @@ -1146,7 +1173,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use pattern-based fixed statement 的本地化字符串。 + /// Looks up a localized string similar to Use pattern-based fixed statement. /// public static string DecompilerSettings_UsePatternBasedFixedStatement { get { @@ -1155,7 +1182,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use new SDK style format for generated project files (*.csproj) 的本地化字符串。 + /// Looks up a localized string similar to Use new SDK style format for generated project files (*.csproj). /// public static string DecompilerSettings_UseSdkStyleProjectFormat { get { @@ -1164,7 +1191,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use stackalloc initializer syntax 的本地化字符串。 + /// Looks up a localized string similar to Use stackalloc initializer syntax. /// public static string DecompilerSettings_UseStackallocInitializerSyntax { get { @@ -1173,7 +1200,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use string interpolation 的本地化字符串。 + /// Looks up a localized string similar to Use string interpolation. /// public static string DecompilerSettings_UseStringInterpolation { get { @@ -1182,7 +1209,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use throw expressions 的本地化字符串。 + /// Looks up a localized string similar to Use throw expressions. /// public static string DecompilerSettings_UseThrowExpressions { get { @@ -1191,7 +1218,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use tuple type syntax 的本地化字符串。 + /// Looks up a localized string similar to Use tuple type syntax. /// public static string DecompilerSettings_UseTupleTypeSyntax { get { @@ -1200,7 +1227,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 + /// Looks up a localized string similar to Use variable names from debug symbols, if available. /// public static string DecompilerSettings_UseVariableNamesFromDebugSymbolsIfAvailable { get { @@ -1209,7 +1236,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 VB-specific options 的本地化字符串。 + /// Looks up a localized string similar to VB-specific options. /// public static string DecompilerSettings_VBSpecificOptions { get { @@ -1218,7 +1245,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls. 的本地化字符串。 + /// Looks up a localized string similar to The settings selected below are applied to the decompiler output in combination with the selection in the language drop-down. Selecting a lower language version in the drop-down will deactivate all selected options of the higher versions. Note that some settings implicitly depend on each other, e.g.: LINQ expressions cannot be introduced without first transforming static calls to extension method calls.. /// public static string DecompilerSettingsPanelLongText { get { @@ -1227,7 +1254,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompile to new tab 的本地化字符串。 + /// Looks up a localized string similar to Decompile to new tab. /// public static string DecompileToNewPanel { get { @@ -1236,7 +1263,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Decompiling... 的本地化字符串。 + /// Looks up a localized string similar to Decompiling.... /// public static string Decompiling { get { @@ -1245,7 +1272,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Dependencies 的本地化字符串。 + /// Looks up a localized string similar to Dependencies. /// public static string Dependencies { get { @@ -1254,7 +1281,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Derived Types 的本地化字符串。 + /// Looks up a localized string similar to Derived Types. /// public static string DerivedTypes { get { @@ -1263,7 +1290,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Display 的本地化字符串。 + /// Looks up a localized string similar to Display. /// public static string Display { get { @@ -1272,7 +1299,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Display Code 的本地化字符串。 + /// Looks up a localized string similar to Display Code. /// public static string DisplayCode { get { @@ -1281,7 +1308,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Font: 的本地化字符串。 + /// Looks up a localized string similar to Font:. /// public static string DisplaySettingsPanel_Font { get { @@ -1290,7 +1317,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Download 的本地化字符串。 + /// Looks up a localized string similar to Download. /// public static string Download { get { @@ -1299,7 +1326,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 E_xit 的本地化字符串。 + /// Looks up a localized string similar to E_xit. /// public static string E_xit { get { @@ -1308,7 +1335,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Editor 的本地化字符串。 + /// Looks up a localized string similar to Editor. /// public static string Editor { get { @@ -1317,7 +1344,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Enable folding on all blocks in braces 的本地化字符串。 + /// Looks up a localized string similar to Enable folding on all blocks in braces. /// public static string EnableFoldingBlocksBraces { get { @@ -1326,7 +1353,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Enable word wrap 的本地化字符串。 + /// Looks up a localized string similar to Enable word wrap. /// public static string EnableWordWrap { get { @@ -1335,7 +1362,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Enter a list name: 的本地化字符串。 + /// Looks up a localized string similar to Enter a list name:. /// public static string EnterListName { get { @@ -1344,7 +1371,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Exit 的本地化字符串。 + /// Looks up a localized string similar to Exit. /// public static string Exit { get { @@ -1353,7 +1380,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Expand member definitions after decompilation 的本地化字符串。 + /// Looks up a localized string similar to Expand member definitions after decompilation. /// public static string ExpandMemberDefinitionsAfterDecompilation { get { @@ -1362,7 +1389,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Expand using declarations after decompilation 的本地化字符串。 + /// Looks up a localized string similar to Expand using declarations after decompilation. /// public static string ExpandUsingDeclarationsAfterDecompilation { get { @@ -1371,7 +1398,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Folding 的本地化字符串。 + /// Looks up a localized string similar to Folding. /// public static string Folding { get { @@ -1380,7 +1407,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Font 的本地化字符串。 + /// Looks up a localized string similar to Font. /// public static string Font { get { @@ -1389,7 +1416,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Forward 的本地化字符串。 + /// Looks up a localized string similar to Forward. /// public static string Forward { get { @@ -1398,7 +1425,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Generate portable PDB 的本地化字符串。 + /// Looks up a localized string similar to Generate portable PDB. /// public static string GeneratePortable { get { @@ -1407,7 +1434,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Generation complete in {0} seconds. 的本地化字符串。 + /// Looks up a localized string similar to Generation complete in {0} seconds.. /// public static string GenerationCompleteInSeconds { get { @@ -1416,7 +1443,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Generation was cancelled. 的本地化字符串。 + /// Looks up a localized string similar to Generation was cancelled.. /// public static string GenerationWasCancelled { get { @@ -1425,7 +1452,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Go to token 的本地化字符串。 + /// Looks up a localized string similar to Go to token. /// public static string GoToToken { get { @@ -1434,7 +1461,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Hide empty metadata tables from tree view 的本地化字符串。 + /// Looks up a localized string similar to Hide empty metadata tables from tree view. /// public static string HideEmptyMetadataTables { get { @@ -1443,7 +1470,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Highlight matching braces 的本地化字符串。 + /// Looks up a localized string similar to Highlight matching braces. /// public static string HighlightMatchingBraces { get { @@ -1452,7 +1479,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 ILSpyAboutPage.txt 的本地化字符串。 + /// Looks up a localized string similar to ILSpyAboutPage.txt. /// public static string ILSpyAboutPageTxt { get { @@ -1461,7 +1488,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 ILSpy version 的本地化字符串。 + /// Looks up a localized string similar to ILSpy version . /// public static string ILSpyVersion { get { @@ -1470,7 +1497,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 A new ILSpy version is available. 的本地化字符串。 + /// Looks up a localized string similar to A new ILSpy version is available.. /// public static string ILSpyVersionAvailable { get { @@ -1479,7 +1506,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Indentation 的本地化字符串。 + /// Looks up a localized string similar to Indentation. /// public static string Indentation { get { @@ -1488,7 +1515,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Indent size: 的本地化字符串。 + /// Looks up a localized string similar to Indent size:. /// public static string IndentSize { get { @@ -1497,7 +1524,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Insert using declarations 的本地化字符串。 + /// Looks up a localized string similar to Insert using declarations. /// public static string InsertUsingDeclarations { get { @@ -1506,7 +1533,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Are you sure that you want to delete the selected assembly list? 的本地化字符串。 + /// Looks up a localized string similar to Are you sure that you want to delete the selected assembly list?. /// public static string ListDeleteConfirmation { get { @@ -1515,7 +1542,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 A list with the same name was found. 的本地化字符串。 + /// Looks up a localized string similar to A list with the same name was found.. /// public static string ListExistsAlready { get { @@ -1524,7 +1551,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Are you sure that you want to remove all assembly lists and recreate the default assembly lists? 的本地化字符串。 + /// Looks up a localized string similar to Are you sure that you want to remove all assembly lists and recreate the default assembly lists?. /// public static string ListsResetConfirmation { get { @@ -1533,7 +1560,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Load assemblies that were loaded in the last instance. 的本地化字符串。 + /// Looks up a localized string similar to Load assemblies that were loaded in the last instance.. /// public static string LoadAssembliesThatWereLoadedInTheLastInstance { get { @@ -1542,7 +1569,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Loading... 的本地化字符串。 + /// Looks up a localized string similar to Loading.... /// public static string Loading { get { @@ -1551,7 +1578,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Location 的本地化字符串。 + /// Looks up a localized string similar to Location. /// public static string Location { get { @@ -1560,7 +1587,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Manage assembly _lists... 的本地化字符串。 + /// Looks up a localized string similar to Manage assembly _lists.... /// public static string ManageAssembly_Lists { get { @@ -1569,7 +1596,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Manage Assembly Lists 的本地化字符串。 + /// Looks up a localized string similar to Manage Assembly Lists. /// public static string ManageAssemblyLists { get { @@ -1578,7 +1605,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Misc 的本地化字符串。 + /// Looks up a localized string similar to Misc. /// public static string Misc { get { @@ -1587,7 +1614,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Name 的本地化字符串。 + /// Looks up a localized string similar to Name. /// public static string Name { get { @@ -1596,7 +1623,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Navigation 的本地化字符串。 + /// Looks up a localized string similar to Navigation. /// public static string Navigation { get { @@ -1605,8 +1632,8 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Navigation failed because the target is hidden or a compiler-generated class.\n - ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again. 的本地化字符串。 + /// Looks up a localized string similar to Navigation failed because the target is hidden or a compiler-generated class.\n + ///Please disable all filters that might hide the item (i.e. activate "View > Show internal types and members") and try again.. /// public static string NavigationFailed { get { @@ -1615,7 +1642,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 New list 的本地化字符串。 + /// Looks up a localized string similar to New list. /// public static string NewList { get { @@ -1624,7 +1651,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 New Tab 的本地化字符串。 + /// Looks up a localized string similar to New Tab. /// public static string NewTab { get { @@ -1633,7 +1660,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Nuget Package Browser 的本地化字符串。 + /// Looks up a localized string similar to Nuget Package Browser. /// public static string NugetPackageBrowser { get { @@ -1642,7 +1669,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 OK 的本地化字符串。 + /// Looks up a localized string similar to OK. /// public static string OK { get { @@ -1651,7 +1678,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Open 的本地化字符串。 + /// Looks up a localized string similar to Open. /// public static string Open { get { @@ -1660,7 +1687,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Open Explorer 的本地化字符串。 + /// Looks up a localized string similar to Open Explorer. /// public static string OpenExplorer { get { @@ -1669,7 +1696,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Open From GAC 的本地化字符串。 + /// Looks up a localized string similar to Open From GAC. /// public static string OpenFrom { get { @@ -1678,7 +1705,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Open from _GAC... 的本地化字符串。 + /// Looks up a localized string similar to Open from _GAC.... /// public static string OpenFrom_GAC { get { @@ -1687,7 +1714,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Delete 的本地化字符串。 + /// Looks up a localized string similar to _Delete. /// public static string OpenListDialog__Delete { get { @@ -1696,7 +1723,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Open 的本地化字符串。 + /// Looks up a localized string similar to _Open. /// public static string OpenListDialog__Open { get { @@ -1705,7 +1732,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Options 的本地化字符串。 + /// Looks up a localized string similar to Options. /// public static string Options { get { @@ -1714,7 +1741,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Other 的本地化字符串。 + /// Looks up a localized string similar to Other. /// public static string Other { get { @@ -1723,7 +1750,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Other options 的本地化字符串。 + /// Looks up a localized string similar to Other options. /// public static string OtherOptions { get { @@ -1732,7 +1759,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Other Resources 的本地化字符串。 + /// Looks up a localized string similar to Other Resources. /// public static string OtherResources { get { @@ -1741,7 +1768,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Portable PDB|*.pdb|All files|*.* 的本地化字符串。 + /// Looks up a localized string similar to Portable PDB|*.pdb|All files|*.*. /// public static string PortablePDBPdbAllFiles { get { @@ -1750,7 +1777,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. 的本地化字符串。 + /// Looks up a localized string similar to for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.. /// public static string PropertyManuallyMissingReferencesListLoadedAssemblies { get { @@ -1759,7 +1786,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Public Key Token 的本地化字符串。 + /// Looks up a localized string similar to Public Key Token. /// public static string PublicToken { get { @@ -1768,7 +1795,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 R_ename 的本地化字符串。 + /// Looks up a localized string similar to R_ename. /// public static string R_ename { get { @@ -1777,7 +1804,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Reference Name 的本地化字符串。 + /// Looks up a localized string similar to Reference Name. /// public static string ReferenceName { get { @@ -1786,7 +1813,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 References 的本地化字符串。 + /// Looks up a localized string similar to References. /// public static string References { get { @@ -1795,7 +1822,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Reload all assemblies 的本地化字符串。 + /// Looks up a localized string similar to Reload all assemblies. /// public static string RefreshCommand_ReloadAssemblies { get { @@ -1804,7 +1831,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Reload all assemblies 的本地化字符串。 + /// Looks up a localized string similar to Reload all assemblies. /// public static string ReloadAssemblies { get { @@ -1813,7 +1840,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove 的本地化字符串。 + /// Looks up a localized string similar to Remove. /// public static string Remove { get { @@ -1822,7 +1849,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove dead and side effect free code 的本地化字符串。 + /// Looks up a localized string similar to Remove dead and side effect free code. /// public static string RemoveDeadSideEffectFreeCode { get { @@ -1831,7 +1858,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Remove shell integration 的本地化字符串。 + /// Looks up a localized string similar to Remove shell integration. /// public static string RemoveShellIntegration { get { @@ -1840,9 +1867,9 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". + /// Looks up a localized string similar to This will remove "{0}" from the registry at "HKCU\Software\Classes\dllfile\shell\Open with ILSpy\command" and "HKCU\Software\Classes\exefile\shell\Open with ILSpy\command". /// - ///Do you want to continue? 的本地化字符串。 + ///Do you want to continue?. /// public static string RemoveShellIntegrationMessage { get { @@ -1851,7 +1878,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Rename list 的本地化字符串。 + /// Looks up a localized string similar to Rename list. /// public static string RenameList { get { @@ -1860,7 +1887,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Reset to defaults 的本地化字符串。 + /// Looks up a localized string similar to Reset to defaults. /// public static string ResetToDefaults { get { @@ -1869,7 +1896,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Do you really want to load the default settings for the active page? 的本地化字符串。 + /// Looks up a localized string similar to Do you really want to load the default settings for the active page?. /// public static string ResetToDefaultsConfirmationMessage { get { @@ -1878,7 +1905,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Resources file (*.resources)|*.resources|Resource XML file|*.resx 的本地化字符串。 + /// Looks up a localized string similar to Resources file (*.resources)|*.resources|Resource XML file|*.resx. /// public static string ResourcesFileFilter { get { @@ -1887,7 +1914,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Save 的本地化字符串。 + /// Looks up a localized string similar to Save. /// public static string Save { get { @@ -1896,7 +1923,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Save Code 的本地化字符串。 + /// Looks up a localized string similar to Save Code. /// public static string SaveCode { get { @@ -1905,7 +1932,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search... 的本地化字符串。 + /// Looks up a localized string similar to Search.... /// public static string Search { get { @@ -1914,7 +1941,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search aborted, more than 1000 results found. 的本地化字符串。 + /// Looks up a localized string similar to Search aborted, more than 1000 results found.. /// public static string SearchAbortedMoreThan1000ResultsFound { get { @@ -1923,7 +1950,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search (Ctrl+Shift+F or Ctrl+E) 的本地化字符串。 + /// Looks up a localized string similar to Search (Ctrl+Shift+F or Ctrl+E). /// public static string SearchCtrlShiftFOrCtrlE { get { @@ -1932,7 +1959,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Searching... 的本地化字符串。 + /// Looks up a localized string similar to Searching.... /// public static string Searching { get { @@ -1941,7 +1968,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search Microsoft Docs... 的本地化字符串。 + /// Looks up a localized string similar to Search Microsoft Docs.... /// public static string SearchMSDN { get { @@ -1950,7 +1977,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search 的本地化字符串。 + /// Looks up a localized string similar to Search. /// public static string SearchPane_Search { get { @@ -1959,7 +1986,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select All 的本地化字符串。 + /// Looks up a localized string similar to Select All. /// public static string Select { get { @@ -1968,7 +1995,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select assemblies to open: 的本地化字符串。 + /// Looks up a localized string similar to Select assemblies to open:. /// public static string SelectAssembliesOpen { get { @@ -1977,7 +2004,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select a list of assemblies 的本地化字符串。 + /// Looks up a localized string similar to Select a list of assemblies. /// public static string SelectAssemblyListDropdownTooltip { get { @@ -1986,7 +2013,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select language to decompile to 的本地化字符串。 + /// Looks up a localized string similar to Select language to decompile to. /// public static string SelectLanguageDropdownTooltip { get { @@ -1995,7 +2022,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select a list: 的本地化字符串。 + /// Looks up a localized string similar to Select a list:. /// public static string SelectList { get { @@ -2004,7 +2031,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select PDB... 的本地化字符串。 + /// Looks up a localized string similar to Select PDB.... /// public static string SelectPDB { get { @@ -2013,7 +2040,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Select version of language to output 的本地化字符串。 + /// Looks up a localized string similar to Select version of language to output. /// public static string SelectVersionDropdownTooltip { get { @@ -2022,7 +2049,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Shell 的本地化字符串。 + /// Looks up a localized string similar to Shell. /// public static string Shell { get { @@ -2031,7 +2058,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show _all types and members 的本地化字符串。 + /// Looks up a localized string similar to Show _all types and members. /// public static string Show_allTypesAndMembers { get { @@ -2040,7 +2067,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show public, private and internal 的本地化字符串。 + /// Looks up a localized string similar to Show public, private and internal. /// public static string Show_internalTypesMembers { get { @@ -2049,7 +2076,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show only _public types and members 的本地化字符串。 + /// Looks up a localized string similar to Show only _public types and members. /// public static string Show_publiconlyTypesMembers { get { @@ -2058,7 +2085,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show all types and members 的本地化字符串。 + /// Looks up a localized string similar to Show all types and members. /// public static string ShowAllTypesAndMembers { get { @@ -2067,7 +2094,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show assembly load log 的本地化字符串。 + /// Looks up a localized string similar to Show assembly load log. /// public static string ShowAssemblyLoad { get { @@ -2076,7 +2103,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 ShowChildIndexInBlock 的本地化字符串。 + /// Looks up a localized string similar to ShowChildIndexInBlock. /// public static string ShowChildIndexInBlock { get { @@ -2085,7 +2112,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show XML documentation in decompiled code 的本地化字符串。 + /// Looks up a localized string similar to Show XML documentation in decompiled code. /// public static string ShowDocumentationDecompiledCode { get { @@ -2094,7 +2121,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 ShowILRanges 的本地化字符串。 + /// Looks up a localized string similar to ShowILRanges. /// public static string ShowILRanges { get { @@ -2103,7 +2130,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show info from debug symbols, if available 的本地化字符串。 + /// Looks up a localized string similar to Show info from debug symbols, if available. /// public static string ShowInfoFromDebugSymbolsAvailable { get { @@ -2112,7 +2139,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show public, private and internal 的本地化字符串。 + /// Looks up a localized string similar to Show public, private and internal. /// public static string ShowInternalTypesMembers { get { @@ -2121,7 +2148,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show line numbers 的本地化字符串。 + /// Looks up a localized string similar to Show line numbers. /// public static string ShowLineNumbers { get { @@ -2130,7 +2157,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show metadata tokens 的本地化字符串。 + /// Looks up a localized string similar to Show metadata tokens. /// public static string ShowMetadataTokens { get { @@ -2139,7 +2166,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show metadata tokens in base 10 的本地化字符串。 + /// Looks up a localized string similar to Show metadata tokens in base 10. /// public static string ShowMetadataTokensInBase10 { get { @@ -2148,7 +2175,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show only public types and members 的本地化字符串。 + /// Looks up a localized string similar to Show only public types and members. /// public static string ShowPublicOnlyTypesMembers { get { @@ -2157,7 +2184,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show state after this step 的本地化字符串。 + /// Looks up a localized string similar to Show state after this step. /// public static string ShowStateAfterThisStep { get { @@ -2166,7 +2193,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Show state before this step 的本地化字符串。 + /// Looks up a localized string similar to Show state before this step. /// public static string ShowStateBeforeThisStep { get { @@ -2175,7 +2202,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Size: 的本地化字符串。 + /// Looks up a localized string similar to Size:. /// public static string Size { get { @@ -2184,7 +2211,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Sort assembly _list by name 的本地化字符串。 + /// Looks up a localized string similar to Sort assembly _list by name. /// public static string SortAssembly_listName { get { @@ -2193,7 +2220,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Sort assembly list by name 的本地化字符串。 + /// Looks up a localized string similar to Sort assembly list by name. /// public static string SortAssemblyListName { get { @@ -2202,7 +2229,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Sort results by fitness 的本地化字符串。 + /// Looks up a localized string similar to Sort results by fitness. /// public static string SortResultsFitness { get { @@ -2211,7 +2238,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Stand by... 的本地化字符串。 + /// Looks up a localized string similar to Stand by.... /// public static string StandBy { get { @@ -2220,7 +2247,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Status 的本地化字符串。 + /// Looks up a localized string similar to Status. /// public static string Status { get { @@ -2229,7 +2256,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 String Table 的本地化字符串。 + /// Looks up a localized string similar to String Table. /// public static string StringTable { get { @@ -2238,7 +2265,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Tab size: 的本地化字符串。 + /// Looks up a localized string similar to Tab size:. /// public static string TabSize { get { @@ -2247,7 +2274,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Toggle All Folding 的本地化字符串。 + /// Looks up a localized string similar to Toggle All Folding. /// public static string ToggleFolding { get { @@ -2256,7 +2283,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Type 的本地化字符串。 + /// Looks up a localized string similar to Type. /// public static string Type { get { @@ -2265,7 +2292,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 No update for ILSpy found. 的本地化字符串。 + /// Looks up a localized string similar to No update for ILSpy found.. /// public static string UpdateILSpyFound { get { @@ -2274,7 +2301,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 UseFieldSugar 的本地化字符串。 + /// Looks up a localized string similar to UseFieldSugar. /// public static string UseFieldSugar { get { @@ -2283,7 +2310,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 UseLogicOperationSugar 的本地化字符串。 + /// Looks up a localized string similar to UseLogicOperationSugar. /// public static string UseLogicOperationSugar { get { @@ -2292,7 +2319,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use tabs instead of spaces 的本地化字符串。 + /// Looks up a localized string similar to Use tabs instead of spaces. /// public static string UseTabsInsteadOfSpaces { get { @@ -2301,7 +2328,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 You are using the latest release. 的本地化字符串。 + /// Looks up a localized string similar to You are using the latest release.. /// public static string UsingLatestRelease { get { @@ -2310,7 +2337,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 You are using a nightly build newer than the latest release. 的本地化字符串。 + /// Looks up a localized string similar to You are using a nightly build newer than the latest release.. /// public static string UsingNightlyBuildNewerThanLatestRelease { get { @@ -2319,7 +2346,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Value 的本地化字符串。 + /// Looks up a localized string similar to Value. /// public static string Value { get { @@ -2328,7 +2355,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Value (as string) 的本地化字符串。 + /// Looks up a localized string similar to Value (as string). /// public static string ValueString { get { @@ -2337,7 +2364,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Use variable names from debug symbols, if available 的本地化字符串。 + /// Looks up a localized string similar to Use variable names from debug symbols, if available. /// public static string VariableNamesFromDebugSymbolsAvailable { get { @@ -2346,7 +2373,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Version 的本地化字符串。 + /// Looks up a localized string similar to Version. /// public static string Version { get { @@ -2355,7 +2382,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Version {0} is available. 的本地化字符串。 + /// Looks up a localized string similar to Version {0} is available.. /// public static string VersionAvailable { get { @@ -2364,7 +2391,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 View 的本地化字符串。 + /// Looks up a localized string similar to View. /// public static string View { get { @@ -2373,7 +2400,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Visual Studio Solution file|*.sln|All files|*.* 的本地化字符串。 + /// Looks up a localized string similar to Visual Studio Solution file|*.sln|All files|*.*. /// public static string VisualStudioSolutionFileSlnAllFiles { get { @@ -2382,7 +2409,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code. 的本地化字符串。 + /// Looks up a localized string similar to Warning: This assembly is marked as 'reference assembly', which means that it only contains metadata and no executable code.. /// public static string WarningAsmMarkedRef { get { @@ -2391,7 +2418,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, 的本地化字符串。 + /// Looks up a localized string similar to Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,. /// public static string WarningSomeAssemblyReference { get { @@ -2400,7 +2427,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/... 的本地化字符串。 + /// Looks up a localized string similar to Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/.... /// public static string WatermarkText { get { @@ -2409,7 +2436,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Close all documents 的本地化字符串。 + /// Looks up a localized string similar to _Close all documents. /// public static string Window_CloseAllDocuments { get { @@ -2418,7 +2445,7 @@ namespace ICSharpCode.ILSpy.Properties { } /// - /// 查找类似 _Reset layout 的本地化字符串。 + /// Looks up a localized string similar to _Reset layout. /// public static string Window_ResetLayout { get { diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 32fc39d61..f5cb6e288 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -234,6 +234,9 @@ Are you sure you want to continue? Decompiler + + Always inline local variables if possible + Allow extension 'Add' methods in collection initializer expressions @@ -327,6 +330,9 @@ Are you sure you want to continue? Include XML documentation comments in the decompiled code + + Allow init; accessors + Insert using declarations @@ -378,6 +384,9 @@ Are you sure you want to continue? Show info from debug symbols, if available + + Switch expressions + Use discards From eabe8f96357c6439b533da88afcd81984230ddbf Mon Sep 17 00:00:00 2001 From: Edward Kazuya Carlson Date: Sat, 8 Aug 2020 10:41:05 -0700 Subject: [PATCH 73/92] Update ILSpy.ReadyToRun/ReadyToRunLanguage.cs Change how it handle's unexpected var loc types. Co-authored-by: Siegfried Pammer --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index f10c40941..602771a2f 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -170,7 +170,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; default: - throw new BadImageFormatException("Unexpected variable type"); + output.WriteLine("WRN: Unexpected variable location type"); } output.WriteLine(""); } From e7d49b230531430e04b607fd1a0c042345d95df7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 8 Aug 2020 19:50:57 +0200 Subject: [PATCH 74/92] Fix #2079: Allow variables generated from state-machine fields to be propagated in TDCU. --- .../IL/Transforms/TransformDisplayClassUsage.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index ab9aaae28..8af899362 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -68,7 +68,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms public void Propagate(ILVariable variable) { - Debug.Assert(declaredVariable == null || (variable == null && declaredVariable.StateMachineField == null)); this.declaredVariable = variable; this.CanPropagate = variable != null; } @@ -456,7 +455,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { ILVariable v; switch (value) { - case LdLoc load when load.Variable.StateMachineField == null: + case LdLoc load: v = load.Variable; if (v.Kind == VariableKind.Parameter) { if (v.LoadCount != 1 && !v.IsThis()) { From f9562d67019e93b1ffa2240138b128401ea30775 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 8 Aug 2020 20:19:58 +0200 Subject: [PATCH 75/92] Fix build. --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 602771a2f..bcf830831 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -171,6 +171,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun break; default: output.WriteLine("WRN: Unexpected variable location type"); + break; } output.WriteLine(""); } From ddff831cf02fcccb797abfcaf1d7b9734902eacd Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 14:54:46 +0200 Subject: [PATCH 76/92] #1292: Fix some more problems with pinned locals. Let's distinguish between the original pinned locals and the PinnedRegion locals. The format need declarations if any are left over after transformations; the latter don't. --- .../TestCases/ILPretty/Unsafe.cs | 15 ++++++ .../TestCases/ILPretty/Unsafe.il | 46 +++++++++++++++++++ .../CSharp/Transforms/DeclareVariables.cs | 5 +- .../IL/ControlFlow/DetectPinnedRegions.cs | 33 ++++++++----- ICSharpCode.Decompiler/IL/ILVariable.cs | 13 +++++- 5 files changed, 97 insertions(+), 15 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index 4bac5c052..8d45ab794 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -25,6 +25,21 @@ internal sealed class ExtraUnsafeTests { return (uint*)Unsafe.AsPointer(ref managedPtr); } + + public unsafe static byte[] Issue1292(int val, byte[] arr) + { + //The blocks IL_0019 are reachable both inside and outside the pinned region starting at IL_0013. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. + byte[] array; + if ((array = arr) != null && array.Length != 0) { + fixed (byte* ptr = &array[0]) { + *(int*)ptr = val; + } + } else { + /*pinned*/ref byte reference = ref *(byte*)null; + *(int*)Unsafe.AsPointer(ref reference) = val; + } + return arr; + } } namespace System.Runtime.CompilerServices diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il index e2b140d3f..2c6605531 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il @@ -474,4 +474,50 @@ ldarg.0 ret } + + .method public hidebysig static + uint8[] Issue1292 ( + int32 val, + uint8[] arr + ) cil managed + { + .maxstack 2 + .locals init ( + [0] uint8[], + [1] uint8[], + [2] uint8& pinned + ) + + IL_0000: ldarg.1 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: dup + IL_0004: stloc.1 + IL_0005: brfalse.s IL_0016 + + IL_0007: ldloc.1 + IL_0008: ldlen + IL_0009: conv.i4 + IL_000a: brfalse.s IL_0016 + + IL_000c: ldloc.1 + IL_000d: ldc.i4.0 + IL_000e: ldelema [mscorlib]System.Byte + IL_0013: stloc.2 + IL_0014: br.s IL_0019 + + IL_0016: ldc.i4.0 + IL_0017: conv.u + IL_0018: stloc.2 + + IL_0019: ldloc.2 + IL_001a: conv.i + IL_001b: ldarg.0 + IL_001c: stind.i4 + IL_001d: ldc.i4.0 + IL_001e: conv.u + IL_001f: stloc.2 + IL_0020: ldloc.0 + IL_0021: ret + } // end of method Issue1292 } \ No newline at end of file diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 2aad6a16d..272042d83 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -308,7 +308,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms internal static bool VariableNeedsDeclaration(VariableKind kind) { switch (kind) { - case VariableKind.PinnedLocal: + case VariableKind.PinnedRegionLocal: case VariableKind.Parameter: case VariableKind.ExceptionLocal: case VariableKind.ExceptionStackSlot: @@ -468,6 +468,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (v.ILVariable.IsRefReadOnly && type is ComposedType composedType && composedType.HasRefSpecifier) { composedType.HasReadOnlySpecifier = true; } + if (v.ILVariable.Kind == VariableKind.PinnedLocal) { + type.InsertChildAfter(null, new Comment("pinned", CommentType.MultiLine), Roles.Comment); + } var vds = new VariableDeclarationStatement(type, v.Name, assignment.Right.Detach()); var init = vds.Variables.Single(); init.AddAnnotation(assignment.Left.GetResolveResult()); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index 14c4ea687..ed83a1972 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } this.context = null; } - + /// /// Ensures that every write to a pinned local is followed by a branch instruction. /// This ensures the 'pinning region' does not involve any half blocks, which makes it easier to extract. @@ -349,7 +349,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; return block.Instructions[1].MatchBranch(nullOrEmptyBlock); } - + bool IsNullSafeArrayToPointerNotNullAndNotEmptyBlock(Block block, ILVariable v, ILVariable p, Block targetBlock) { // Block B_not_null_and_not_empty { @@ -380,7 +380,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; return block.Instructions[1].MatchBranch(targetBlock); } - + bool IsNullSafeArrayToPointerNullOrEmptyBlock(Block block, out ILVariable p, out Block targetBlock) { p = null; @@ -490,7 +490,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow body.Blocks.Add(innerBlock); // move block into body if (!cloneBlocks) { sourceContainer.Blocks[i] = new Block(); // replace with dummy block - // we'll delete the dummy block later + // we'll delete the dummy block later } } } @@ -506,14 +506,24 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } // Replace unreachable blocks in sourceContainer with dummy blocks: bool[] isAlive = new bool[sourceContainer.Blocks.Count]; + List duplicatedBlockStartOffsets = new List(); foreach (var remainingBlock in sourceContainer.TopologicalSort(deleteUnreachableBlocks: true)) { isAlive[remainingBlock.ChildIndex] = true; + if (clonedBlocks[remainingBlock.ChildIndex] != null) { + duplicatedBlockStartOffsets.Add(remainingBlock.StartILOffset); + } } for (int i = 0; i < isAlive.Length; i++) { if (!isAlive[i]) sourceContainer.Blocks[i] = new Block(); } // we'll delete the dummy blocks later + Debug.Assert(duplicatedBlockStartOffsets.Count > 0); + duplicatedBlockStartOffsets.Sort(); + context.Function.Warnings.Add("The blocks " + + string.Join(", ", duplicatedBlockStartOffsets.Select(o => $"IL_{o:x4}")) + + $" are reachable both inside and outside the pinned region starting at IL_{stLoc.StartILOffset:x4}." + + " ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement."); } if (body.Blocks.Count == 0) { // empty body, the entryBlock itself doesn't belong into the pinned region @@ -539,7 +549,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return inst.MatchLdcI4(0) || inst.MatchLdNull(); } #endregion - + #region ProcessPinnedRegion /// /// After a pinned region was detected; process its body; replacing the pin variable @@ -553,15 +563,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ILVariable oldVar = pinnedRegion.Variable; IType elementType = ((ByReferenceType)oldVar.Type).ElementType; if (elementType.Kind == TypeKind.Pointer && pinnedRegion.Init.MatchLdFlda(out _, out var field) - && ((PointerType)elementType).ElementType.Equals(field.Type)) - { + && ((PointerType)elementType).ElementType.Equals(field.Type)) { // Roslyn 2.6 (C# 7.2) uses type "int*&" for the pinned local referring to a // fixed field of type "int". // Remove the extra level of indirection. elementType = ((PointerType)elementType).ElementType; } ILVariable newVar = new ILVariable( - VariableKind.PinnedLocal, + VariableKind.PinnedRegionLocal, new PointerType(elementType), oldVar.Index); newVar.Name = oldVar.Name; @@ -610,7 +619,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Debug.Assert(arrayToPointer.IsDescendantOf(pinnedRegion)); ILVariable oldVar = pinnedRegion.Variable; ILVariable newVar = new ILVariable( - VariableKind.PinnedLocal, + VariableKind.PinnedRegionLocal, new PointerType(((ArrayType)oldVar.Type).ElementType), oldVar.Index); newVar.Name = oldVar.Name; @@ -680,7 +689,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // potentially a special case with legacy csc and an unused pinned variable: if (pinnedRegion.Variable.AddressCount == 0 && pinnedRegion.Variable.LoadCount == 0) { var charPtr = new PointerType(context.TypeSystem.FindType(KnownTypeCode.Char)); - newVar = new ILVariable(VariableKind.PinnedLocal, charPtr, pinnedRegion.Variable.Index); + newVar = new ILVariable(VariableKind.PinnedRegionLocal, charPtr, pinnedRegion.Variable.Index); newVar.Name = pinnedRegion.Variable.Name; newVar.HasGeneratedName = pinnedRegion.Variable.HasGeneratedName; pinnedRegion.Variable.Function.Variables.Add(newVar); @@ -732,7 +741,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow nativeVar = otherVar; } if (nativeVar.Kind == VariableKind.Local) { - newVar = new ILVariable(VariableKind.PinnedLocal, nativeVar.Type, nativeVar.Index); + newVar = new ILVariable(VariableKind.PinnedRegionLocal, nativeVar.Type, nativeVar.Index); newVar.Name = nativeVar.Name; newVar.HasGeneratedName = nativeVar.HasGeneratedName; nativeVar.Function.Variables.Add(newVar); @@ -801,7 +810,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (v.Kind != VariableKind.Local) return; // replace V_1 with V_0 - v.Kind = VariableKind.PinnedLocal; + v.Kind = VariableKind.PinnedRegionLocal; pinnedRegion.Variable = v; body.EntryPoint.Instructions.RemoveAt(0); } diff --git a/ICSharpCode.Decompiler/IL/ILVariable.cs b/ICSharpCode.Decompiler/IL/ILVariable.cs index 77b6dbae5..607f0b47b 100644 --- a/ICSharpCode.Decompiler/IL/ILVariable.cs +++ b/ICSharpCode.Decompiler/IL/ILVariable.cs @@ -31,10 +31,14 @@ namespace ICSharpCode.Decompiler.IL /// Local, /// - /// A pinned local variable + /// A pinned local variable (not associated with a pinned region) /// PinnedLocal, /// + /// A pinned local variable (associated with a pinned region) + /// + PinnedRegionLocal, + /// /// A local variable used as using-resource variable. /// UsingLocal, @@ -88,6 +92,7 @@ namespace ICSharpCode.Decompiler.IL case VariableKind.ForeachLocal: case VariableKind.UsingLocal: case VariableKind.PinnedLocal: + case VariableKind.PinnedRegionLocal: case VariableKind.DisplayClassLocal: return true; default: @@ -157,6 +162,7 @@ namespace ICSharpCode.Decompiler.IL case VariableKind.Local: case VariableKind.ForeachLocal: case VariableKind.PinnedLocal: + case VariableKind.PinnedRegionLocal: case VariableKind.UsingLocal: case VariableKind.ExceptionLocal: case VariableKind.DisplayClassLocal: @@ -397,6 +403,9 @@ namespace ICSharpCode.Decompiler.IL case VariableKind.PinnedLocal: output.Write("pinned local "); break; + case VariableKind.PinnedRegionLocal: + output.Write("PinnedRegion local "); + break; case VariableKind.Parameter: output.Write("param "); break; @@ -431,7 +440,7 @@ namespace ICSharpCode.Decompiler.IL output.Write(" : "); Type.WriteTo(output); output.Write('('); - if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal) { + if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal || Kind == VariableKind.PinnedRegionLocal) { output.Write("Index={0}, ", Index); } output.Write("LoadCount={0}, AddressCount={1}, StoreCount={2})", LoadCount, AddressCount, StoreCount); From 3e6e628483f9438ce51e8043587aa59ca8f130d1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 15:01:12 +0200 Subject: [PATCH 77/92] Fix missing conversion on ref-reassignment. --- .../TestCases/ILPretty/Unsafe.cs | 10 +++++++ .../TestCases/ILPretty/Unsafe.il | 26 +++++++++++++++++++ .../CSharp/ExpressionBuilder.cs | 1 + 3 files changed, 37 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index 8d45ab794..be41f47b0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -26,6 +26,16 @@ internal sealed class ExtraUnsafeTests return (uint*)Unsafe.AsPointer(ref managedPtr); } + public static ref ulong RefAssignTypeMismatch(ref uint a, ref uint b) + { + ref ushort reference = ref Unsafe.As(ref a); + if (a != 0) { + reference = ref Unsafe.As(ref b); + } + Console.WriteLine(reference); + return ref Unsafe.As(ref reference); + } + public unsafe static byte[] Issue1292(int val, byte[] arr) { //The blocks IL_0019 are reachable both inside and outside the pinned region starting at IL_0013. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il index 2c6605531..7766f0c80 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il @@ -475,6 +475,32 @@ ret } + .method public hidebysig static uint64& RefAssignTypeMismatch(uint32& a, uint32& b) + { + .maxstack 8 + .locals ( + [0] uint16& + ) + + ldarg.0 + stloc.0 + + ldarg.0 + ldind.i4 + brfalse lbl + + ldarg.1 + stloc.0 + +lbl: + ldloc.0 + ldind.i2 + call void [mscorlib]System.Console::WriteLine(uint16) + + ldloc.0 + ret + } + .method public hidebysig static uint8[] Issue1292 ( int32 val, diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 7bbd4f964..09bbb7c19 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -640,6 +640,7 @@ namespace ICSharpCode.Decompiler.CSharp if (lhs.Expression is DirectionExpression dirExpr && lhs.ResolveResult is ByReferenceResolveResult lhsRefRR) { // ref (re-)assignment, emit "ref (a = ref b)". lhs = lhs.UnwrapChild(dirExpr.Expression); + translatedValue = translatedValue.ConvertTo(lhsRefRR.Type, this, allowImplicitConversion: true); var assign = new AssignmentExpression(lhs.Expression, translatedValue.Expression) .WithRR(new OperatorResolveResult(lhs.Type, ExpressionType.Assign, lhsRefRR, translatedValue.ResolveResult)); return new DirectionExpression(FieldDirection.Ref, assign) From bd4e565b93d7efbdd371b4e65af5be7882811c5e Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 21:54:39 +0200 Subject: [PATCH 78/92] Ensure all pinned regions variables are converted to VariableKind.PinnedRegionLocal --- ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs | 4 ++++ ICSharpCode.Decompiler/IL/Instructions.cs | 1 + ICSharpCode.Decompiler/IL/Instructions.tt | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index ed83a1972..838ad1feb 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -592,6 +592,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow DetectPinnedRegion(block); body.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks body.SetILRange(body.EntryPoint); + if (pinnedRegion.Variable.Kind != VariableKind.PinnedRegionLocal) { + Debug.Assert(pinnedRegion.Variable.Kind == VariableKind.PinnedLocal); + pinnedRegion.Variable.Kind = VariableKind.PinnedRegionLocal; + } } private void MoveArrayToPointerToPinnedRegionInit(PinnedRegion pinnedRegion) diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 1de9d1fc8..a292afb07 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -1013,6 +1013,7 @@ namespace ICSharpCode.Decompiler.IL base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function)); Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable); + Debug.Assert(Variable.Kind == VariableKind.PinnedRegionLocal); } } } diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index b288ed9b2..92b30e6f9 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -67,7 +67,8 @@ CustomChildren(new []{ new ChildInfo("init") { CanInlineInto = true }, new ChildInfo("body") - })), + }), + CustomInvariant("Debug.Assert(Variable.Kind == VariableKind.PinnedRegionLocal);")), new OpCode("binary", "Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.", CustomClassName("BinaryNumericInstruction"), Binary, CustomWriteTo, CustomConstructor, CustomComputeFlags, MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator && IsLifted == o.IsLifted")), From c9f65d3b5ee3a15873af65d2baafa94f8757fb82 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 22:50:15 +0200 Subject: [PATCH 79/92] Fix #1555: Eliminate value-type temporaries emitted by mcs on field reads. --- .../PrettyTestRunner.cs | 2 +- .../IL/Transforms/ILInlining.cs | 50 ++++++++++++------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index fa6fc7ccf..48bbeba88 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -289,7 +289,7 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public void ValueTypes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) + public void ValueTypes([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions) { RunForLibrary(cscOptions: cscOptions); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index db93a64bc..5316249e2 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -250,21 +250,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Thus, we have to ensure we're operating on an r-value. // Additionally, we cannot inline in cases where the C# compiler prohibits the direct use // of the rvalue (e.g. M(ref (MyStruct)obj); is invalid). - if (!IsUsedAsThisPointerInCall(loadInst, out var method)) + if (IsUsedAsThisPointerInCall(loadInst, out var method)) { + switch (ClassifyExpression(inlinedExpression)) { + case ExpressionClassification.RValue: + // For struct method calls on rvalues, the C# compiler always generates temporaries. + return true; + case ExpressionClassification.MutableLValue: + // For struct method calls on mutable lvalues, the C# compiler never generates temporaries. + return false; + case ExpressionClassification.ReadonlyLValue: + // For struct method calls on readonly lvalues, the C# compiler + // only generates a temporary if it isn't a "readonly struct" + return MethodRequiresCopyForReadonlyLValue(method); + default: + throw new InvalidOperationException("invalid expression classification"); + } + } else if (IsUsedAsThisPointerInFieldRead(loadInst)) { + // mcs generated temporaries for field reads on rvalues (#1555) + return ClassifyExpression(inlinedExpression) == ExpressionClassification.RValue; + } else { return false; - switch (ClassifyExpression(inlinedExpression)) { - case ExpressionClassification.RValue: - // For struct method calls on rvalues, the C# compiler always generates temporaries. - return true; - case ExpressionClassification.MutableLValue: - // For struct method calls on mutable lvalues, the C# compiler never generates temporaries. - return false; - case ExpressionClassification.ReadonlyLValue: - // For struct method calls on readonly lvalues, the C# compiler - // only generates a temporary if it isn't a "readonly struct" - return MethodRequiresCopyForReadonlyLValue(method); - default: - throw new InvalidOperationException("invalid expression classification"); } } @@ -288,14 +293,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsUsedAsThisPointerInCall(LdLoca ldloca, out IMethod method) { method = null; - if (ldloca.ChildIndex != 0) - return false; if (ldloca.Variable.Type.IsReferenceType ?? false) return false; ILInstruction inst = ldloca; while (inst.Parent is LdFlda ldflda) { inst = ldflda; } + if (inst.ChildIndex != 0) + return false; switch (inst.Parent.OpCode) { case OpCode.Call: case OpCode.CallVirt: @@ -321,7 +326,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; } } - + + static bool IsUsedAsThisPointerInFieldRead(LdLoca ldloca) + { + if (ldloca.Variable.Type.IsReferenceType ?? false) + return false; + ILInstruction inst = ldloca; + while (inst.Parent is LdFlda ldflda) { + inst = ldflda; + } + return inst != ldloca && inst.Parent is LdObj; + } + internal enum ExpressionClassification { RValue, From 4b716e2db5bab8b769e8eadf5498988121d826ab Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 8 Aug 2020 23:47:12 +0200 Subject: [PATCH 80/92] Fix #2056: "remove branch into body" must be executed before the clone cleanup Otherwise the to-be-removed branch could keep an soon-to-be-unreachable block alive outside the pinned region. --- .../IL/ControlFlow/DetectPinnedRegions.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index 838ad1feb..a7a89d40e 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -494,6 +494,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } } + if (body.Blocks.Count == 0) { + // empty body, the entryBlock itself doesn't belong into the pinned region + Debug.Assert(reachedEdgesPerBlock[entryBlock.ChildIndex] == 0); + var bodyBlock = new Block(); + bodyBlock.SetILRange(stLoc); + bodyBlock.Instructions.Add(new Branch(entryBlock)); + body.Blocks.Add(bodyBlock); + } + + var pinnedRegion = new PinnedRegion(stLoc.Variable, stLoc.Value, body).WithILRange(stLoc); + stLoc.ReplaceWith(pinnedRegion); + block.Instructions.RemoveAt(block.Instructions.Count - 1); // remove branch into body + if (cloneBlocks) { // Adjust branches between cloned blocks. foreach (var branch in body.Descendants.OfType()) { @@ -525,18 +538,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow + $" are reachable both inside and outside the pinned region starting at IL_{stLoc.StartILOffset:x4}." + " ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement."); } - if (body.Blocks.Count == 0) { - // empty body, the entryBlock itself doesn't belong into the pinned region - Debug.Assert(reachedEdgesPerBlock[entryBlock.ChildIndex] == 0); - var bodyBlock = new Block(); - bodyBlock.SetILRange(stLoc); - bodyBlock.Instructions.Add(new Branch(entryBlock)); - body.Blocks.Add(bodyBlock); - } - var pinnedRegion = new PinnedRegion(stLoc.Variable, stLoc.Value, body).WithILRange(stLoc); - stLoc.ReplaceWith(pinnedRegion); - block.Instructions.RemoveAt(block.Instructions.Count - 1); // remove branch into body ProcessPinnedRegion(pinnedRegion); return true; } From 4f1443e2ff72437d2d509b761818a113322b8675 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 9 Aug 2020 09:09:20 +0200 Subject: [PATCH 81/92] Fix #2097: Prefix:PropertyName is invalid syntax --- ILSpy.BamlDecompiler/Xaml/XamlProperty.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs index ffddf65b1..0610126a4 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs @@ -80,12 +80,13 @@ namespace ILSpy.BamlDecompiler.Xaml { XName name; if (!isFullName) name = XmlConvert.EncodeLocalName(PropertyName); - else + else { name = typeName.LocalName + "." + XmlConvert.EncodeLocalName(PropertyName); - if (parent == null || (parent.GetDefaultNamespace() != typeName.Namespace && - parent.Name.Namespace != typeName.Namespace)) - name = typeName.Namespace + name.LocalName; + if (parent == null || (parent.GetDefaultNamespace() != typeName.Namespace + && parent.Name.Namespace != typeName.Namespace)) + name = typeName.Namespace + name.LocalName; + } return name; } From deae14a316bff17b22ccf48bf3c6583b61261459 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 10 Aug 2020 08:28:04 +0200 Subject: [PATCH 82/92] Temp run once an hour --- .github/workflows/lock.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 04cffa91a..8db2e5a74 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -2,7 +2,7 @@ name: 'Lock threads' on: schedule: - - cron: '0 0 * * *' + - cron: '0 * * * *' jobs: lock: @@ -19,4 +19,4 @@ jobs: issue-lock-reason: 'resolved' process-only: 'issues' # pr-lock-inactive-days: '365' - # pr-lock-reason: 'resolved' \ No newline at end of file + # pr-lock-reason: 'resolved' From d08d9154b1c1cb4d0c994de0b962ae20ceb3df4a Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 10 Aug 2020 09:21:04 +0200 Subject: [PATCH 83/92] Remove lock comment --- .github/workflows/lock.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 8db2e5a74..524d1ed18 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -12,10 +12,6 @@ jobs: with: github-token: ${{ github.token }} issue-lock-inactive-days: '365' - issue-lock-comment: > - This issue has been automatically locked since there - has not been any recent activity after it was closed. - Please open a new issue for related bugs. issue-lock-reason: 'resolved' process-only: 'issues' # pr-lock-inactive-days: '365' From e0a8f957cca5ea4bc1bed581cff23d116d1dd7ba Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 10 Aug 2020 21:00:41 +0200 Subject: [PATCH 84/92] Fix #2097: Prefix:PropertyName is invalid syntax --- ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs | 6 ++++ .../Cases/Issue2097.xaml | 5 +++ .../Cases/Issue2097.xaml.cs | 32 +++++++++++++++++++ .../ILSpy.BamlDecompiler.Tests.csproj | 4 +++ ILSpy.BamlDecompiler/Xaml/XamlProperty.cs | 4 +-- ILSpy.BamlDecompiler/Xaml/XamlUtils.cs | 11 ++++--- 6 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml create mode 100644 ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml.cs diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 7c1d2d152..42921963e 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -134,6 +134,12 @@ namespace ILSpy.BamlDecompiler.Tests RunTest("cases/issue1547"); } + [Test] + public void Issue2097() + { + RunTest("cases/issue2097"); + } + #region RunTest void RunTest(string name) { diff --git a/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml b/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml new file mode 100644 index 000000000..0742d86b4 --- /dev/null +++ b/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml @@ -0,0 +1,5 @@ + + + + + diff --git a/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml.cs b/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml.cs new file mode 100644 index 000000000..ab347c52f --- /dev/null +++ b/ILSpy.BamlDecompiler.Tests/Cases/Issue2097.xaml.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace ILSpy.BamlDecompiler.Tests.Cases +{ + /// + /// Interaction logic for Issue2097.xaml + /// + public partial class Issue2097 : Window + { + public Issue2097() + { + InitializeComponent(); + } + } + + class Issue2097Temp + { + public static string Test = "Hello"; + } +} diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj index 4534735ff..45169e45d 100644 --- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj +++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj @@ -52,6 +52,7 @@ + MyControl.xaml @@ -86,6 +87,9 @@ MSBuild:Compile + + MSBuild:Compile + Designer diff --git a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs index 0610126a4..f6264d1cf 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs @@ -82,9 +82,7 @@ namespace ILSpy.BamlDecompiler.Xaml { name = XmlConvert.EncodeLocalName(PropertyName); else { name = typeName.LocalName + "." + XmlConvert.EncodeLocalName(PropertyName); - - if (parent == null || (parent.GetDefaultNamespace() != typeName.Namespace - && parent.Name.Namespace != typeName.Namespace)) + if (parent == null || parent.GetDefaultNamespace() != typeName.Namespace) name = typeName.Namespace + name.LocalName; } diff --git a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs b/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs index 81c160a89..f165922ae 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs @@ -41,11 +41,12 @@ namespace ILSpy.BamlDecompiler.Xaml { public static string ToString(this XamlContext ctx, XElement elem, XName name) { var sb = new StringBuilder(); - if (name.Namespace != elem.GetDefaultNamespace() && - name.Namespace != elem.Name.Namespace && - !string.IsNullOrEmpty(name.Namespace.NamespaceName)) { - sb.Append(elem.GetPrefixOfNamespace(name.Namespace)); - sb.Append(':'); + if (name.Namespace != elem.GetDefaultNamespace()) { + var prefix = elem.GetPrefixOfNamespace(name.Namespace); + if (!string.IsNullOrEmpty(prefix)) { + sb.Append(prefix); + sb.Append(':'); + } } sb.Append(name.LocalName); return sb.ToString(); From f5409ebe313d8fa05b38629e2065b94021d38bfc Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 10 Aug 2020 21:34:35 +0200 Subject: [PATCH 85/92] Fix re-pinning getting confused about which variant of the pinned local to use when the new re-pinned reference depends on the old pinned reference. --- .../TestCases/ILPretty/Unsafe.cs | 16 +++++++ .../TestCases/ILPretty/Unsafe.il | 47 +++++++++++++++++++ .../IL/ControlFlow/DetectPinnedRegions.cs | 15 +++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index be41f47b0..fd288864c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -50,6 +50,22 @@ internal sealed class ExtraUnsafeTests } return arr; } + + public unsafe void pin_ptr_test(int[] a, int[] b) + { + //The blocks IL_0016 are reachable both inside and outside the pinned region starting at IL_0007. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. + ref int reference; + fixed (int* ptr = &a[0]) { + if (*ptr <= 0) { + ptr[4 * 0] = 1; + return; + } + reference = ref *ptr; + } + fixed (int* ptr = &b[reference]) { + ptr[4 * 0] = 1; + } + } } namespace System.Runtime.CompilerServices diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il index 7766f0c80..8e89b8adf 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.il @@ -546,4 +546,51 @@ lbl: IL_0020: ldloc.0 IL_0021: ret } // end of method Issue1292 + +.method /* 06000066 */ public hidebysig + instance void pin_ptr_test ( + int32[] a, + int32[] b + ) cil managed +{ + /* From C++/CLI: + void pin_ptr_test(array^ a, array^ b) + { + pin_ptr p = &a[0]; + if (*p > 0) + { + p = &b[*p]; + } + p[0] = 1; + } + */ + .maxstack 3 + .locals /* 11000004 */ ( + [0] int32& pinned modopt([mscorlib]System.Runtime.CompilerServices.IsExplicitlyDereferenced) p + ) + + IL_0000: ldarg.1 + IL_0001: ldc.i4.0 + IL_0002: ldelema [mscorlib]System.Int32 /* 01000016 */ + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: ldind.i4 + IL_000a: ldc.i4.0 + IL_000b: ble.s IL_0016 + + IL_000d: ldarg.2 + IL_000e: ldloc.0 + IL_000f: ldind.i4 + IL_0010: ldelema [mscorlib]System.Int32 /* 01000016 */ + IL_0015: stloc.0 + + IL_0016: ldloc.0 + IL_0017: ldc.i4.4 + IL_0018: ldc.i4.0 + IL_0019: mul + IL_001a: add + IL_001b: ldc.i4.1 + IL_001c: stind.i4 + IL_001d: ret +} // end of method pin_ptr_test } \ No newline at end of file diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index a7a89d40e..793dedb3a 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var block = container.Blocks[i]; for (int j = 0; j < block.Instructions.Count - 1; j++) { var inst = block.Instructions[j]; - if (inst.MatchStLoc(out ILVariable v) && v.Kind == VariableKind.PinnedLocal) { + if (inst.MatchStLoc(out ILVariable v, out var value) && v.Kind == VariableKind.PinnedLocal) { if (block.Instructions[j + 1].OpCode != OpCode.Branch) { // split block after j: context.Step("Split block after pinned local write", inst); @@ -107,6 +107,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow block.Instructions.Add(new Branch(newBlock)); container.Blocks.Insert(i + 1, newBlock); } + // in case of re-pinning (e.g. C++/CLI assignment to pin_ptr variable), + // it's possible for the new value to be dependent on the old. + if (v.IsUsedWithin(value)) { + // In this case, we need to un-inline the uses of the pinned local + // so that they are split off into the block prior to the pinned local write + var temp = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type); + block.Instructions.Insert(j++, new StLoc(temp, new LdLoc(v))); + foreach (var descendant in value.Descendants) { + if (descendant.MatchLdLoc(v)) { + descendant.ReplaceWith(new LdLoc(temp).WithILRange(descendant)); + } + } + } if (j > 0) { // split block before j: context.Step("Split block before pinned local write", inst); From ea9d2a2eb2ca33a7442a9f42bfc137e438fff5cc Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 12 Aug 2020 17:53:18 +0200 Subject: [PATCH 86/92] Fix output of pattern nodes --- .../CSharp/OutputVisitor/CSharpOutputVisitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 1f3b9dc2d..30caec5dc 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -2588,7 +2588,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } else if (childNode is Repeat) { VisitRepeat((Repeat)childNode); } else { - TextWriterTokenWriter.PrintPrimitiveValue(childNode); + writer.WritePrimitiveValue(childNode); } } #endregion From eea4b7701c3f2abab8c20306ae9b4eedcc323ac2 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 12 Aug 2020 17:55:08 +0200 Subject: [PATCH 87/92] #2098: CallBuilder: Fix named argument handling in TI --- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 7 +++---- .../CSharp/Resolver/OverloadResolution.cs | 2 +- .../Transforms/TransformCollectionAndObjectInitializers.cs | 4 +--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index d1d633a0c..e471927e3 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -811,7 +811,7 @@ namespace ICSharpCode.Decompiler.CSharp // that are no longer required once we add the type arguments. // We lend overload resolution a hand by detecting such cases beforehand and requiring type arguments, // if necessary. - if (!CanInferTypeArgumentsFromParameters(method, argumentList.Arguments.SelectArray(a => a.ResolveResult), expressionBuilder.typeInference)) { + if (!CanInferTypeArgumentsFromParameters(method, expressionBuilder.typeInference)) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); appliedRequireTypeArgumentsShortcut = true; @@ -895,14 +895,13 @@ namespace ICSharpCode.Decompiler.CSharp return method.IsExtensionMethod && arguments.Count > 0 && arguments[0].Expression is NullReferenceExpression; } - public static bool CanInferTypeArgumentsFromParameters(IMethod method, IReadOnlyList arguments, - TypeInference typeInference) + public static bool CanInferTypeArgumentsFromParameters(IMethod method, TypeInference typeInference) { if (method.TypeParameters.Count == 0) return true; // always use unspecialized member, otherwise type inference fails method = (IMethod)method.MemberDefinition; - typeInference.InferTypeArguments(method.TypeParameters, arguments, method.Parameters.SelectReadOnlyArray(p => p.Type), + typeInference.InferTypeArguments(method.TypeParameters, method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), method.Parameters.SelectReadOnlyArray(p => p.Type), out bool success); return success; } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs index d645e36b2..d69dbc08b 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs @@ -424,7 +424,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } else { TypeInference ti = new TypeInference(compilation, conversions); bool success; - candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); + candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ArgumentToParameterMap.SelectReadOnlyArray(parameterIndex => candidate.ParameterTypes[parameterIndex]), out success, classTypeArguments); if (!success) candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index ee619d6a8..76ebb6c05 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -378,9 +378,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!targetType.GetAllBaseTypes().Any(i => i.IsKnownType(KnownTypeCode.IEnumerable) || i.IsKnownType(KnownTypeCode.IEnumerableOfT))) return false; - return CSharp.CallBuilder.CanInferTypeArgumentsFromParameters( - method, method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), - new TypeInference(resolveContext.Compilation)); + return CSharp.CallBuilder.CanInferTypeArgumentsFromParameters(method, new TypeInference(resolveContext.Compilation)); } static IType GetReturnTypeFromInstruction(ILInstruction instruction) From e22e5423d5738f16f41baa4f22f0110762909433 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 12 Aug 2020 17:55:53 +0200 Subject: [PATCH 88/92] Fix #2098: Support auto event pattern with reordered arguments. --- .../Transforms/PatternStatementTransform.cs | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index 81814b0b0..899934023 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -755,6 +755,37 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } }; + static readonly Accessor automaticEventPatternV4AggressivelyInlined = new Accessor { + Attributes = { new Repeat(new AnyNode()) }, + Body = new BlockStatement { + new AssignmentExpression { + Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)), + Operator = AssignmentOperatorType.Assign, + Right = new NamedNode("field", fieldReferencePattern) + }, + new DoWhileStatement { + EmbeddedStatement = new BlockStatement { + new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")), + new AssignmentExpression { + Left = new IdentifierExpressionBackreference("var1"), + Right = new InvocationExpression(new MemberReferenceExpression(new TypeReferenceExpression(new TypePattern(typeof(System.Threading.Interlocked)).ToType()), + "CompareExchange"), + new Expression[] { // arguments + new NamedArgumentExpression("value", new CastExpression(new AnyNode("type"), new InvocationExpression(new AnyNode("delegateCombine").ToExpression(), new IdentifierExpressionBackreference("var2"), new IdentifierExpression("value")))), + new NamedArgumentExpression("location1", new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") }), + new NamedArgumentExpression("comparand", new IdentifierExpressionBackreference("var2")) + } + )} + }, + Condition = new BinaryOperatorExpression { + Left = new CastExpression(new TypePattern(typeof(object)), new IdentifierExpressionBackreference("var1")), + Operator = BinaryOperatorType.InEquality, + Right = new IdentifierExpressionBackreference("var2") + }, + } + } + }; + static readonly Accessor automaticEventPatternV4MCS = new Accessor { Attributes = { new Repeat(new AnyNode()) }, Body = new BlockStatement { @@ -837,10 +868,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool CheckAutomaticEventV4(CustomEventDeclaration ev) { Match addMatch = automaticEventPatternV4.Match(ev.AddAccessor); - if (!CheckAutomaticEventMatch(addMatch, ev, true)) + if (!CheckAutomaticEventMatch(addMatch, ev, isAddAccessor: true)) return false; Match removeMatch = automaticEventPatternV4.Match(ev.RemoveAccessor); - if (!CheckAutomaticEventMatch(removeMatch, ev, false)) + if (!CheckAutomaticEventMatch(removeMatch, ev, isAddAccessor: false)) + return false; + return true; + } + + bool CheckAutomaticEventV4AggressivelyInlined(CustomEventDeclaration ev) + { + if (!context.Settings.AggressiveInlining) + return false; + Match addMatch = automaticEventPatternV4AggressivelyInlined.Match(ev.AddAccessor); + if (!CheckAutomaticEventMatch(addMatch, ev, isAddAccessor: true)) + return false; + Match removeMatch = automaticEventPatternV4AggressivelyInlined.Match(ev.RemoveAccessor); + if (!CheckAutomaticEventMatch(removeMatch, ev, isAddAccessor: false)) return false; return true; } @@ -848,10 +892,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool CheckAutomaticEventV2(CustomEventDeclaration ev) { Match addMatch = automaticEventPatternV2.Match(ev.AddAccessor); - if (!CheckAutomaticEventMatch(addMatch, ev, true)) + if (!CheckAutomaticEventMatch(addMatch, ev, isAddAccessor: true)) return false; Match removeMatch = automaticEventPatternV2.Match(ev.RemoveAccessor); - if (!CheckAutomaticEventMatch(removeMatch, ev, false)) + if (!CheckAutomaticEventMatch(removeMatch, ev, isAddAccessor: false)) return false; return true; } @@ -872,7 +916,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (!ev.PrivateImplementationType.IsNull) return null; if (!ev.Modifiers.HasFlag(Modifiers.Abstract)) { - if (!CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev)) + if (!CheckAutomaticEventV4AggressivelyInlined(ev) && !CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev)) return null; } RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes, attributeTypesToRemoveFromAutoEvents); From 6ab58865a827b8dd1aaf24cff43aa0520ad64941 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 14 Aug 2020 08:02:02 +0200 Subject: [PATCH 89/92] lock-threads now runs once a day --- .github/workflows/lock.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 524d1ed18..8a689f2d5 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -2,7 +2,7 @@ name: 'Lock threads' on: schedule: - - cron: '0 * * * *' + - cron: '0 0 * * *' jobs: lock: @@ -11,8 +11,6 @@ jobs: - uses: dessant/lock-threads@v2.0.1 with: github-token: ${{ github.token }} - issue-lock-inactive-days: '365' + issue-lock-inactive-days: '90' issue-lock-reason: 'resolved' process-only: 'issues' - # pr-lock-inactive-days: '365' - # pr-lock-reason: 'resolved' From 3bc0bf3270c0b0b7219bed8d578febe20f68267e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 13 Aug 2020 11:07:43 +0200 Subject: [PATCH 90/92] WIP --- ICSharpCode.Decompiler/CSharp/Resolver/Log.cs | 2 +- ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs index e8884a0e0..8b922253f 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// static class Log { - const bool logEnabled = false; + const bool logEnabled = true; #if __MonoCS__ [Conditional("MCS_DEBUG")] #else diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs index d69dbc08b..fedc71ebd 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs @@ -423,8 +423,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } else { TypeInference ti = new TypeInference(compilation, conversions); + IType[] parameterTypes = candidate.ArgumentToParameterMap + .SelectReadOnlyArray(parameterIndex => parameterIndex >= 0 ? candidate.ParameterTypes[parameterIndex] : SpecialType.UnknownType); bool success; - candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ArgumentToParameterMap.SelectReadOnlyArray(parameterIndex => candidate.ParameterTypes[parameterIndex]), out success, classTypeArguments); + candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, parameterTypes, out success, classTypeArguments); if (!success) candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } From 05c988c5df1b13b4c97aeba7219570a7b7902b34 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 13 Aug 2020 11:10:22 +0200 Subject: [PATCH 91/92] Revert "#2098: CallBuilder: Fix named argument handling in TI" This partially reverts commit eea4b7701c3f2abab8c20306ae9b4eedcc323ac2. --- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 7 ++++--- .../Transforms/TransformCollectionAndObjectInitializers.cs | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index e471927e3..d1d633a0c 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -811,7 +811,7 @@ namespace ICSharpCode.Decompiler.CSharp // that are no longer required once we add the type arguments. // We lend overload resolution a hand by detecting such cases beforehand and requiring type arguments, // if necessary. - if (!CanInferTypeArgumentsFromParameters(method, expressionBuilder.typeInference)) { + if (!CanInferTypeArgumentsFromParameters(method, argumentList.Arguments.SelectArray(a => a.ResolveResult), expressionBuilder.typeInference)) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); appliedRequireTypeArgumentsShortcut = true; @@ -895,13 +895,14 @@ namespace ICSharpCode.Decompiler.CSharp return method.IsExtensionMethod && arguments.Count > 0 && arguments[0].Expression is NullReferenceExpression; } - public static bool CanInferTypeArgumentsFromParameters(IMethod method, TypeInference typeInference) + public static bool CanInferTypeArgumentsFromParameters(IMethod method, IReadOnlyList arguments, + TypeInference typeInference) { if (method.TypeParameters.Count == 0) return true; // always use unspecialized member, otherwise type inference fails method = (IMethod)method.MemberDefinition; - typeInference.InferTypeArguments(method.TypeParameters, method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), method.Parameters.SelectReadOnlyArray(p => p.Type), + typeInference.InferTypeArguments(method.TypeParameters, arguments, method.Parameters.SelectReadOnlyArray(p => p.Type), out bool success); return success; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 76ebb6c05..ee619d6a8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -378,7 +378,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!targetType.GetAllBaseTypes().Any(i => i.IsKnownType(KnownTypeCode.IEnumerable) || i.IsKnownType(KnownTypeCode.IEnumerableOfT))) return false; - return CSharp.CallBuilder.CanInferTypeArgumentsFromParameters(method, new TypeInference(resolveContext.Compilation)); + return CSharp.CallBuilder.CanInferTypeArgumentsFromParameters( + method, method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), + new TypeInference(resolveContext.Compilation)); } static IType GetReturnTypeFromInstruction(ILInstruction instruction) From a0d9410f67ffbf5961526c706e73aab4a43e6499 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 15 Aug 2020 09:33:25 +0200 Subject: [PATCH 92/92] Fix build. --- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 8 +++---- ICSharpCode.Decompiler/CSharp/Resolver/Log.cs | 2 +- ...ransformCollectionAndObjectInitializers.cs | 21 ++++++++++++++++--- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index d1d633a0c..5128297fa 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -811,7 +811,7 @@ namespace ICSharpCode.Decompiler.CSharp // that are no longer required once we add the type arguments. // We lend overload resolution a hand by detecting such cases beforehand and requiring type arguments, // if necessary. - if (!CanInferTypeArgumentsFromParameters(method, argumentList.Arguments.SelectArray(a => a.ResolveResult), expressionBuilder.typeInference)) { + if (!CanInferTypeArgumentsFromArguments(method, argumentList, expressionBuilder.typeInference)) { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); appliedRequireTypeArgumentsShortcut = true; @@ -895,14 +895,14 @@ namespace ICSharpCode.Decompiler.CSharp return method.IsExtensionMethod && arguments.Count > 0 && arguments[0].Expression is NullReferenceExpression; } - public static bool CanInferTypeArgumentsFromParameters(IMethod method, IReadOnlyList arguments, - TypeInference typeInference) + static bool CanInferTypeArgumentsFromArguments(IMethod method, ArgumentList argumentList, TypeInference typeInference) { if (method.TypeParameters.Count == 0) return true; // always use unspecialized member, otherwise type inference fails method = (IMethod)method.MemberDefinition; - typeInference.InferTypeArguments(method.TypeParameters, arguments, method.Parameters.SelectReadOnlyArray(p => p.Type), + var parametersInArgumentOrder = argumentList.ArgumentToParameterMap == null ? method.Parameters : argumentList.ArgumentToParameterMap.SelectReadOnlyArray(index => method.Parameters[index]); + typeInference.InferTypeArguments(method.TypeParameters, argumentList.Arguments.SelectReadOnlyArray(a => a.ResolveResult), parametersInArgumentOrder.SelectReadOnlyArray(p => p.Type), out bool success); return success; } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs index 8b922253f..e8884a0e0 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// static class Log { - const bool logEnabled = true; + const bool logEnabled = false; #if __MonoCS__ [Conditional("MCS_DEBUG")] #else diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index ee619d6a8..42edf5183 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -378,9 +378,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!targetType.GetAllBaseTypes().Any(i => i.IsKnownType(KnownTypeCode.IEnumerable) || i.IsKnownType(KnownTypeCode.IEnumerableOfT))) return false; - return CSharp.CallBuilder.CanInferTypeArgumentsFromParameters( - method, method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), - new TypeInference(resolveContext.Compilation)); + return CanInferTypeArgumentsFromParameters(method); + + bool CanInferTypeArgumentsFromParameters(IMethod method) + { + if (method.TypeParameters.Count == 0) + return true; + // always use unspecialized member, otherwise type inference fails + method = (IMethod)method.MemberDefinition; + new TypeInference(resolveContext.Compilation) + .InferTypeArguments( + method.TypeParameters, + // TODO : this is not entirely correct... we need argument type information to resolve Add methods properly + method.Parameters.SelectReadOnlyArray(p => new ResolveResult(p.Type)), + method.Parameters.SelectReadOnlyArray(p => p.Type), + out bool success + ); + return success; + } } static IType GetReturnTypeFromInstruction(ILInstruction instruction)