From da16495779c09f5fcb798af11b5600acf141f456 Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Sun, 16 Dec 2018 16:20:11 -0800 Subject: [PATCH 1/3] beta3 sync --- ...rpCode.Decompiler.PdbProvider.Cecil.csproj | 5 +- ILSpy.Core/Analyzers/AnalyzerScope.cs | 21 +-- .../Builtin/AttributeAppliedToAnalyzer.cs | 128 ++++++++++++++++-- .../Analyzers/Builtin/MethodUsedByAnalyzer.cs | 20 ++- ILSpy.Core/DecompilationOptions.cs | 3 +- ILSpy.Core/ILSpy.Core.csproj | 2 +- .../CSharpHighlightingTokenWriter.cs | 1 + ILSpy.Core/Languages/CSharpLanguage.cs | 3 +- ILSpy.Core/Languages/Language.cs | 18 +-- ILSpy.Core/LoadedAssembly.cs | 23 ++-- ILSpy.Core/MainWindow.xaml.cs | 92 ++++++++++--- .../Options/DecompilerSettingsPanel.xaml | 1 + .../Options/DecompilerSettingsPanel.xaml.cs | 26 +++- ILSpy.Core/Properties/AssemblyInfo.cs | 4 +- ILSpy.Core/Search/AbstractSearchStrategy.cs | 5 +- .../Search/MetadataTokenSearchStrategy.cs | 36 ++++- ILSpy.Core/Search/SearchPane.xaml | 2 +- ILSpy.Core/Search/SearchPane.xaml.cs | 3 +- ILSpy.Core/TreeNodes/AssemblyTreeNode.cs | 56 ++++++-- ILSpy.Core/TreeNodes/ResourceListTreeNode.cs | 2 +- .../ResourceNodes/ResourcesFileTreeNode.cs | 3 +- 21 files changed, 363 insertions(+), 91 deletions(-) diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj index 677c9c0..cf7d08e 100644 --- a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj +++ b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj @@ -7,9 +7,8 @@ - - - + + diff --git a/ILSpy.Core/Analyzers/AnalyzerScope.cs b/ILSpy.Core/Analyzers/AnalyzerScope.cs index a6b03db..c2c28de 100644 --- a/ILSpy.Core/Analyzers/AnalyzerScope.cs +++ b/ILSpy.Core/Analyzers/AnalyzerScope.cs @@ -89,16 +89,17 @@ public IEnumerable GetTypesInScope(CancellationToken ct) { if (IsLocal) { var typeSystem = new DecompilerTypeSystem(TypeScope.ParentModule.PEFile, TypeScope.ParentModule.PEFile.GetAssemblyResolver()); - if (memberAccessibility == Accessibility.Private) { - foreach (var type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) { - yield return type; - } - } else { - foreach (var type in TreeTraversal.PreOrder(typeScope.DeclaringTypeDefinition, t => t.NestedTypes)) { - yield return type; - } - } - } else { + ITypeDefinition scope = typeScope; + if (memberAccessibility != Accessibility.Private && typeScope.DeclaringTypeDefinition != null) + { + scope = typeScope.DeclaringTypeDefinition; + } + foreach (var type in TreeTraversal.PreOrder(scope, t => t.NestedTypes)) + { + yield return type; + } + } + else { foreach (var module in GetModulesInScope(ct)) { var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); foreach (var type in typeSystem.MainModule.TypeDefinitions) { diff --git a/ILSpy.Core/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs b/ILSpy.Core/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs index 462c741..650a187 100644 --- a/ILSpy.Core/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs +++ b/ILSpy.Core/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs @@ -18,10 +18,11 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Reflection.Metadata; +using System.Runtime.InteropServices; +using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -31,10 +32,121 @@ class AttributeAppliedToAnalyzer : IAnalyzer { public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext context) { - if (!(analyzedSymbol is IEntity attributeEntity)) - yield break; + if (!(analyzedSymbol is ITypeDefinition attributeType)) + return Array.Empty(); + var scope = context.GetScopeOf(attributeType); + // TODO: DeclSecurity attributes are not supported. + if (!IsBuiltinAttribute(attributeType, out var knownAttribute)) + { + return HandleCustomAttribute(attributeType, scope); + } + else + { + return HandleBuiltinAttribute(knownAttribute, scope).SelectMany(s => s); + } + } - var scope = context.GetScopeOf(attributeEntity); + bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute) + { + knownAttribute = attributeType.IsBuiltinAttribute(); + switch (knownAttribute) + { + case KnownAttribute.Serializable: + case KnownAttribute.ComImport: + case KnownAttribute.StructLayout: + case KnownAttribute.DllImport: + case KnownAttribute.PreserveSig: + case KnownAttribute.MethodImpl: + case KnownAttribute.FieldOffset: + case KnownAttribute.NonSerialized: + case KnownAttribute.MarshalAs: + case KnownAttribute.PermissionSet: + case KnownAttribute.Optional: + case KnownAttribute.In: + case KnownAttribute.Out: + case KnownAttribute.IndexerName: + return true; + default: + return false; + } + } + + IEnumerable> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope) + { + IEnumerable ScanTypes(DecompilerTypeSystem ts) + { + return ts.MainModule.TypeDefinitions + .Where(t => t.HasAttribute(attribute)); + } + + IEnumerable ScanMethods(DecompilerTypeSystem ts) + { + return ts.MainModule.TypeDefinitions + .SelectMany(t => t.Members.OfType()) + .Where(m => m.HasAttribute(attribute)) + .Select(m => m.AccessorOwner ?? m); + } + + IEnumerable ScanFields(DecompilerTypeSystem ts) + { + return ts.MainModule.TypeDefinitions + .SelectMany(t => t.Fields) + .Where(f => f.HasAttribute(attribute)); + } + + IEnumerable ScanProperties(DecompilerTypeSystem ts) + { + return ts.MainModule.TypeDefinitions + .SelectMany(t => t.Properties) + .Where(p => p.HasAttribute(attribute)); + } + + IEnumerable ScanParameters(DecompilerTypeSystem ts) + { + return ts.MainModule.TypeDefinitions + .SelectMany(t => t.Members.OfType()) + .Where(m => m.Parameters.Any(p => p.HasAttribute(attribute))) + .Select(m => m.AccessorOwner ?? m); + } + + foreach (Decompiler.Metadata.PEFile module in scope.GetAllModules()) + { + var ts = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); + + switch (attribute) + { + case KnownAttribute.Serializable: + case KnownAttribute.ComImport: + case KnownAttribute.StructLayout: + yield return ScanTypes(ts); + break; + case KnownAttribute.DllImport: + case KnownAttribute.PreserveSig: + case KnownAttribute.MethodImpl: + yield return ScanMethods(ts); + break; + case KnownAttribute.FieldOffset: + case KnownAttribute.NonSerialized: + yield return ScanFields(ts); + break; + case KnownAttribute.MarshalAs: + yield return ScanFields(ts); + yield return ScanParameters(ts); + goto case KnownAttribute.Out; + case KnownAttribute.Optional: + case KnownAttribute.In: + case KnownAttribute.Out: + yield return ScanParameters(ts); + break; + case KnownAttribute.IndexerName: + yield return ScanProperties(ts); + break; + } + } + } + + IEnumerable HandleCustomAttribute(ITypeDefinition attributeType, AnalyzerScope scope) + { var genericContext = new GenericContext(); // type arguments do not matter for this analyzer. foreach (var module in scope.GetAllModules()) { @@ -44,9 +156,9 @@ public IEnumerable Analyze(ISymbol analyzedSymbol, AnalyzerContext cont var customAttribute = module.Metadata.GetCustomAttribute(h); var attributeCtor = ts.MainModule.ResolveMethod(customAttribute.Constructor, genericContext); if (attributeCtor.DeclaringTypeDefinition != null - && attributeCtor.ParentModule.PEFile == attributeEntity.ParentModule.PEFile - && attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeEntity.MetadataToken) { - if (customAttribute.Parent.Kind == HandleKind.Parameter) { + && attributeCtor.ParentModule.PEFile == attributeType.ParentModule.PEFile + && attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeType.MetadataToken) { + if (customAttribute.Parent.Kind == HandleKind.Parameter) { referencedParameters.Add((ParameterHandle)customAttribute.Parent); } else { var parent = GetParentEntity(ts, customAttribute); diff --git a/ILSpy.Core/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ILSpy.Core/Analyzers/Builtin/MethodUsedByAnalyzer.cs index 6398d87..69531bd 100644 --- a/ILSpy.Core/Analyzers/Builtin/MethodUsedByAnalyzer.cs +++ b/ILSpy.Core/Analyzers/Builtin/MethodUsedByAnalyzer.cs @@ -99,7 +99,7 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo ILOpCode opCode; try { opCode = blob.DecodeOpCode(); - if (opCode != ILOpCode.Call && opCode != ILOpCode.Callvirt && opCode != ILOpCode.Ldtoken) { + if (!IsSupportedOpCode(opCode)) { ILParser.SkipOperand(ref blob, opCode); continue; } @@ -132,7 +132,23 @@ static bool ScanMethodBody(IMethod analyzedMethod, IMethod method, MethodBodyBlo return false; } - static bool IsSameMember(IMember analyzedMethod, IMember m) + static bool IsSupportedOpCode(ILOpCode opCode) + { + switch (opCode) + { + case ILOpCode.Call: + case ILOpCode.Callvirt: + case ILOpCode.Ldtoken: + case ILOpCode.Ldftn: + case ILOpCode.Ldvirtftn: + case ILOpCode.Newobj: + return true; + default: + return false; + } + } + + static bool IsSameMember(IMember analyzedMethod, IMember m) { return m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile; diff --git a/ILSpy.Core/DecompilationOptions.cs b/ILSpy.Core/DecompilationOptions.cs index 10dbd99..2786c5d 100644 --- a/ILSpy.Core/DecompilationOptions.cs +++ b/ILSpy.Core/DecompilationOptions.cs @@ -90,7 +90,8 @@ public DecompilationOptions(LanguageVersion version, Options.DecompilerSettings ShowXmlDocumentation = settings.ShowXmlDocumentation, UseDebugSymbols = settings.UseDebugSymbols, UsingDeclarations = settings.UsingDeclarations, - }; + ApplyWindowsRuntimeProjections = settings.ApplyWindowsRuntimeProjections, + }; } } } diff --git a/ILSpy.Core/ILSpy.Core.csproj b/ILSpy.Core/ILSpy.Core.csproj index 0f44423..e66d4ea 100644 --- a/ILSpy.Core/ILSpy.Core.csproj +++ b/ILSpy.Core/ILSpy.Core.csproj @@ -28,7 +28,7 @@ - + diff --git a/ILSpy.Core/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy.Core/Languages/CSharpHighlightingTokenWriter.cs index 0efe633..a3dbff9 100644 --- a/ILSpy.Core/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy.Core/Languages/CSharpHighlightingTokenWriter.cs @@ -273,6 +273,7 @@ public override void WritePrimitiveType(string type) case "ulong": color = valueTypeKeywordsColor; break; + case "class": case "object": case "string": case "void": diff --git a/ILSpy.Core/Languages/CSharpLanguage.cs b/ILSpy.Core/Languages/CSharpLanguage.cs index 5497d93..7f18cba 100644 --- a/ILSpy.Core/Languages/CSharpLanguage.cs +++ b/ILSpy.Core/Languages/CSharpLanguage.cs @@ -110,7 +110,8 @@ CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options) { CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; - while (decompiler.AstTransforms.Count > transformCount) + decompiler.DebugInfoProvider = module.GetDebugInfoOrNull(); + while (decompiler.AstTransforms.Count > transformCount) decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1); return decompiler; } diff --git a/ILSpy.Core/Languages/Language.cs b/ILSpy.Core/Languages/Language.cs index 14d4f47..559c999 100644 --- a/ILSpy.Core/Languages/Language.cs +++ b/ILSpy.Core/Languages/Language.cs @@ -503,15 +503,17 @@ public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandl public static string GetPlatformDisplayName(PEFile module) { var architecture = module.Reader.PEHeaders.CoffHeader.Machine; - var flags = module.Reader.PEHeaders.CorHeader.Flags; - switch (architecture) { + var characteristics = module.Reader.PEHeaders.CoffHeader.Characteristics; + var corflags = module.Reader.PEHeaders.CorHeader.Flags; + switch (architecture) { case Machine.I386: - if ((flags & CorFlags.Prefers32Bit) != 0) - return "AnyCPU (32-bit preferred)"; - else if ((flags & CorFlags.Requires32Bit) != 0) - return "x86"; - else - return "AnyCPU (64-bit preferred)"; + if ((corflags & CorFlags.Prefers32Bit) != 0) + return "AnyCPU (32-bit preferred)"; + // According to ECMA-335, II.25.3.3.1 CorFlags.Requires32Bit and Characteristics.Bit32Machine must be in sync + // for assemblies containing managed code. However, this is not true for C++/CLI assemblies. + if ((corflags & CorFlags.Requires32Bit) != 0 || (characteristics & Characteristics.Bit32Machine) != 0) + return "x86"; + return "AnyCPU (64-bit preferred)"; case Machine.Amd64: return "x64"; case Machine.IA64: diff --git a/ILSpy.Core/LoadedAssembly.cs b/ILSpy.Core/LoadedAssembly.cs index 5e1f139..4e9471f 100644 --- a/ILSpy.Core/LoadedAssembly.cs +++ b/ILSpy.Core/LoadedAssembly.cs @@ -153,16 +153,17 @@ PEFile LoadAssembly(object state) // runs on background thread if (stream != null) { - // Read the module from a precrafted stream - module = new PEFile(fileName, stream); - } - else + // Read the module from a precrafted stream + module = new PEFile(fileName, stream, metadataOptions: DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None); + } + else { - // Read the module from disk (by default) - module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), PEStreamOptions.PrefetchEntireImage); - } + // Read the module from disk (by default) + module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), PEStreamOptions.PrefetchEntireImage, + metadataOptions: DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None); + } - if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { + if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { try { LoadSymbols(module); } catch (IOException) { @@ -323,9 +324,9 @@ public LoadedAssembly LookupReferencedModule(PEFile mainModule, string moduleNam class MyUniversalResolver : UniversalAssemblyResolver { public MyUniversalResolver(LoadedAssembly assembly) - : base(assembly.FileName, false, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.PrefetchEntireImage) - { - } + : base(assembly.FileName, false, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.PrefetchEntireImage, DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None) + { + } } static Dictionary loadingAssemblies = new Dictionary(); diff --git a/ILSpy.Core/MainWindow.xaml.cs b/ILSpy.Core/MainWindow.xaml.cs index d7e3099..9e66821 100644 --- a/ILSpy.Core/MainWindow.xaml.cs +++ b/ILSpy.Core/MainWindow.xaml.cs @@ -24,6 +24,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Input; @@ -56,7 +57,8 @@ namespace ICSharpCode.ILSpy /// public partial class MainWindow : Window, IRoutedCommandBindable { - readonly NavigationHistory history = new NavigationHistory(); + bool refreshInProgress; + readonly NavigationHistory history = new NavigationHistory(); ILSpySettings spySettings; internal SessionSettings sessionSettings; @@ -333,12 +335,28 @@ void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args) } } } else { - foreach (LoadedAssembly asm in commandLineLoadedAssemblies) { - var def = asm.GetPEFileOrNull(); - if (def != null) { - var compilation = new SimpleCompilation(def, MinimalCorlib.Instance); - var mr = IdStringProvider.FindEntity(args.NavigateTo, new SimpleTypeResolveContext(compilation)); - if (mr != null) { + ITypeReference typeRef = null; + IMemberReference memberRef = null; + if (args.NavigateTo.StartsWith("T:", StringComparison.Ordinal)) + { + typeRef = IdStringProvider.ParseTypeName(args.NavigateTo); + } + else + { + memberRef = IdStringProvider.ParseMemberIdString(args.NavigateTo); + typeRef = memberRef.DeclaringTypeReference; + } + foreach (LoadedAssembly asm in commandLineLoadedAssemblies) { + var module = asm.GetPEFileOrNull(); + if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) { + IEntity mr = null; + ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType + ? new DecompilerTypeSystem(module, module.GetAssemblyResolver()) + : new SimpleCompilation(module, MinimalCorlib.Instance); + mr = memberRef == null + ? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition + : (IEntity)memberRef.Resolve(new SimpleTypeResolveContext(compilation)); + if (mr != null && mr.ParentModule.PEFile != null) { found = true; // Defer JumpToReference call to allow an assembly that was loaded while // resolving a type-forwarder in FindMemberByKey to appear in the assembly list. @@ -366,7 +384,32 @@ void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args) commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore } - void MainWindow_Loaded(object sender, EventArgs e) + private bool CanResolveTypeInPEFile(PEFile module, ITypeReference typeRef, out EntityHandle typeHandle) + { + switch (typeRef) + { + case GetPotentiallyNestedClassTypeReference topLevelType: + typeHandle = topLevelType.ResolveInPEFile(module); + return !typeHandle.IsNil; + case NestedTypeReference nestedType: + if (!CanResolveTypeInPEFile(module, nestedType.DeclaringTypeReference, out typeHandle)) + return false; + if (typeHandle.Kind == HandleKind.ExportedType) + return true; + var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeHandle); + typeHandle = typeDef.GetNestedTypes().FirstOrDefault(t => { + var td = module.Metadata.GetTypeDefinition(t); + var typeName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(module.Metadata.GetString(td.Name), out int typeParameterCount); + return nestedType.AdditionalTypeParameterCount == typeParameterCount && nestedType.Name == typeName; + }); + return !typeHandle.IsNil; + default: + typeHandle = default; + return false; + } + } + + void MainWindow_Loaded(object sender, EventArgs e) { Application.Current.FocusManager.Focus(treeView); @@ -862,10 +905,17 @@ async void LoadAssemblies(IEnumerable fileNames, List lo } void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e) - { - var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode); - ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); - SelectNode(FindNodeByPath(path, true)); + { + try + { + refreshInProgress = true; + var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode); + ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); + SelectNode(FindNodeByPath(path, true)); + } finally { + refreshInProgress = false; + } + } void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e) @@ -890,8 +940,11 @@ void DecompileSelectedNodes(DecompilerTextViewState state = null, bool recordHis { if (ignoreDecompilationRequests) return; - - if (recordHistory) { + + if (treeView.SelectedItems.Count == 0 && refreshInProgress) + return; + + if (recordHistory) { var dtState = decompilerTextView.GetState(); if(dtState != null) history.UpdateCurrent(new NavigationState(dtState)); @@ -918,8 +971,15 @@ async void SaveCommandExecuted(object sender, ExecutedRoutedEventArgs e) } public void RefreshDecompiledView() - { - DecompileSelectedNodes(); + { + try + { + refreshInProgress = true; + DecompileSelectedNodes(); + } finally { + refreshInProgress = false; + } + } public DecompilerTextView TextView { diff --git a/ILSpy.Core/Options/DecompilerSettingsPanel.xaml b/ILSpy.Core/Options/DecompilerSettingsPanel.xaml index f0718a0..5959c6a 100644 --- a/ILSpy.Core/Options/DecompilerSettingsPanel.xaml +++ b/ILSpy.Core/Options/DecompilerSettingsPanel.xaml @@ -10,5 +10,6 @@ Insert using declarations Always use braces Expand member definitions after decompilation + Apply Windows Runtime projections on loaded assemblies \ No newline at end of file diff --git a/ILSpy.Core/Options/DecompilerSettingsPanel.xaml.cs b/ILSpy.Core/Options/DecompilerSettingsPanel.xaml.cs index 5cfccbe..0d64ee4 100644 --- a/ILSpy.Core/Options/DecompilerSettingsPanel.xaml.cs +++ b/ILSpy.Core/Options/DecompilerSettingsPanel.xaml.cs @@ -64,7 +64,8 @@ public static DecompilerSettings LoadDecompilerSettings(ILSpySettings settings) s.RemoveDeadCode = (bool?)e.Attribute("removeDeadCode") ?? s.RemoveDeadCode; s.UsingDeclarations = (bool?)e.Attribute("usingDeclarations") ?? s.UsingDeclarations; s.AlwaysUseBraces = (bool?)e.Attribute("alwaysUseBraces") ?? s.AlwaysUseBraces; - return s; + s.ApplyWindowsRuntimeProjections = (bool?)e.Attribute("applyWindowsRuntimeProjections") ?? s.ApplyWindowsRuntimeProjections; + return s; } public void Save(XElement root) @@ -79,8 +80,9 @@ public void Save(XElement root) section.SetAttributeValue("removeDeadCode", s.RemoveDeadCode); section.SetAttributeValue("usingDeclarations", s.UsingDeclarations); section.SetAttributeValue("alwaysUseBraces", s.AlwaysUseBraces); + section.SetAttributeValue("applyWindowsRuntimeProjections", s.ApplyWindowsRuntimeProjections); - XElement existingElement = root.Element("DecompilerSettings"); + XElement existingElement = root.Element("DecompilerSettings"); if (existingElement != null) existingElement.ReplaceWith(section); else @@ -212,7 +214,25 @@ public bool AlwaysUseBraces { } } - public event PropertyChangedEventHandler PropertyChanged; + bool applyWindowsRuntimeProjections = true; + + /// + /// Gets/Sets whether to Windows Runtime projections to all loaded assemblies. + /// + public bool ApplyWindowsRuntimeProjections + { + get { return applyWindowsRuntimeProjections; } + set + { + if (applyWindowsRuntimeProjections != value) + { + applyWindowsRuntimeProjections = value; + OnPropertyChanged(); + } + } + } + + public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { diff --git a/ILSpy.Core/Properties/AssemblyInfo.cs b/ILSpy.Core/Properties/AssemblyInfo.cs index 74e24cb..6b9313d 100644 --- a/ILSpy.Core/Properties/AssemblyInfo.cs +++ b/ILSpy.Core/Properties/AssemblyInfo.cs @@ -42,7 +42,7 @@ internal static class RevisionClass public const string Minor = "0"; public const string Build = "0"; public const string Revision = "0"; - public const string VersionName = "beta2"; + public const string VersionName = "beta3"; - public const string FullVersion = Major + "." + Minor + "." + Build + ".0-no-branch-beta2"; + public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision + "." + VersionName; } diff --git a/ILSpy.Core/Search/AbstractSearchStrategy.cs b/ILSpy.Core/Search/AbstractSearchStrategy.cs index 32c7675..a0f9dc0 100644 --- a/ILSpy.Core/Search/AbstractSearchStrategy.cs +++ b/ILSpy.Core/Search/AbstractSearchStrategy.cs @@ -189,8 +189,9 @@ protected SearchResult ResultFromEntity(IEntity item) Image = GetIcon(item), Name = GetLanguageSpecificName(item), LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace, - Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : item.Namespace - }; + Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : item.Namespace, + ToolTip = item.ParentModule.PEFile?.FileName + }; } } } diff --git a/ILSpy.Core/Search/MetadataTokenSearchStrategy.cs b/ILSpy.Core/Search/MetadataTokenSearchStrategy.cs index 87e482c..cea115b 100644 --- a/ILSpy.Core/Search/MetadataTokenSearchStrategy.cs +++ b/ILSpy.Core/Search/MetadataTokenSearchStrategy.cs @@ -25,12 +25,40 @@ public override void Search(PEFile module) if (searchTermToken.IsNil) return; var typeSystem = module.GetTypeSystemOrNull(); if (typeSystem == null) return; + var metadataModule = (MetadataModule)typeSystem.MainModule; + int row = module.Metadata.GetRowNumber(searchTermToken); - switch (searchTermToken.Kind) { + switch (searchTermToken.Kind) { case HandleKind.TypeDefinition: - var type = ((MetadataModule)typeSystem.MainModule).GetDefinition((TypeDefinitionHandle)searchTermToken); - addResult(ResultFromEntity(type)); - break; + if (row < 1 || row > module.Metadata.TypeDefinitions.Count) + break; + var type = metadataModule.GetDefinition((TypeDefinitionHandle)searchTermToken); + addResult(ResultFromEntity(type)); + break; + case HandleKind.MethodDefinition: + if (row < 1 || row > module.Metadata.MethodDefinitions.Count) + break; + var method = metadataModule.GetDefinition((MethodDefinitionHandle)searchTermToken); + addResult(ResultFromEntity(method)); + break; + case HandleKind.FieldDefinition: + if (row < 1 || row > module.Metadata.FieldDefinitions.Count) + break; + var field = metadataModule.GetDefinition((FieldDefinitionHandle)searchTermToken); + addResult(ResultFromEntity(field)); + break; + case HandleKind.PropertyDefinition: + if (row < 1 || row > module.Metadata.PropertyDefinitions.Count) + break; + var property = metadataModule.GetDefinition((PropertyDefinitionHandle)searchTermToken); + addResult(ResultFromEntity(property)); + break; + case HandleKind.EventDefinition: + if (row < 1 || row > module.Metadata.EventDefinitions.Count) + break; + var @event = metadataModule.GetDefinition((EventDefinitionHandle)searchTermToken); + addResult(ResultFromEntity(@event)); + break; } } } diff --git a/ILSpy.Core/Search/SearchPane.xaml b/ILSpy.Core/Search/SearchPane.xaml index 57d2bef..a7ce6dd 100644 --- a/ILSpy.Core/Search/SearchPane.xaml +++ b/ILSpy.Core/Search/SearchPane.xaml @@ -46,7 +46,7 @@ - + diff --git a/ILSpy.Core/Search/SearchPane.xaml.cs b/ILSpy.Core/Search/SearchPane.xaml.cs index 653c158..c563620 100644 --- a/ILSpy.Core/Search/SearchPane.xaml.cs +++ b/ILSpy.Core/Search/SearchPane.xaml.cs @@ -363,7 +363,8 @@ sealed class SearchResult : IMemberTreeNode public string Location { get; set; } public string Name { get; set; } - public IBitmap Image { get; set; } + public object ToolTip { get; set; } + public IBitmap Image { get; set; } public IBitmap LocationImage { get; set; } public override string ToString() diff --git a/ILSpy.Core/TreeNodes/AssemblyTreeNode.cs b/ILSpy.Core/TreeNodes/AssemblyTreeNode.cs index e58f864..956b2ae 100644 --- a/ILSpy.Core/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy.Core/TreeNodes/AssemblyTreeNode.cs @@ -451,22 +451,41 @@ public bool IsVisible(TextViewContext context) if (context.SelectedTreeNodes == null) return false; return context.SelectedTreeNodes - .All(n => n is AssemblyTreeNode a && File.Exists(a.LoadedAssembly.FileName)); - } - - public bool IsEnabled(TextViewContext context) + .All(n => { + var a = GetAssemblyTreeNode(n); + return a != null && File.Exists(a.LoadedAssembly.FileName); + }); + } + + internal static AssemblyTreeNode GetAssemblyTreeNode(SharpTreeNode node) + { + while (node != null) + { + if (node is AssemblyTreeNode a) + return a; + node = node.Parent; + } + return null; + } + + + public bool IsEnabled(TextViewContext context) { if (context.SelectedTreeNodes == null) return false; return context.SelectedTreeNodes - .All(n => n is AssemblyTreeNode a && File.Exists(a.LoadedAssembly.FileName)); - } + .All(n => { + var a = GetAssemblyTreeNode(n); + return a != null && File.Exists(a.LoadedAssembly.FileName); + }); + } - public void Execute(TextViewContext context) + public void Execute(TextViewContext context) { if (context.SelectedTreeNodes == null) return; - foreach (var node in context.SelectedTreeNodes.OfType()) { + foreach (var n in context.SelectedTreeNodes) { + var node = GetAssemblyTreeNode(n); var path = Path.GetDirectoryName(node.LoadedAssembly.FileName); if (Directory.Exists(path)) { MainWindow.OpenFolder(path); @@ -483,22 +502,29 @@ public bool IsVisible(TextViewContext context) if (context.SelectedTreeNodes == null) return false; return context.SelectedTreeNodes - .All(n => n is AssemblyTreeNode a && File.Exists(a.LoadedAssembly.FileName)); - } + .All(n => { + var a = OpenContainingFolder.GetAssemblyTreeNode(n); + return a != null && File.Exists(a.LoadedAssembly.FileName); + }); + } - public bool IsEnabled(TextViewContext context) + public bool IsEnabled(TextViewContext context) { if (context.SelectedTreeNodes == null) return false; return context.SelectedTreeNodes - .All(n => n is AssemblyTreeNode a && File.Exists(a.LoadedAssembly.FileName)); - } + .All(n => { + var a = OpenContainingFolder.GetAssemblyTreeNode(n); + return a != null && File.Exists(a.LoadedAssembly.FileName); + }); + } - public void Execute(TextViewContext context) + public void Execute(TextViewContext context) { if (context.SelectedTreeNodes == null) return; - foreach (var node in context.SelectedTreeNodes.OfType()) { + foreach (var n in context.SelectedTreeNodes) { + var node = OpenContainingFolder.GetAssemblyTreeNode(n); var path = Path.GetDirectoryName(node.LoadedAssembly.FileName); if (Directory.Exists(path)) { MainWindow.OpenCommandLine(path); diff --git a/ILSpy.Core/TreeNodes/ResourceListTreeNode.cs b/ILSpy.Core/TreeNodes/ResourceListTreeNode.cs index 0d9785f..f4a7bd3 100644 --- a/ILSpy.Core/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy.Core/TreeNodes/ResourceListTreeNode.cs @@ -51,7 +51,7 @@ public override object ExpandedIcon { protected override void LoadChildren() { - foreach (Resource r in module.Resources.OrderBy(m => m.Name)) + foreach (Resource r in module.Resources.OrderBy(m => m.Name, NaturalStringComparer.Instance)) this.Children.Add(ResourceTreeNode.Create(r)); } diff --git a/ILSpy.Core/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs b/ILSpy.Core/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs index 98e6d41..51ba740 100644 --- a/ILSpy.Core/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs +++ b/ILSpy.Core/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs @@ -21,6 +21,7 @@ using System.Collections.ObjectModel; using System.ComponentModel.Composition; using System.IO; +using System.Linq; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Metadata; @@ -71,7 +72,7 @@ protected override void LoadChildren() if (s == null) return; s.Position = 0; try { - foreach (var entry in new ResourcesFile(s)) { + foreach (var entry in new ResourcesFile(s).OrderBy(e => e.Key, NaturalStringComparer.Instance)) { ProcessResourceEntry(entry); } } catch (BadImageFormatException) { From 9d8500126fe537a78fe892a1f4ee9886710b19c8 Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Sun, 16 Dec 2018 17:01:30 -0800 Subject: [PATCH 2/3] fix dependencies --- .../ICSharpCode.Decompiler.PdbProvider.Cecil.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj index cf7d08e..50d34ce 100644 --- a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj +++ b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj @@ -9,6 +9,10 @@ + + + + From 3a742e719e5c44567305805e4b234fa226e2a45d Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Sun, 16 Dec 2018 17:24:24 -0800 Subject: [PATCH 3/3] Fix image loading bug --- ILSpy.Core/ILSpy.Core.csproj | 2 +- ILSpy.Core/Search/SearchPane.xaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ILSpy.Core/ILSpy.Core.csproj b/ILSpy.Core/ILSpy.Core.csproj index e66d4ea..c61e011 100644 --- a/ILSpy.Core/ILSpy.Core.csproj +++ b/ILSpy.Core/ILSpy.Core.csproj @@ -56,7 +56,7 @@ PreserveNewest - + diff --git a/ILSpy.Core/Search/SearchPane.xaml b/ILSpy.Core/Search/SearchPane.xaml index a7ce6dd..52720bd 100644 --- a/ILSpy.Core/Search/SearchPane.xaml +++ b/ILSpy.Core/Search/SearchPane.xaml @@ -17,7 +17,7 @@ @@ -46,7 +46,7 @@ - +