From 46e5a2afb98621158ba7b61dcbaf47b78892a37b Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Wed, 27 Apr 2011 11:49:08 +1000 Subject: [PATCH 1/6] Added Type Analysis - Exposed BY, Instantiated BY, Extension Methods --- ILSpy/ILSpy.csproj | 4 + .../Analyzer/AnalyzeContextMenuEntry.cs | 12 +- .../Analyzer/AnalyzedTypeExposedByTreeNode.cs | 188 ++++++++++++++++++ .../AnalyzedTypeExtensionMethodsTreeNode.cs | 119 +++++++++++ .../AnalyzedTypeInstantiationsTreeNode.cs | 116 +++++++++++ .../Analyzer/AnalyzedTypeTreeNode.cs | 72 +++++++ .../Analyzer/ScopedWhereUsedAnalyzer.cs | 2 +- 7 files changed, 508 insertions(+), 5 deletions(-) create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 646d6f47f..14b21908d 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -135,6 +135,10 @@ + + + + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs index fa2c5bf29..9f56b086e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs @@ -30,11 +30,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { return selectedNodes.All(n => n is IMemberTreeNode); } - + public bool IsEnabled(SharpTreeNode[] selectedNodes) { foreach (IMemberTreeNode node in selectedNodes) { - if (!(node.Member is FieldDefinition + if (!(node.Member is TypeDefinition + || node.Member is FieldDefinition || node.Member is MethodDefinition || Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member) || Analyzer.AnalyzedEventTreeNode.CanShow(node.Member))) @@ -42,12 +43,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } return true; } - + public void Execute(SharpTreeNode[] selectedNodes) { // TODO: figure out when equivalent nodes are already present // and focus those instead. foreach (IMemberTreeNode node in selectedNodes) { + TypeDefinition type = node.Member as TypeDefinition; + if (type != null) + MainWindow.Instance.AddToAnalyzer(new AnalyzedTypeTreeNode(type)); FieldDefinition field = node.Member as FieldDefinition; if (field != null) MainWindow.Instance.AddToAnalyzer(new AnalyzedFieldNode(field)); @@ -55,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (method != null) MainWindow.Instance.AddToAnalyzer(new AnalyzedMethodTreeNode(method)); var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member); - if(propertyAnalyzer != null) + if (propertyAnalyzer != null) MainWindow.Instance.AddToAnalyzer(propertyAnalyzer); var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(node.Member); if (eventAnalyzer != null) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs new file mode 100644 index 000000000..da9670eaf --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -0,0 +1,188 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Threading; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode + { + TypeDefinition analyzedType; + ThreadingSupport threading; + bool IsSystemObject; + + public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType) + { + if (analyzedType == null) + throw new ArgumentNullException("analyzedType"); + + this.analyzedType = analyzedType; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + + this.IsSystemObject = (analyzedType.FullName == "System.Object"); + } + + public override object Text + { + get { return "Exposed By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + if (analyzedType.IsEnum && type == analyzedType) + yield break; + + if (!this.Language.ShowMember(type)) + yield break; + + foreach (FieldDefinition field in type.Fields) { + if (TypeIsExposedBy(field)) + yield return new AnalyzedFieldNode(field); + } + + foreach (PropertyDefinition property in type.Properties) { + if (TypeIsExposedBy(property)) + yield return new AnalyzedPropertyTreeNode(property); + } + + foreach (EventDefinition eventDef in type.Events) { + if (TypeIsExposedBy(eventDef)) + yield return new AnalyzedEventTreeNode(eventDef); + } + + foreach (MethodDefinition method in type.Methods) { + if (TypeIsExposedBy(method)) + yield return new AnalyzedMethodTreeNode(method); + } + } + + private bool TypeIsExposedBy(FieldDefinition field) + { + if (field.IsPrivate) + return false; + + if (field.FieldType.Resolve() == analyzedType) + return true; + + return false; + } + + private bool TypeIsExposedBy(PropertyDefinition property) + { + if (IsPrivate(property)) + return false; + + if (property.PropertyType.Resolve() == analyzedType) + return true; + + return false; + } + + private bool TypeIsExposedBy(EventDefinition eventDef) + { + if (IsPrivate(eventDef)) + return false; + + if (eventDef.EventType.Resolve() == analyzedType) + return true; + + return false; + } + + private bool TypeIsExposedBy(MethodDefinition method) + { + // if the method has overrides, it is probably an explicit interface member + // and should be considered part of the public API even though it is marked private. + if (method.IsPrivate) { + if (!method.HasOverrides) + return false; + else if (!method.Overrides[0].DeclaringType.Resolve().IsInterface) + return false; + } + + // exclude methods with 'semantics'. for example, property getters & setters. + // HACK: this is a potentially fragile implementation, as the MethodSemantics may be extended to other uses at a later date. + if (method.SemanticsAttributes != MethodSemanticsAttributes.None) + return false; + + if (method.ReturnType.Resolve() == analyzedType) + return true; + + if (method.HasParameters) { + foreach (var parameter in method.Parameters) { + if (parameter.ParameterType.Resolve() == analyzedType) + return true; + } + } + + return false; + } + + private bool IsPrivate(PropertyDefinition property) + { + bool isGetterPublic = (property.GetMethod != null && !property.GetMethod.IsPrivate); + bool isSetterPublic = (property.SetMethod != null && !property.SetMethod.IsPrivate); + return !(isGetterPublic || isSetterPublic); + } + + private bool IsPrivate(EventDefinition eventDef) + { + bool isAdderPublic = (eventDef.AddMethod != null && !eventDef.AddMethod.IsPrivate); + bool isRemoverPublic = (eventDef.RemoveMethod != null && !eventDef.RemoveMethod.IsPrivate); + return !(isAdderPublic || isRemoverPublic); + } + + public static bool CanShowAnalyzer(TypeDefinition type) + { + return true; + } + + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs new file mode 100644 index 000000000..258ff6e75 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -0,0 +1,119 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode + { + TypeDefinition analyzedType; + ThreadingSupport threading; + bool IsSystemObject; + + public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType) + { + if (analyzedType == null) + throw new ArgumentNullException("analyzedType"); + + this.analyzedType = analyzedType; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + + this.IsSystemObject = (analyzedType.FullName == "System.Object"); + } + + public override object Text + { + get { return "Extension Methods"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + foreach (MethodDefinition method in type.Methods) { + if (method.IsStatic && method.HasCustomAttributes) { + if (method.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute")) { + if (method.HasParameters && method.Parameters[0].ParameterType.Resolve() == analyzedType) { + yield return new AnalyzedMethodTreeNode(method); + } + } + } + } + } + + private bool TypeIsExposedBy(MethodDefinition method) + { + if (method.IsPrivate) + return false; + + // exclude methods with 'semantics'. for example, property getters & setters. + if (method.SemanticsAttributes != MethodSemanticsAttributes.None) + return false; + + if (method.ReturnType.Resolve() == analyzedType) + return true; + + if (method.HasParameters) { + foreach (var parameter in method.Parameters) { + if (parameter.ParameterType.Resolve() == analyzedType) + return true; + } + } + + return false; + } + + public static bool CanShowAnalyzer(TypeDefinition type) + { + return !(type.IsEnum); + } + + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs new file mode 100644 index 000000000..578ddd582 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -0,0 +1,116 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.TreeView; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode + { + TypeDefinition analyzedType; + ThreadingSupport threading; + bool IsSystemObject; + + public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType) + { + if (analyzedType == null) + throw new ArgumentNullException("analyzedType"); + + this.analyzedType = analyzedType; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + + this.IsSystemObject = (analyzedType.FullName == "System.Object"); + } + + public override object Text + { + get { return "Instantiated By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + foreach (MethodDefinition method in type.Methods) { + bool found = false; + if (!method.HasBody) + continue; + + // ignore chained constructors + // (since object is the root of everything, we can short circuit the test in this case) + if (method.Name == ".ctor" && + (IsSystemObject || analyzedType == type || TypesHierarchyHelpers.IsBaseType(analyzedType, type, false))) + continue; + + foreach (Instruction instr in method.Body.Instructions) { + MethodReference mr = instr.Operand as MethodReference; + if (mr != null && mr.Name == ".ctor") { + if (Helpers.IsReferencedBy(analyzedType, mr.DeclaringType)) { + found = true; + break; + } + } + } + if (found) + yield return new AnalyzedMethodTreeNode(method); + } + } + + public static bool CanShowAnalyzer(TypeDefinition type) + { + if (type.IsClass && !type.IsEnum) { + return type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); + } + return false; + } + + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs new file mode 100644 index 000000000..58548a967 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs @@ -0,0 +1,72 @@ +// Copyright (c) 2011 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; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode + { + TypeDefinition analyzedType; + + public AnalyzedTypeTreeNode(TypeDefinition analyzedType) + { + if (analyzedType == null) + throw new ArgumentNullException("analyzedType"); + this.analyzedType = analyzedType; + this.LazyLoading = true; + } + + public override object Icon + { + get { return TypeTreeNode.GetIcon(analyzedType); } + } + + public override object Text + { + get + { + return Language.TypeToString(analyzedType, true); + } + } + + public override void ActivateItem(System.Windows.RoutedEventArgs e) + { + e.Handled = true; + MainWindow.Instance.JumpToReference(analyzedType); + } + + protected override void LoadChildren() + { + if (AnalyzedTypeInstantiationsTreeNode.CanShowAnalyzer(analyzedType)) + this.Children.Add(new AnalyzedTypeInstantiationsTreeNode(analyzedType)); + + if (AnalyzedTypeExposedByTreeNode.CanShowAnalyzer(analyzedType)) + this.Children.Add(new AnalyzedTypeExposedByTreeNode(analyzedType)); + + if (AnalyzedTypeExtensionMethodsTreeNode.CanShowAnalyzer(analyzedType)) + this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType)); + } + + MemberReference IMemberTreeNode.Member + { + get { return analyzedType; } + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 281da3a21..79746a288 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private Accessibility typeAccessibility = Accessibility.Public; private Func> typeAnalysisFunction; - private ScopedWhereUsedScopeAnalyzer(TypeDefinition type, Func> typeAnalysisFunction) + public ScopedWhereUsedScopeAnalyzer(TypeDefinition type, Func> typeAnalysisFunction) { this.typeScope = type; this.assemblyScope = type.Module.Assembly; From 19634e21a096cdc7b820e9b50eba524d3ed8b814 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Wed, 27 Apr 2011 12:01:17 +1000 Subject: [PATCH 2/6] Analyzer code clean-up. Class/member naming, code formatting and License text. --- ILSpy/ILSpy.csproj | 2 +- .../AnalyzedEventAccessorsTreeNode.cs | 23 +++++++-- .../AnalyzedEventOverridesTreeNode.cs | 23 +++++++-- .../Analyzer/AnalyzedEventTreeNode.cs | 29 ++++++----- .../Analyzer/AnalyzedFieldAccessNode.cs | 22 +++++++-- ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs | 43 ++++++++++++----- ....cs => AnalyzedMethodOverridesTreeNode.cs} | 6 +-- .../Analyzer/AnalyzedMethodTreeNode.cs | 31 +++++++----- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 3 -- .../Analyzer/AnalyzedMethodUsesNode.cs | 20 ++++---- .../AnalyzedPropertyAccessorsTreeNode.cs | 48 +++++++++++++------ .../AnalyzedPropertyOverridesTreeNode.cs | 23 +++++++-- .../Analyzer/AnalyzedPropertyTreeNode.cs | 30 +++++++----- .../Analyzer/AnalyzedTypeExposedByTreeNode.cs | 2 +- .../AnalyzedTypeExtensionMethodsTreeNode.cs | 2 +- .../AnalyzedTypeInstantiationsTreeNode.cs | 2 +- .../Analyzer/AnalyzedTypeTreeNode.cs | 6 +-- ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs | 16 ++++--- ILSpy/TreeNodes/Analyzer/Helpers.cs | 20 +++++++- .../Analyzer/ScopedWhereUsedAnalyzer.cs | 24 ++++++++-- 20 files changed, 260 insertions(+), 115 deletions(-) rename ILSpy/TreeNodes/Analyzer/{AnalyzerMethodOverridesTreeNode.cs => AnalyzedMethodOverridesTreeNode.cs} (94%) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 14b21908d..822a17db7 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -181,7 +181,7 @@ - + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs index 8bf0285fb..9a60a031e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs @@ -1,11 +1,26 @@ -using System; +// Copyright (c) 2011 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; using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - /// - /// Description of AnalyzedEventAccessorsTreeNode. - /// public class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode { EventDefinition analyzedEvent; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index f406b45e0..306e86017 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -1,7 +1,24 @@ -using System; +// Copyright (c) 2011 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; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using ICSharpCode.Decompiler.Ast; using ICSharpCode.NRefactory.Utils; @@ -84,7 +101,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public static bool CanShowAnalyzer(EventDefinition property) + public static bool CanShow(EventDefinition property) { var accessor = property.AddMethod ?? property.RemoveMethod; return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs index e2db2aa67..a8922eea8 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs @@ -18,7 +18,6 @@ using System; using Mono.Cecil; -using ICSharpCode.Decompiler; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { @@ -26,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { EventDefinition analyzedEvent; string prefix; - + public AnalyzedEventTreeNode(EventDefinition analyzedEvent, string prefix = "") { if (analyzedEvent == null) @@ -35,28 +34,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.prefix = prefix; this.LazyLoading = true; } - - public override object Icon { + + public override object Icon + { get { return EventTreeNode.GetIcon(analyzedEvent); } } - - public override object Text { - get { + + public override object Text + { + get + { // TODO: This way of formatting is not suitable for events which explicitly implement interfaces. - return prefix + Language.TypeToString(analyzedEvent.DeclaringType, true) + "." + EventTreeNode.GetText(analyzedEvent, Language); } + return prefix + Language.TypeToString(analyzedEvent.DeclaringType, true) + "." + EventTreeNode.GetText(analyzedEvent, Language); + } } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; MainWindow.Instance.JumpToReference(analyzedEvent); } - + protected override void LoadChildren() { - if(AnalyzedEventAccessorsTreeNode.CanShow(analyzedEvent)) + if (AnalyzedEventAccessorsTreeNode.CanShow(analyzedEvent)) this.Children.Add(new AnalyzedEventAccessorsTreeNode(analyzedEvent)); - if (AnalyzedEventOverridesTreeNode.CanShowAnalyzer(analyzedEvent)) + if (AnalyzedEventOverridesTreeNode.CanShow(analyzedEvent)) this.Children.Add(new AnalyzedEventOverridesTreeNode(analyzedEvent)); } @@ -75,7 +78,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return false; return AnalyzedEventAccessorsTreeNode.CanShow(property) - || AnalyzedEventOverridesTreeNode.CanShowAnalyzer(property); + || AnalyzedEventOverridesTreeNode.CanShow(property); } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs index 3375048c5..88b6253a6 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs @@ -1,12 +1,24 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 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; using System.Collections.Generic; -using System.Linq; using System.Threading; - -using ICSharpCode.NRefactory.Utils; using ICSharpCode.TreeView; using Mono.Cecil; using Mono.Cecil.Cil; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs index fdbe7159d..a5e65ef6e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// Copyright (c) 2011 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; using Mono.Cecil; @@ -9,7 +24,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer class AnalyzedFieldNode : AnalyzerTreeNode, IMemberTreeNode { FieldDefinition analyzedField; - + public AnalyzedFieldNode(FieldDefinition analyzedField) { if (analyzedField == null) @@ -17,32 +32,36 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedField = analyzedField; this.LazyLoading = true; } - - public override object Icon { + + public override object Icon + { get { return FieldTreeNode.GetIcon(analyzedField); } } - - public override object Text { - get { + + public override object Text + { + get + { return Language.TypeToString(analyzedField.DeclaringType, true) + "." + analyzedField.Name + " : " + this.Language.TypeToString(analyzedField.FieldType, false, analyzedField); } } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; MainWindow.Instance.JumpToReference(analyzedField); } - + protected override void LoadChildren() { this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, false)); if (!analyzedField.IsLiteral) this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, true)); } - - MemberReference IMemberTreeNode.Member { + + MemberReference IMemberTreeNode.Member + { get { return analyzedField; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs similarity index 94% rename from ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index b3ea54122..70da7b542 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -14,12 +14,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Searches for overrides of the analyzed method. /// - class AnalyzerMethodOverridesTreeNode : AnalyzerTreeNode + class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode { readonly MethodDefinition analyzedMethod; readonly ThreadingSupport threading; - public AnalyzerMethodOverridesTreeNode(MethodDefinition analyzedMethod) + public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod) { if (analyzedMethod == null) throw new ArgumentNullException("analyzedMethod"); @@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public static bool CanShowAnalyzer(MethodDefinition method) + public static bool CanShow(MethodDefinition method) { return method.IsVirtual && !method.IsFinal && !method.DeclaringType.IsSealed && !method.DeclaringType.IsInterface; // interfaces are temporarly disabled } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs index 77e53ed49..053038fbb 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { MethodDefinition analyzedMethod; string prefix; - + public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "") { if (analyzedMethod == null) @@ -34,32 +34,37 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.prefix = prefix; this.LazyLoading = true; } - - public override object Icon { + + public override object Icon + { get { return MethodTreeNode.GetIcon(analyzedMethod); } } - - public override object Text { - get { - return prefix + Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language); } + + public override object Text + { + get + { + return prefix + Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language); + } } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; MainWindow.Instance.JumpToReference(analyzedMethod); } - + protected override void LoadChildren() { if (analyzedMethod.HasBody) this.Children.Add(new AnalyzedMethodUsesNode(analyzedMethod)); this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); - if (AnalyzerMethodOverridesTreeNode.CanShowAnalyzer(analyzedMethod)) - this.Children.Add(new AnalyzerMethodOverridesTreeNode(analyzedMethod)); + if (AnalyzedMethodOverridesTreeNode.CanShow(analyzedMethod)) + this.Children.Add(new AnalyzedMethodOverridesTreeNode(analyzedMethod)); } - - MemberReference IMemberTreeNode.Member { + + MemberReference IMemberTreeNode.Member + { get { return analyzedMethod; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index f89081064..c21351a7a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -18,10 +18,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; -using ICSharpCode.NRefactory.Utils; using ICSharpCode.TreeView; using Mono.Cecil; using Mono.Cecil.Cil; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs index 65b1706c4..eabc686c5 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs @@ -30,24 +30,26 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer sealed class AnalyzedMethodUsesNode : AnalyzerTreeNode { MethodDefinition analyzedMethod; - + public AnalyzedMethodUsesNode(MethodDefinition analyzedMethod) { if (analyzedMethod == null) throw new ArgumentNullException("analyzedMethod"); - + this.analyzedMethod = analyzedMethod; this.LazyLoading = true; } - - public override object Text { + + public override object Text + { get { return "Uses"; } } - - public override object Icon { + + public override object Icon + { get { return Images.Search; } } - + protected override void LoadChildren() { foreach (var f in GetUsedFields().Distinct()) { @@ -57,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedMethodTreeNode(m)); } } - + IEnumerable GetUsedMethods() { foreach (Instruction instr in analyzedMethod.Body.Instructions) { @@ -69,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } } - + IEnumerable GetUsedFields() { foreach (Instruction instr in analyzedMethod.Body.Instructions) { diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs index 2ce84c1c6..d6ba5ae67 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs @@ -1,21 +1,36 @@ -using System; +// Copyright (c) 2011 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; using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - /// - /// Description of AnalyzedPropertyAccessorsTreeNode. - /// public class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode { PropertyDefinition analyzedProperty; - + public AnalyzedPropertyAccessorsTreeNode(PropertyDefinition analyzedProperty) { if (analyzedProperty == null) throw new ArgumentNullException("analyzedProperty"); this.analyzedProperty = analyzedProperty; - + if (analyzedProperty.GetMethod != null) this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get")); if (analyzedProperty.SetMethod != null) @@ -23,31 +38,34 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (var accessor in analyzedProperty.OtherMethods) this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null)); } - - public override object Icon { + + public override object Icon + { get { return Images.Search; } } - - public override object Text { + + public override object Text + { get { return "Accessors"; } } - + public static bool CanShow(PropertyDefinition property) { return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod); } - + class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode { string name; - + public AnalyzedPropertyAccessorTreeNode(MethodDefinition analyzedMethod, string name) : base(analyzedMethod) { this.name = name; } - - public override object Text { + + public override object Text + { get { return name ?? base.Text; } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index b1a91521a..7ebc563c3 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -1,7 +1,24 @@ -using System; +// Copyright (c) 2011 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; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; @@ -93,7 +110,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public static bool CanShowAnalyzer(PropertyDefinition property) + public static bool CanShow(PropertyDefinition property) { var accessor = property.GetMethod ?? property.SetMethod; return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs index 84598997a..cbffc9b20 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs @@ -17,8 +17,8 @@ // DEALINGS IN THE SOFTWARE. using System; -using Mono.Cecil; using ICSharpCode.Decompiler; +using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { @@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer PropertyDefinition analyzedProperty; bool isIndexer; string prefix; - + public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "") { if (analyzedProperty == null) @@ -37,28 +37,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.prefix = prefix; this.LazyLoading = true; } - - public override object Icon { + + public override object Icon + { get { return PropertyTreeNode.GetIcon(analyzedProperty, isIndexer); } } - - public override object Text { - get { + + public override object Text + { + get + { // TODO: This way of formatting is not suitable for properties which explicitly implement interfaces. - return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language, isIndexer); } + return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language, isIndexer); + } } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; MainWindow.Instance.JumpToReference(analyzedProperty); } - + protected override void LoadChildren() { - if(AnalyzedPropertyAccessorsTreeNode.CanShow(analyzedProperty)) + if (AnalyzedPropertyAccessorsTreeNode.CanShow(analyzedProperty)) this.Children.Add(new AnalyzedPropertyAccessorsTreeNode(analyzedProperty)); - if (AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(analyzedProperty)) + if (AnalyzedPropertyOverridesTreeNode.CanShow(analyzedProperty)) this.Children.Add(new AnalyzedPropertyOverridesTreeNode(analyzedProperty)); //if (analyzedProperty.HasBody) // this.Children.Add(new AnalyzedMethodUsesNode(analyzedProperty)); @@ -80,7 +84,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return false; return AnalyzedPropertyAccessorsTreeNode.CanShow(property) - || AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(property); + || AnalyzedPropertyOverridesTreeNode.CanShow(property); } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs index da9670eaf..0e66ef86a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -179,7 +179,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return !(isAdderPublic || isRemoverPublic); } - public static bool CanShowAnalyzer(TypeDefinition type) + public static bool CanShow(TypeDefinition type) { return true; } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs index 258ff6e75..769f62198 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -110,7 +110,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return false; } - public static bool CanShowAnalyzer(TypeDefinition type) + public static bool CanShow(TypeDefinition type) { return !(type.IsEnum); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index 578ddd582..b79d123ef 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - public static bool CanShowAnalyzer(TypeDefinition type) + public static bool CanShow(TypeDefinition type) { if (type.IsClass && !type.IsEnum) { return type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs index 58548a967..8bcc8c1db 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs @@ -54,13 +54,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { - if (AnalyzedTypeInstantiationsTreeNode.CanShowAnalyzer(analyzedType)) + if (AnalyzedTypeInstantiationsTreeNode.CanShow(analyzedType)) this.Children.Add(new AnalyzedTypeInstantiationsTreeNode(analyzedType)); - if (AnalyzedTypeExposedByTreeNode.CanShowAnalyzer(analyzedType)) + if (AnalyzedTypeExposedByTreeNode.CanShow(analyzedType)) this.Children.Add(new AnalyzedTypeExposedByTreeNode(analyzedType)); - if (AnalyzedTypeExtensionMethodsTreeNode.CanShowAnalyzer(analyzedType)) + if (AnalyzedTypeExtensionMethodsTreeNode.CanShow(analyzedType)) this.Children.Add(new AnalyzedTypeExtensionMethodsTreeNode(analyzedType)); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs index 8ab995e39..005524226 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs @@ -25,10 +25,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public class AnalyzerTreeNode : SharpTreeNode { Language language; - - public Language Language { + + public Language Language + { get { return language; } - set { + set + { if (language != value) { language = value; foreach (var child in this.Children.OfType()) @@ -36,22 +38,22 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } } - + public override bool CanDelete() { return Parent != null && Parent.IsRoot; } - + public override void DeleteCore() { Parent.Children.Remove(this); } - + public override void Delete() { DeleteCore(); } - + protected override void OnChildrenChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { diff --git a/ILSpy/TreeNodes/Analyzer/Helpers.cs b/ILSpy/TreeNodes/Analyzer/Helpers.cs index 25a74348f..1fcc9dbfd 100644 --- a/ILSpy/TreeNodes/Analyzer/Helpers.cs +++ b/ILSpy/TreeNodes/Analyzer/Helpers.cs @@ -1,4 +1,22 @@ -using System; +// Copyright (c) 2011 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; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 79746a288..11ce50dd7 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -1,11 +1,27 @@ -using System; +// Copyright (c) 2011 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; using System.Collections.Generic; using System.Linq; using System.Threading; -using Mono.Cecil; using ICSharpCode.NRefactory.Utils; -using ICSharpCode.TreeView; - +using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { From 24c0eaccb7c6587895e632f0da38eeb9daf5ccce Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Wed, 27 Apr 2011 12:23:07 +1000 Subject: [PATCH 3/6] Added Analyzer - Interface Method Implemented By --- .../Ast/TypesHierarchyHelpers.cs | 16 +++ ILSpy/ILSpy.csproj | 1 + ...zedInterfaceMethodImplementedByTreeNode.cs | 101 ++++++++++++++++++ .../Analyzer/AnalyzedMethodTreeNode.cs | 2 + 4 files changed, 120 insertions(+) create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs diff --git a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs index 5104ea7ba..ca1d72f8f 100644 --- a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs +++ b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs @@ -182,6 +182,22 @@ namespace ICSharpCode.Decompiler.Ast return true; } + public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType) + { + var candidateContext = CreateGenericContext(candidate.DeclaringType); + var gCandidate = candidateContext.ApplyTo(candidate); + + if (interfaceContextType is GenericInstanceType) { + var methodContext = new GenericContext(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments); + var gMethod = methodContext.ApplyTo(method); + return MatchMethod(gCandidate, gMethod); + } else { + var methodContext = CreateGenericContext(interfaceContextType.Resolve()); + var gMethod = candidateContext.ApplyTo(method); + return MatchMethod(gCandidate, gMethod); + } + } + private static bool MatchProperty(GenericContext candidate, GenericContext property) { var mCandidate = candidate.Item; diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 822a17db7..57858bc18 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -135,6 +135,7 @@ + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs new file mode 100644 index 000000000..d06256be7 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode + { + MethodDefinition analyzedMethod; + ThreadingSupport threading; + + public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod) + { + if (analyzedMethod == null) + throw new ArgumentNullException("analyzedMethod"); + + this.analyzedMethod = analyzedMethod; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + } + + public override object Text + { + get { return "Implemented By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + if (!type.HasInterfaces) + yield break; + TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType); + if (implementedInterfaceRef == null) + yield break; + + foreach (MethodDefinition method in type.Methods.Where(m => m.Name == analyzedMethod.Name)) { + if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef)) + yield return new AnalyzedMethodTreeNode(method); + yield break; + } + + foreach (MethodDefinition method in type.Methods) { + if (method.HasOverrides && method.Overrides.Any(m => m.Resolve() == analyzedMethod)) { + yield return new AnalyzedMethodTreeNode(method); + } + } + } + + public static bool CanShow(MethodDefinition method) + { + return method.DeclaringType.IsInterface; + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs index 053038fbb..52b1f8867 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs @@ -61,6 +61,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); if (AnalyzedMethodOverridesTreeNode.CanShow(analyzedMethod)) this.Children.Add(new AnalyzedMethodOverridesTreeNode(analyzedMethod)); + if (AnalyzedInterfaceMethodImplementedByTreeNode.CanShow(analyzedMethod)) + this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod)); } MemberReference IMemberTreeNode.Member From 9ea6f02482a669bc6b3a206be7fe024f15efbcda Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Wed, 27 Apr 2011 22:20:16 +1000 Subject: [PATCH 4/6] Added Analyzers - Interface Event and Property Implemented BY --- ILSpy/ILSpy.csproj | 2 + .../Analyzer/AnalyzedEventTreeNode.cs | 2 + ...yzedInterfaceEventImplementedByTreeNode.cs | 105 ++++++++++++++++++ ...dInterfacePropertyImplementedByTreeNode.cs | 105 ++++++++++++++++++ .../Analyzer/AnalyzedPropertyTreeNode.cs | 5 +- 5 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 57858bc18..0fce56c9c 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -135,7 +135,9 @@ + + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs index a8922eea8..d1cbc1f81 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs @@ -61,6 +61,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedEventAccessorsTreeNode(analyzedEvent)); if (AnalyzedEventOverridesTreeNode.CanShow(analyzedEvent)) this.Children.Add(new AnalyzedEventOverridesTreeNode(analyzedEvent)); + if (AnalyzedInterfaceEventImplementedByTreeNode.CanShow(analyzedEvent)) + this.Children.Add(new AnalyzedInterfaceEventImplementedByTreeNode(analyzedEvent)); } public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs new file mode 100644 index 000000000..40ed960f6 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs @@ -0,0 +1,105 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode + { + EventDefinition analyzedEvent; + MethodDefinition analyzedMethod; + ThreadingSupport threading; + + public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent) + { + if (analyzedEvent == null) + throw new ArgumentNullException("analyzedEvent"); + + this.analyzedEvent = analyzedEvent; + this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + } + + public override object Text + { + get { return "Implemented By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + if (!type.HasInterfaces) + yield break; + TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType); + if (implementedInterfaceRef == null) + yield break; + + foreach (EventDefinition ev in type.Events.Where(e => e.Name == analyzedEvent.Name)) { + MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod; + if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) + yield return new AnalyzedEventTreeNode(ev); + yield break; + } + + foreach (EventDefinition ev in type.Events.Where(e => e.Name.EndsWith(analyzedEvent.Name))) { + MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod; + if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) { + yield return new AnalyzedEventTreeNode(ev); + } + } + } + + public static bool CanShow(EventDefinition ev) + { + return ev.DeclaringType.IsInterface; + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs new file mode 100644 index 000000000..60ef3da26 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs @@ -0,0 +1,105 @@ +// Copyright (c) 2011 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; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.Decompiler.Ast; +using ICSharpCode.TreeView; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode + { + PropertyDefinition analyzedProperty; + MethodDefinition analyzedMethod; + ThreadingSupport threading; + + public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty) + { + if (analyzedProperty == null) + throw new ArgumentNullException("analyzedProperty"); + + this.analyzedProperty = analyzedProperty; + this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + } + + public override object Text + { + get { return "Implemented By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + IEnumerable FetchChildren(CancellationToken ct) + { + ScopedWhereUsedScopeAnalyzer analyzer; + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + return analyzer.PerformAnalysis(ct); + } + + IEnumerable FindReferencesInType(TypeDefinition type) + { + if (!type.HasInterfaces) + yield break; + TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.Resolve() == analyzedMethod.DeclaringType); + if (implementedInterfaceRef == null) + yield break; + + foreach (PropertyDefinition property in type.Properties.Where(e => e.Name == analyzedProperty.Name)) { + MethodDefinition accessor = property.GetMethod ?? property.SetMethod; + if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) + yield return new AnalyzedPropertyTreeNode(property); + yield break; + } + + foreach (PropertyDefinition property in type.Properties.Where(e => e.Name.EndsWith(analyzedProperty.Name))) { + MethodDefinition accessor = property.GetMethod ?? property.SetMethod; + if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) { + yield return new AnalyzedPropertyTreeNode(property); + } + } + } + + public static bool CanShow(PropertyDefinition property) + { + return property.DeclaringType.IsInterface; + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs index cbffc9b20..d6509d44e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs @@ -64,9 +64,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.Children.Add(new AnalyzedPropertyAccessorsTreeNode(analyzedProperty)); if (AnalyzedPropertyOverridesTreeNode.CanShow(analyzedProperty)) this.Children.Add(new AnalyzedPropertyOverridesTreeNode(analyzedProperty)); - //if (analyzedProperty.HasBody) - // this.Children.Add(new AnalyzedMethodUsesNode(analyzedProperty)); - //this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedProperty)); + if (AnalyzedInterfacePropertyImplementedByTreeNode.CanShow(analyzedProperty)) + this.Children.Add(new AnalyzedInterfacePropertyImplementedByTreeNode(analyzedProperty)); } public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member) From 6ae4df7ecc96c99cacbb63d8e561d8053fde1c0b Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Thu, 28 Apr 2011 13:10:36 +1000 Subject: [PATCH 5/6] Analyzer memory usage reduction. --- ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs | 3 +++ ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs | 4 ++++ ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs | 1 + .../TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs | 3 +++ 4 files changed, 11 insertions(+) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs index 88b6253a6..6419c0fcb 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs @@ -90,6 +90,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } } + + method.Body = null; + if (found) yield return new AnalyzedMethodTreeNode(method); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index c21351a7a..ebf997313 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -86,6 +86,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer break; } } + + + method.Body = null; + if (found) yield return new AnalyzedMethodTreeNode(method); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs index eabc686c5..a8ce330d5 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs @@ -58,6 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (var m in GetUsedMethods().Distinct()) { this.Children.Add(new AnalyzedMethodTreeNode(m)); } + analyzedMethod.Body = null; } IEnumerable GetUsedMethods() diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index b79d123ef..5f66643b4 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -99,6 +99,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } } + + method.Body = null; + if (found) yield return new AnalyzedMethodTreeNode(method); } From e40fe48a5bb1652ed5e336db01378d334b0d8084 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 30 Apr 2011 11:36:36 +1000 Subject: [PATCH 6/6] Analyzer code clean-up. --- ILSpy/BamlDecompiler.cs | 4 +- ILSpy/ILSpy.csproj | 6 +- .../Analyzer/AnalyzeContextMenuEntry.cs | 5 +- .../AnalyzedEventAccessorsTreeNode.cs | 9 +-- .../AnalyzedEventOverridesTreeNode.cs | 15 ++-- .../Analyzer/AnalyzedEventTreeNode.cs | 8 +- ...Node.cs => AnalyzedFieldAccessTreeNode.cs} | 20 ++--- ...dFieldNode.cs => AnalyzedFieldTreeNode.cs} | 10 +-- ...yzedInterfaceEventImplementedByTreeNode.cs | 12 +-- ...zedInterfaceMethodImplementedByTreeNode.cs | 10 +-- ...dInterfacePropertyImplementedByTreeNode.cs | 12 +-- .../AnalyzedMethodOverridesTreeNode.cs | 25 +++--- .../Analyzer/AnalyzedMethodTreeNode.cs | 8 +- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 16 ++-- ...sNode.cs => AnalyzedMethodUsesTreeNode.cs} | 12 +-- .../AnalyzedPropertyAccessorsTreeNode.cs | 9 +-- .../AnalyzedPropertyOverridesTreeNode.cs | 13 ++-- .../Analyzer/AnalyzedPropertyTreeNode.cs | 10 +-- .../Analyzer/AnalyzedTypeExposedByTreeNode.cs | 20 ++--- .../AnalyzedTypeExtensionMethodsTreeNode.cs | 36 ++------- .../AnalyzedTypeInstantiationsTreeNode.cs | 17 ++-- .../Analyzer/AnalyzedTypeTreeNode.cs | 4 +- ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs | 2 +- ILSpy/TreeNodes/Analyzer/Helpers.cs | 2 +- .../Analyzer/ScopedWhereUsedAnalyzer.cs | 18 ++--- ILSpy/TreeNodes/AssemblyTreeNode.cs | 78 ++++++++++--------- ILSpy/TreeNodes/ResourceEntryNode.cs | 46 ++++++----- ILSpy/TreeNodes/XamlResourceNode.cs | 2 +- 28 files changed, 209 insertions(+), 220 deletions(-) rename ILSpy/TreeNodes/Analyzer/{AnalyzedFieldAccessNode.cs => AnalyzedFieldAccessTreeNode.cs} (81%) rename ILSpy/TreeNodes/Analyzer/{AnalyzedFieldNode.cs => AnalyzedFieldTreeNode.cs} (85%) rename ILSpy/TreeNodes/Analyzer/{AnalyzedMethodUsesNode.cs => AnalyzedMethodUsesTreeNode.cs} (87%) diff --git a/ILSpy/BamlDecompiler.cs b/ILSpy/BamlDecompiler.cs index 10682b794..d14d6589c 100644 --- a/ILSpy/BamlDecompiler.cs +++ b/ILSpy/BamlDecompiler.cs @@ -400,8 +400,8 @@ namespace ICSharpCode.ILSpy.Baml BamlDecompiler decompiler = CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, asm.FileName); MemoryStream bamlStream = new MemoryStream(); - data.Position = 0; - data.CopyTo(bamlStream); + Data.Position = 0; + Data.CopyTo(bamlStream); output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName, new ConnectMethodDecompiler(asm), new AssemblyResolver(asm))); return true; diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 0fce56c9c..8661f9202 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -178,11 +178,11 @@ - - + + - + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs index 9f56b086e..9af10e581 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs @@ -24,7 +24,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { [ExportContextMenuEntry(Header = "Analyze", Icon = "images/Search.png")] - sealed class AnalyzeContextMenuEntry : IContextMenuEntry + internal sealed class AnalyzeContextMenuEntry : IContextMenuEntry { public bool IsVisible(SharpTreeNode[] selectedNodes) { @@ -41,6 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer || Analyzer.AnalyzedEventTreeNode.CanShow(node.Member))) return false; } + return true; } @@ -54,7 +55,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer MainWindow.Instance.AddToAnalyzer(new AnalyzedTypeTreeNode(type)); FieldDefinition field = node.Member as FieldDefinition; if (field != null) - MainWindow.Instance.AddToAnalyzer(new AnalyzedFieldNode(field)); + MainWindow.Instance.AddToAnalyzer(new AnalyzedFieldTreeNode(field)); MethodDefinition method = node.Member as MethodDefinition; if (method != null) MainWindow.Instance.AddToAnalyzer(new AnalyzedMethodTreeNode(method)); diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs index 9a60a031e..d350147f1 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs @@ -21,15 +21,12 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - public class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode { - EventDefinition analyzedEvent; - public AnalyzedEventAccessorsTreeNode(EventDefinition analyzedEvent) { if (analyzedEvent == null) throw new ArgumentNullException("analyzedEvent"); - this.analyzedEvent = analyzedEvent; if (analyzedEvent.AddMethod != null) this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.AddMethod, "add")); @@ -54,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return !MainWindow.Instance.CurrentLanguage.ShowMember(property.AddMethod ?? property.RemoveMethod); } - class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode + internal class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode { - string name; + private string name; public AnalyzedEventAccessorTreeNode(MethodDefinition analyzedMethod, string name) : base(analyzedMethod) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index 306e86017..113ffd029 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -27,10 +27,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerTreeNode { - readonly EventDefinition analyzedEvent; - readonly ThreadingSupport threading; + private readonly EventDefinition analyzedEvent; + private readonly ThreadingSupport threading; public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent) { @@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public override object Text { - get { return "Overriden By"; } + get { return "Overridden By"; } } public override object Icon @@ -66,19 +66,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); } - IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) + private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) { assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + // use parallelism only on the assembly level (avoid locks within Cecil) return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); } - IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) { string asmName = asm.AssemblyDefinition.Name.Name; string name = analyzedEvent.Name; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs index d1cbc1f81..3ebf2d23b 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs @@ -21,15 +21,15 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedEventTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedEventTreeNode : AnalyzerTreeNode { - EventDefinition analyzedEvent; - string prefix; + private readonly EventDefinition analyzedEvent; + private readonly string prefix; public AnalyzedEventTreeNode(EventDefinition analyzedEvent, string prefix = "") { if (analyzedEvent == null) - throw new ArgumentNullException("analyzedMethod"); + throw new ArgumentNullException("analyzedEvent"); this.analyzedEvent = analyzedEvent; this.prefix = prefix; this.LazyLoading = true; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs similarity index 81% rename from ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs index 6419c0fcb..c18b62d0f 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs @@ -25,13 +25,13 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedFieldAccessNode : AnalyzerTreeNode + internal sealed class AnalyzedFieldAccessTreeNode : AnalyzerTreeNode { - readonly bool showWrites; // true: show writes; false: show read access - readonly FieldDefinition analyzedField; - readonly ThreadingSupport threading; + private readonly bool showWrites; // true: show writes; false: show read access + private readonly FieldDefinition analyzedField; + private readonly ThreadingSupport threading; - public AnalyzedFieldAccessNode(FieldDefinition analyzedField, bool showWrites) + public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites) { if (analyzedField == null) throw new ArgumentNullException("analyzedField"); @@ -66,13 +66,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedField, FindReferencesInType); return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedField.Name; string declTypeName = analyzedField.DeclaringType.FullName; @@ -84,7 +84,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (Instruction instr in method.Body.Instructions) { if (CanBeReference(instr.OpCode.Code)) { FieldReference fr = instr.Operand as FieldReference; - if (fr != null && fr.Name == name && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) { + if (fr != null && fr.Name == name && + Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && + fr.Resolve() == analyzedField) { found = true; break; } @@ -98,7 +100,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - bool CanBeReference(Code code) + private bool CanBeReference(Code code) { switch (code) { case Code.Ldfld: diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs similarity index 85% rename from ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs index a5e65ef6e..6e08c566e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldTreeNode.cs @@ -21,11 +21,11 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedFieldNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedFieldTreeNode : AnalyzerTreeNode, IMemberTreeNode { - FieldDefinition analyzedField; + private readonly FieldDefinition analyzedField; - public AnalyzedFieldNode(FieldDefinition analyzedField) + public AnalyzedFieldTreeNode(FieldDefinition analyzedField) { if (analyzedField == null) throw new ArgumentNullException("analyzedField"); @@ -55,9 +55,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { - this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, false)); + this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, false)); if (!analyzedField.IsLiteral) - this.Children.Add(new AnalyzedFieldAccessNode(analyzedField, true)); + this.Children.Add(new AnalyzedFieldAccessTreeNode(analyzedField, true)); } MemberReference IMemberTreeNode.Member diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs index 40ed960f6..c17f3ec36 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs @@ -26,11 +26,11 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerTreeNode { - EventDefinition analyzedEvent; - MethodDefinition analyzedMethod; - ThreadingSupport threading; + private readonly EventDefinition analyzedEvent; + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent) { @@ -67,14 +67,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs index d06256be7..6ce86fc8b 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs @@ -26,10 +26,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerTreeNode { - MethodDefinition analyzedMethod; - ThreadingSupport threading; + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinition analyzedMethod) { @@ -65,14 +65,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs index 60ef3da26..06a4fb961 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs @@ -26,11 +26,11 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerTreeNode { - PropertyDefinition analyzedProperty; - MethodDefinition analyzedMethod; - ThreadingSupport threading; + private readonly PropertyDefinition analyzedProperty; + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty) { @@ -67,14 +67,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (!type.HasInterfaces) yield break; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index 70da7b542..79e4e9782 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -14,10 +14,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Searches for overrides of the analyzed method. /// - class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerTreeNode { - readonly MethodDefinition analyzedMethod; - readonly ThreadingSupport threading; + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod) { @@ -46,33 +46,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void OnCollapsing() { - if (threading.IsRunning) - { + if (threading.IsRunning) { this.LazyLoading = true; threading.Cancel(); this.Children.Clear(); } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); } - IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) + private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) { assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + // use parallelism only on the assembly level (avoid locks within Cecil) return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); } - IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) { string asmName = asm.AssemblyDefinition.Name.Name; string name = analyzedMethod.Name; string declTypeName = analyzedMethod.DeclaringType.FullName; - foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) - { + foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); SharpTreeNode newNode = null; try { @@ -91,6 +90,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer catch (ReferenceResolvingException) { // ignore this type definition. maybe add a notification about such cases. } + if (newNode != null) yield return newNode; } @@ -98,7 +98,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public static bool CanShow(MethodDefinition method) { - return method.IsVirtual && !method.IsFinal && !method.DeclaringType.IsSealed && !method.DeclaringType.IsInterface; // interfaces are temporarly disabled + return method.IsVirtual && + !method.IsFinal && + !method.DeclaringType.IsSealed && + !method.DeclaringType.IsInterface; // interface methods are definitions not implementations - cannot be overridden } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs index 52b1f8867..2ecc053f8 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs @@ -21,10 +21,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode { - MethodDefinition analyzedMethod; - string prefix; + private readonly MethodDefinition analyzedMethod; + private readonly string prefix; public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "") { @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { if (analyzedMethod.HasBody) - this.Children.Add(new AnalyzedMethodUsesNode(analyzedMethod)); + this.Children.Add(new AnalyzedMethodUsesTreeNode(analyzedMethod)); this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); if (AnalyzedMethodOverridesTreeNode.CanShow(analyzedMethod)) this.Children.Add(new AnalyzedMethodOverridesTreeNode(analyzedMethod)); diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index ebf997313..2a7cf784f 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -25,10 +25,10 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode { - MethodDefinition analyzedMethod; - ThreadingSupport threading; + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) { @@ -64,7 +64,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; @@ -72,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { string name = analyzedMethod.Name; foreach (MethodDefinition method in type.Methods) { @@ -81,13 +81,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer continue; foreach (Instruction instr in method.Body.Instructions) { MethodReference mr = instr.Operand as MethodReference; - if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) { + if (mr != null && + mr.Name == name && + Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && + mr.Resolve() == analyzedMethod) { found = true; break; } } - method.Body = null; if (found) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs similarity index 87% rename from ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs index a8ce330d5..5553f5a98 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs @@ -27,11 +27,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Shows the methods that are used by this method. /// - sealed class AnalyzedMethodUsesNode : AnalyzerTreeNode + internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerTreeNode { - MethodDefinition analyzedMethod; + private readonly MethodDefinition analyzedMethod; - public AnalyzedMethodUsesNode(MethodDefinition analyzedMethod) + public AnalyzedMethodUsesTreeNode(MethodDefinition analyzedMethod) { if (analyzedMethod == null) throw new ArgumentNullException("analyzedMethod"); @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { foreach (var f in GetUsedFields().Distinct()) { - this.Children.Add(new AnalyzedFieldNode(f)); + this.Children.Add(new AnalyzedFieldTreeNode(f)); } foreach (var m in GetUsedMethods().Distinct()) { this.Children.Add(new AnalyzedMethodTreeNode(m)); @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer analyzedMethod.Body = null; } - IEnumerable GetUsedMethods() + private IEnumerable GetUsedMethods() { foreach (Instruction instr in analyzedMethod.Body.Instructions) { MethodReference mr = instr.Operand as MethodReference; @@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable GetUsedFields() + private IEnumerable GetUsedFields() { foreach (Instruction instr in analyzedMethod.Body.Instructions) { FieldReference fr = instr.Operand as FieldReference; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs index d6ba5ae67..941801dbe 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs @@ -21,15 +21,12 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - public class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode + public sealed class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode { - PropertyDefinition analyzedProperty; - public AnalyzedPropertyAccessorsTreeNode(PropertyDefinition analyzedProperty) { if (analyzedProperty == null) throw new ArgumentNullException("analyzedProperty"); - this.analyzedProperty = analyzedProperty; if (analyzedProperty.GetMethod != null) this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get")); @@ -54,9 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod); } - class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode + private class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode { - string name; + private readonly string name; public AnalyzedPropertyAccessorTreeNode(MethodDefinition analyzedMethod, string name) : base(analyzedMethod) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index 7ebc563c3..440a54f6e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -28,10 +28,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode { - readonly PropertyDefinition analyzedProperty; - readonly ThreadingSupport threading; + private readonly PropertyDefinition analyzedProperty; + private readonly ThreadingSupport threading; public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty) { @@ -67,19 +67,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); } - IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) + private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) { assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + // use parallelism only on the assembly level (avoid locks within Cecil) return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); } - IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) { string asmName = asm.AssemblyDefinition.Name.Name; string name = analyzedProperty.Name; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs index d6509d44e..bba0b3362 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs @@ -22,16 +22,16 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedPropertyTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedPropertyTreeNode : AnalyzerTreeNode { - PropertyDefinition analyzedProperty; - bool isIndexer; - string prefix; + private readonly PropertyDefinition analyzedProperty; + private readonly bool isIndexer; + private readonly string prefix; public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "") { if (analyzedProperty == null) - throw new ArgumentNullException("analyzedMethod"); + throw new ArgumentNullException("analyzedProperty"); this.isIndexer = analyzedProperty.IsIndexer(); this.analyzedProperty = analyzedProperty; this.prefix = prefix; diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs index 0e66ef86a..00e09e37d 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -24,11 +24,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerTreeNode { - TypeDefinition analyzedType; - ThreadingSupport threading; - bool IsSystemObject; + private readonly TypeDefinition analyzedType; + private readonly ThreadingSupport threading; public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType) { @@ -38,8 +37,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedType = analyzedType; this.threading = new ThreadingSupport(); this.LazyLoading = true; - - this.IsSystemObject = (analyzedType.FullName == "System.Object"); } public override object Text @@ -66,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; @@ -74,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { if (analyzedType.IsEnum && type == analyzedType) yield break; @@ -84,7 +81,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (FieldDefinition field in type.Fields) { if (TypeIsExposedBy(field)) - yield return new AnalyzedFieldNode(field); + yield return new AnalyzedFieldTreeNode(field); } foreach (PropertyDefinition property in type.Properties) { @@ -165,14 +162,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return false; } - private bool IsPrivate(PropertyDefinition property) + private static bool IsPrivate(PropertyDefinition property) { bool isGetterPublic = (property.GetMethod != null && !property.GetMethod.IsPrivate); bool isSetterPublic = (property.SetMethod != null && !property.SetMethod.IsPrivate); return !(isGetterPublic || isSetterPublic); } - private bool IsPrivate(EventDefinition eventDef) + private static bool IsPrivate(EventDefinition eventDef) { bool isAdderPublic = (eventDef.AddMethod != null && !eventDef.AddMethod.IsPrivate); bool isRemoverPublic = (eventDef.RemoveMethod != null && !eventDef.RemoveMethod.IsPrivate); @@ -183,6 +180,5 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { return true; } - } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs index 769f62198..237131b2f 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -25,11 +25,10 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode + internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerTreeNode { - TypeDefinition analyzedType; - ThreadingSupport threading; - bool IsSystemObject; + private readonly TypeDefinition analyzedType; + private readonly ThreadingSupport threading; public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType) { @@ -39,8 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.analyzedType = analyzedType; this.threading = new ThreadingSupport(); this.LazyLoading = true; - - this.IsSystemObject = (analyzedType.FullName == "System.Object"); } public override object Text @@ -67,7 +64,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; @@ -75,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { foreach (MethodDefinition method in type.Methods) { if (method.IsStatic && method.HasCustomAttributes) { @@ -88,32 +85,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - private bool TypeIsExposedBy(MethodDefinition method) - { - if (method.IsPrivate) - return false; - - // exclude methods with 'semantics'. for example, property getters & setters. - if (method.SemanticsAttributes != MethodSemanticsAttributes.None) - return false; - - if (method.ReturnType.Resolve() == analyzedType) - return true; - - if (method.HasParameters) { - foreach (var parameter in method.Parameters) { - if (parameter.ParameterType.Resolve() == analyzedType) - return true; - } - } - - return false; - } - public static bool CanShow(TypeDefinition type) { return !(type.IsEnum); } - } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index 5f66643b4..f11fca495 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -27,11 +27,11 @@ using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode + internal sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerTreeNode { - TypeDefinition analyzedType; - ThreadingSupport threading; - bool IsSystemObject; + private readonly TypeDefinition analyzedType; + private readonly ThreadingSupport threading; + private readonly bool isSystemObject; public AnalyzedTypeInstantiationsTreeNode(TypeDefinition analyzedType) { @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.threading = new ThreadingSupport(); this.LazyLoading = true; - this.IsSystemObject = (analyzedType.FullName == "System.Object"); + this.isSystemObject = (analyzedType.FullName == "System.Object"); } public override object Text @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FetchChildren(CancellationToken ct) + private IEnumerable FetchChildren(CancellationToken ct) { ScopedWhereUsedScopeAnalyzer analyzer; @@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return analyzer.PerformAnalysis(ct); } - IEnumerable FindReferencesInType(TypeDefinition type) + private IEnumerable FindReferencesInType(TypeDefinition type) { foreach (MethodDefinition method in type.Methods) { bool found = false; @@ -87,7 +87,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer // ignore chained constructors // (since object is the root of everything, we can short circuit the test in this case) if (method.Name == ".ctor" && - (IsSystemObject || analyzedType == type || TypesHierarchyHelpers.IsBaseType(analyzedType, type, false))) + (isSystemObject || analyzedType == type || TypesHierarchyHelpers.IsBaseType(analyzedType, type, false))) continue; foreach (Instruction instr in method.Body.Instructions) { @@ -114,6 +114,5 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } return false; } - } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs index 8bcc8c1db..bc50ffbec 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeTreeNode.cs @@ -21,9 +21,9 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode + internal class AnalyzedTypeTreeNode : AnalyzerTreeNode, IMemberTreeNode { - TypeDefinition analyzedType; + private readonly TypeDefinition analyzedType; public AnalyzedTypeTreeNode(TypeDefinition analyzedType) { diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs index 005524226..29e8e76f0 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerTreeNode.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { public class AnalyzerTreeNode : SharpTreeNode { - Language language; + private Language language; public Language Language { diff --git a/ILSpy/TreeNodes/Analyzer/Helpers.cs b/ILSpy/TreeNodes/Analyzer/Helpers.cs index 1fcc9dbfd..778996a72 100644 --- a/ILSpy/TreeNodes/Analyzer/Helpers.cs +++ b/ILSpy/TreeNodes/Analyzer/Helpers.cs @@ -24,7 +24,7 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - static class Helpers + internal static class Helpers { public static bool IsReferencedBy(TypeDefinition type, TypeReference typeRef) { diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 11ce50dd7..48eb21bc5 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -108,7 +108,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return FindReferencesInTypeScope(ct); } - if (memberAccessibility == Accessibility.Internal || memberAccessibility == Accessibility.FamilyAndInternal || typeAccessibility == Accessibility.Internal || @@ -136,7 +135,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - private Accessibility GetNestedTypeAccessibility(TypeDefinition type) + private static Accessibility GetNestedTypeAccessibility(TypeDefinition type) { Accessibility result; switch (type.Attributes & TypeAttributes.VisibilityMask) { @@ -177,22 +176,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer Public } - - IEnumerable FindReferencesInAssemblyAndFriends(CancellationToken ct) + private IEnumerable FindReferencesInAssemblyAndFriends(CancellationToken ct) { var assemblies = GetAssemblyAndAnyFriends(assemblyScope, ct); + // use parallelism only on the assembly level (avoid locks within Cecil) return assemblies.AsParallel().WithCancellation(ct).SelectMany((AssemblyDefinition a) => FindReferencesInAssembly(a, ct)); } - IEnumerable FindReferencesGlobal(CancellationToken ct) + private IEnumerable FindReferencesGlobal(CancellationToken ct) { var assemblies = GetReferencingAssemblies(assemblyScope, ct); + // use parallelism only on the assembly level (avoid locks within Cecil) return assemblies.AsParallel().WithCancellation(ct).SelectMany((AssemblyDefinition asm) => FindReferencesInAssembly(asm, ct)); } - IEnumerable FindReferencesInAssembly(AssemblyDefinition asm, CancellationToken ct) + private IEnumerable FindReferencesInAssembly(AssemblyDefinition asm, CancellationToken ct) { foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); @@ -203,7 +203,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable FindReferencesInTypeScope(CancellationToken ct) + private IEnumerable FindReferencesInTypeScope(CancellationToken ct) { foreach (TypeDefinition type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); @@ -214,7 +214,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct) + private IEnumerable GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct) { yield return asm; @@ -236,7 +236,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } - IEnumerable GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct) + private IEnumerable GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct) { yield return asm; diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index 27a03ba1c..73dbb38da 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -41,35 +41,39 @@ namespace ICSharpCode.ILSpy.TreeNodes public sealed class AssemblyTreeNode : ILSpyTreeNode { readonly LoadedAssembly assembly; - readonly List classes = new List(); readonly Dictionary namespaces = new Dictionary(); - + public AssemblyTreeNode(LoadedAssembly assembly) { if (assembly == null) throw new ArgumentNullException("assembly"); - + this.assembly = assembly; - + assembly.ContinueWhenLoaded(OnAssemblyLoaded, TaskScheduler.FromCurrentSynchronizationContext()); - + this.LazyLoading = true; } - - public AssemblyList AssemblyList { + + public AssemblyList AssemblyList + { get { return assembly.AssemblyList; } } - - public LoadedAssembly LoadedAssembly { + + public LoadedAssembly LoadedAssembly + { get { return assembly; } } - - public override object Text { + + public override object Text + { get { return HighlightSearchMatch(assembly.ShortName); } } - - public override object Icon { - get { + + public override object Icon + { + get + { if (assembly.IsLoaded) { return assembly.HasLoadError ? Images.AssemblyWarning : Images.Assembly; } else { @@ -77,11 +81,12 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - - public override bool ShowExpander { + + public override bool ShowExpander + { get { return !assembly.HasLoadError; } } - + void OnAssemblyLoaded(Task assemblyTask) { // change from "Loading" icon to final icon @@ -90,14 +95,15 @@ namespace ICSharpCode.ILSpy.TreeNodes if (assemblyTask.IsFaulted) { RaisePropertyChanged("ShowExpander"); // cannot expand assemblies with load error // observe the exception so that the Task's finalizer doesn't re-throw it - try { assemblyTask.Wait(); } catch (AggregateException) {} + try { assemblyTask.Wait(); } + catch (AggregateException) { } } else { RaisePropertyChanged("Text"); // shortname might have changed } } - + Dictionary typeDict = new Dictionary(); - + protected override void LoadChildren() { AssemblyDefinition assemblyDefinition = assembly.AssemblyDefinition; @@ -106,7 +112,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return; } ModuleDefinition mainModule = assemblyDefinition.MainModule; - + this.Children.Add(new ReferenceFolderTreeNode(mainModule, this)); if (mainModule.HasResources) this.Children.Add(new ResourceListTreeNode(mainModule)); @@ -128,7 +134,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.Children.Add(ns); } } - + public TypeTreeNode FindTypeNode(TypeDefinition def) { if (def == null) @@ -140,41 +146,41 @@ namespace ICSharpCode.ILSpy.TreeNodes else return null; } - + public override bool CanDrag(SharpTreeNode[] nodes) { return nodes.All(n => n is AssemblyTreeNode); } - + public override void StartDrag(DependencyObject dragSource, SharpTreeNode[] nodes) { DragDrop.DoDragDrop(dragSource, Copy(nodes), DragDropEffects.All); } - + public override bool CanDelete() { return true; } - + public override void Delete() { DeleteCore(); } - + public override void DeleteCore() { assembly.AssemblyList.Unload(assembly); } - + internal const string DataFormat = "ILSpyAssemblies"; - + public override IDataObject Copy(SharpTreeNode[] nodes) { DataObject dataObject = new DataObject(); dataObject.SetData(DataFormat, nodes.OfType().Select(n => n.LoadedAssembly.FileName).ToArray()); return dataObject; } - + public override FilterResult Filter(FilterSettings settings) { if (settings.SearchTermMatches(assembly.ShortName)) @@ -182,13 +188,13 @@ namespace ICSharpCode.ILSpy.TreeNodes else return FilterResult.Recurse; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { assembly.WaitUntilLoaded(); // necessary so that load errors are passed on to the caller language.DecompileAssembly(assembly, output, options); } - + public override bool Save(DecompilerTextView textView) { Language language = this.Language; @@ -215,12 +221,12 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - textView.SaveToDisk(language, new[]{this}, options, dlg.FileName); + textView.SaveToDisk(language, new[] { this }, options, dlg.FileName); } return true; } } - + [ExportContextMenuEntry(Header = "_Remove", Icon = "images/Delete.png")] sealed class RemoveAssembly : IContextMenuEntry { @@ -228,12 +234,12 @@ namespace ICSharpCode.ILSpy.TreeNodes { return selectedNodes.All(n => n is AssemblyTreeNode); } - + public bool IsEnabled(SharpTreeNode[] selectedNodes) { return true; } - + public void Execute(SharpTreeNode[] selectedNodes) { foreach (var node in selectedNodes) { diff --git a/ILSpy/TreeNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceEntryNode.cs index f642c1140..c2b815d18 100644 --- a/ILSpy/TreeNodes/ResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceEntryNode.cs @@ -22,17 +22,25 @@ namespace ICSharpCode.ILSpy.TreeNodes /// public class ResourceEntryNode : ILSpyTreeNode { - protected readonly string key; - protected readonly Stream data; - - public override object Text { + private readonly string key; + private readonly Stream data; + + public override object Text + { get { return key.ToString(); } } - - public override object Icon { + + public override object Icon + { get { return Images.Resource; } } - + + protected Stream Data + { + get { return data; } + } + + public ResourceEntryNode(string key, Stream data) { if (key == null) @@ -42,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.key = key; this.data = data; } - + public static ILSpyTreeNode Create(string key, Stream data) { ILSpyTreeNode result = null; @@ -53,12 +61,12 @@ namespace ICSharpCode.ILSpy.TreeNodes } return result ?? new ResourceEntryNode(key, data); } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.WriteCommentLine(output, string.Format("{0} = {1}", key, data)); } - + public override bool Save(DecompilerTextView textView) { SaveFileDialog dlg = new SaveFileDialog(); @@ -72,12 +80,12 @@ namespace ICSharpCode.ILSpy.TreeNodes return true; } } - + [Export(typeof(IResourceNodeFactory))] sealed class ImageResourceNodeFactory : IResourceNodeFactory { static readonly string[] imageFileExtensions = { ".png", ".gif", ".bmp", ".jpg", ".ico" }; - + public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource) { EmbeddedResource er = resource as EmbeddedResource; @@ -86,7 +94,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } return null; } - + public ILSpyTreeNode CreateNode(string key, Stream data) { foreach (string fileExt in imageFileExtensions) { @@ -96,10 +104,11 @@ namespace ICSharpCode.ILSpy.TreeNodes return null; } } - + sealed class ImageResourceEntryNode : ResourceEntryNode { - public ImageResourceEntryNode(string key, Stream data) : base(key, data) + public ImageResourceEntryNode(string key, Stream data) + : base(key, data) { } @@ -112,17 +121,18 @@ namespace ICSharpCode.ILSpy.TreeNodes { try { AvalonEditTextOutput output = new AvalonEditTextOutput(); - data.Position = 0; + Data.Position = 0; BitmapImage image = new BitmapImage(); image.BeginInit(); - image.StreamSource = data; + image.StreamSource = Data; image.EndInit(); output.AddUIElement(() => new Image { Source = image }); output.WriteLine(); output.AddButton(Images.Save, "Save", delegate { Save(null); }); textView.Show(output, null); return true; - } catch (Exception) { + } + catch (Exception) { return false; } } diff --git a/ILSpy/TreeNodes/XamlResourceNode.cs b/ILSpy/TreeNodes/XamlResourceNode.cs index 7610ca6b7..930d10f15 100644 --- a/ILSpy/TreeNodes/XamlResourceNode.cs +++ b/ILSpy/TreeNodes/XamlResourceNode.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.Xaml try { // cache read XAML because stream will be closed after first read if (xaml == null) { - using (var reader = new StreamReader(data)) { + using (var reader = new StreamReader(Data)) { xaml = reader.ReadToEnd(); } }