From c9f2dc1069aa85b4f0eaabe444d2dc5006f1e4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sun, 17 Apr 2011 18:10:17 +0200 Subject: [PATCH 1/3] Minor ContextMenu displaying problems fixed. --- ILSpy/ContextMenuEntry.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ILSpy/ContextMenuEntry.cs b/ILSpy/ContextMenuEntry.cs index ba86b487d..1b50ab88a 100644 --- a/ILSpy/ContextMenuEntry.cs +++ b/ILSpy/ContextMenuEntry.cs @@ -65,7 +65,9 @@ namespace ICSharpCode.ILSpy { var provider = new ContextMenuProvider(treeView); treeView.ContextMenuOpening += provider.treeView_ContextMenuOpening; - treeView.ContextMenuClosing -= provider.treeView_ContextMenuClosing; + // Context menu is shown only when the ContextMenu property is not null before the + // ContextMenuOpening event handler is called. + treeView.ContextMenu = new ContextMenu(); } readonly SharpTreeView treeView; @@ -114,11 +116,9 @@ namespace ICSharpCode.ILSpy } if (menu.Items.Count > 0) treeView.ContextMenu = menu; - } - - void treeView_ContextMenuClosing(object sender, ContextMenuEventArgs e) - { - treeView.ContextMenu = null; + else + // hide the context menu. + e.Handled = true; } } } From 680a3730d1c78603aebe3e356644390535c43437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sun, 17 Apr 2011 18:15:55 +0200 Subject: [PATCH 2/3] Fixed NullReferenceException errors caused by unresolved references. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 40 ++++++++------ .../Ast/TypesHierarchyHelpers.cs | 54 +++++++++++++------ ICSharpCode.Decompiler/CecilExtensions.cs | 10 +++- .../ICSharpCode.Decompiler.csproj | 1 + .../ReferenceResolvingException.cs | 50 +++++++++++++++++ .../AnalyzedPropertyOverridesTreeNode.cs | 25 ++++++--- .../AnalyzerMethodOverridesTreeNode.cs | 26 +++++---- 7 files changed, 156 insertions(+), 50 deletions(-) create mode 100644 ICSharpCode.Decompiler/ReferenceResolvingException.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 02e73d4d4..1d7859793 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -624,10 +624,14 @@ namespace ICSharpCode.Decompiler.Ast if (!methodDef.DeclaringType.IsInterface) { if (!methodDef.HasOverrides) { astMethod.Modifiers = ConvertModifiers(methodDef); - if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) { - if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any()) - astMethod.Modifiers |= Modifiers.New; - } + if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) + try { + if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any()) + astMethod.Modifiers |= Modifiers.New; + } + catch (ReferenceResolvingException) { + // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. + } } else astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType); astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); @@ -739,17 +743,23 @@ namespace ICSharpCode.Decompiler.Ast getterModifiers = ConvertModifiers(propDef.GetMethod); setterModifiers = ConvertModifiers(propDef.SetMethod); astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers); - if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) - foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) - if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) { - var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod); - astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask)); - break; - } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) - break; - if (accessor.IsVirtual ^ !accessor.IsNewSlot) { - if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any()) - astProp.Modifiers |= Modifiers.New; + try { + if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) + foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) + if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) { + var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod); + astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask)); + break; + } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) + break; + + if (accessor.IsVirtual ^ !accessor.IsNewSlot) { + if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any()) + astProp.Modifiers |= Modifiers.New; + } + } + catch (ReferenceResolvingException) { + // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. } } astProp.Name = CleanName(propDef.Name); diff --git a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs index 4668b1f8f..c9105d4e7 100644 --- a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs +++ b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs @@ -14,9 +14,9 @@ namespace ICSharpCode.Decompiler.Ast if (resolveTypeArguments) return BaseTypes(derivedType).Any(t => t.Item == baseType); else { - var comparableBaseType = baseType.Resolve(); + var comparableBaseType = baseType.ResolveOrThrow(); while (derivedType.BaseType != null) { - var resolvedBaseType = derivedType.BaseType.Resolve(); + var resolvedBaseType = derivedType.BaseType.ResolveOrThrow(); if (resolvedBaseType == null) return false; if (comparableBaseType == resolvedBaseType) @@ -29,11 +29,16 @@ namespace ICSharpCode.Decompiler.Ast public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod) { + if (parentMethod == null) + throw new ArgumentNullException("parentMethod"); + if (childMethod == null) + throw new ArgumentNullException("childMethod"); + if (parentMethod.Name != childMethod.Name) return false; if (parentMethod.HasParameters || childMethod.HasParameters) - if(!parentMethod.HasParameters || ! childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count) + if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count) return false; return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.); @@ -41,6 +46,11 @@ namespace ICSharpCode.Decompiler.Ast public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty) { + if (parentProperty == null) + throw new ArgumentNullException("parentProperty"); + if (childProperty == null) + throw new ArgumentNullException("childProperty"); + if (parentProperty.Name != childProperty.Name) return false; @@ -53,6 +63,9 @@ namespace ICSharpCode.Decompiler.Ast public static IEnumerable FindBaseMethods(MethodDefinition method) { + if (method == null) + throw new ArgumentNullException("method"); + var typeContext = CreateGenericContext(method.DeclaringType); var gMethod = typeContext.ApplyTo(method); @@ -65,8 +78,11 @@ namespace ICSharpCode.Decompiler.Ast } } - public static IEnumerable FindBaseProperties(PropertyDefinition property) + public static IEnumerable FindBaseProperties(PropertyDefinition property, bool ignoreResolveExceptions = false) { + if (property == null) + throw new ArgumentNullException("property"); + var typeContext = CreateGenericContext(property.DeclaringType); var gProperty = typeContext.ApplyTo(property); @@ -109,7 +125,7 @@ namespace ICSharpCode.Decompiler.Ast if (mCandidate.HasOverrides) return false; - if (!IsSameType(candidate.Resolve(mCandidate.ReturnType), method.Resolve(mMethod.ReturnType))) + if (!IsSameType(candidate.ResolveWithContext(mCandidate.ReturnType), method.ResolveWithContext(mMethod.ReturnType))) return false; if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) { @@ -140,7 +156,7 @@ namespace ICSharpCode.Decompiler.Ast if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides) return false; - if (!IsSameType(candidate.Resolve(mCandidate.PropertyType), property.Resolve(mProperty.PropertyType))) + if (!IsSameType(candidate.ResolveWithContext(mCandidate.PropertyType), property.ResolveWithContext(mProperty.PropertyType))) return false; if (mCandidate.HasParameters || mProperty.HasParameters) { @@ -158,8 +174,8 @@ namespace ICSharpCode.Decompiler.Ast private static bool MatchParameters(GenericContext baseParameterType, GenericContext parameterType) { - var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType); - var param = parameterType.Resolve(parameterType.Item.ParameterType); + var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType); + var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType); return IsSameType(baseParam, param); } @@ -186,10 +202,10 @@ namespace ICSharpCode.Decompiler.Ast var baseType = type.Item.BaseType; var genericBaseType = baseType as GenericInstanceType; if (genericBaseType != null) { - type = new GenericContext(genericBaseType.Resolve(), - genericBaseType.GenericArguments.Select(t => type.Resolve(t))); + type = new GenericContext(genericBaseType.ResolveOrThrow(), + genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t))); } else - type = new GenericContext(baseType.Resolve()); + type = new GenericContext(baseType.ResolveOrThrow()); yield return type; } } @@ -201,7 +217,7 @@ namespace ICSharpCode.Decompiler.Ast : new GenericContext(type); } - struct GenericContext + struct GenericContext where T : class { private static readonly ReadOnlyCollection Empty = new ReadOnlyCollection(new List()); @@ -210,12 +226,18 @@ namespace ICSharpCode.Decompiler.Ast public GenericContext(T item) { + if (item == null) + throw new ArgumentNullException("item"); + Item = item; TypeArguments = Empty; } public GenericContext(T item, IEnumerable typeArguments) { + if (item == null) + throw new ArgumentNullException("item"); + Item = item; var list = new List(); foreach (var arg in typeArguments) { @@ -231,7 +253,7 @@ namespace ICSharpCode.Decompiler.Ast TypeArguments = typeArguments; } - public TypeReference Resolve(TypeReference type) + public TypeReference ResolveWithContext(TypeReference type) { var genericParameter = type as GenericParameter; if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) { @@ -239,7 +261,7 @@ namespace ICSharpCode.Decompiler.Ast } var arrayType = type as ArrayType; if (arrayType != null) { - var resolvedElementType = Resolve(arrayType.ElementType); + var resolvedElementType = ResolveWithContext(arrayType.ElementType); if (resolvedElementType == null) return null; if (resolvedElementType == arrayType.ElementType) @@ -249,10 +271,10 @@ namespace ICSharpCode.Decompiler.Ast newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension]; return newArrayType; } - return type.Resolve(); + return type.ResolveOrThrow(); } - public GenericContext ApplyTo(T2 item) + public GenericContext ApplyTo(T2 item) where T2 : class { return new GenericContext(item, this.TypeArguments); } diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs index 5e806e7af..46d471957 100644 --- a/ICSharpCode.Decompiler/CecilExtensions.cs +++ b/ICSharpCode.Decompiler/CecilExtensions.cs @@ -185,7 +185,15 @@ namespace ICSharpCode.Decompiler else return null; } - + + public static TypeDefinition ResolveOrThrow(this TypeReference typeReference) + { + var resolved = typeReference.Resolve(); + if (resolved == null) + throw new ReferenceResolvingException(); + return resolved; + } + public static bool IsCompilerGenerated(this ICustomAttributeProvider provider) { if (provider != null && provider.HasCustomAttributes) { diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 6e8d0eae8..072171276 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -110,6 +110,7 @@ + diff --git a/ICSharpCode.Decompiler/ReferenceResolvingException.cs b/ICSharpCode.Decompiler/ReferenceResolvingException.cs new file mode 100644 index 000000000..acd53b499 --- /dev/null +++ b/ICSharpCode.Decompiler/ReferenceResolvingException.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Decompiler +{ + /// + /// Represents an error while resolving a reference to a type or a member. + /// + [Serializable] + public class ReferenceResolvingException : Exception + { + /// + /// Initializes a new instance of the class + /// + public ReferenceResolvingException() + { + } + + /// + /// Initializes a new instance of the class + /// + /// A that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. + public ReferenceResolvingException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class + /// + /// A that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. + /// The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception. + public ReferenceResolvingException(string message, Exception inner) + : base(message, inner) + { + } + + /// + /// Initializes a new instance of the class + /// + /// The object that holds the serialized object data. + /// The contextual information about the source or destination. + protected ReferenceResolvingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index a4d028dc1..43601694a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; +using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; using ICSharpCode.NRefactory.Utils; using ICSharpCode.TreeView; @@ -69,18 +70,26 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); - if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) - continue; + SharpTreeNode newNode = null; + try { + if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) + continue; - foreach (PropertyDefinition property in type.Properties) { - ct.ThrowIfCancellationRequested(); + foreach (PropertyDefinition property in type.Properties) { + ct.ThrowIfCancellationRequested(); - if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { - MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; - bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; - yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); + if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { + MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; + bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; + newNode = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); + } } } + catch (ReferenceResolvingException) { + // ignore this type definition. + } + if (newNode != null) + yield return newNode; } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs index 4244c595d..4200c78db 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; +using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; using ICSharpCode.NRefactory.Utils; using ICSharpCode.TreeView; @@ -73,20 +74,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); + SharpTreeNode newNode = null; + try { + if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) + continue; - if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) - continue; + foreach (MethodDefinition method in type.Methods) { + ct.ThrowIfCancellationRequested(); - foreach (MethodDefinition method in type.Methods) - { - ct.ThrowIfCancellationRequested(); - - if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) - { - bool hidesParent = !method.IsVirtual ^ method.IsNewSlot; - yield return new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : ""); + if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) { + bool hidesParent = !method.IsVirtual ^ method.IsNewSlot; + newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : ""); + } } } + catch (ReferenceResolvingException) { + // ignore this type definition. maybe add a notification about such cases. + } + if (newNode != null) + yield return newNode; } } From 46838a6a72586d5529147b06229d64e16dd39212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Mon, 18 Apr 2011 00:54:57 +0200 Subject: [PATCH 3/3] Fixed some bugs in "Used by" analyzers. --- ILSpy/ILSpy.csproj | 5 ++- .../Analyzer/AnalyzedFieldAccessNode.cs | 3 +- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 3 +- ILSpy/TreeNodes/Analyzer/Helpers.cs | 36 +++++++++++++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 ILSpy/TreeNodes/Analyzer/Helpers.cs diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index d2b59b2ef..2b4c2f3ba 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -130,6 +130,7 @@ + @@ -268,8 +269,6 @@ ICSharpCode.TreeView - - - + \ No newline at end of file diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs index 59d8b47c2..c9a0a6fb2 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs @@ -67,7 +67,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) { string name = analyzedField.Name; - string declTypeName = analyzedField.DeclaringType.FullName; foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); foreach (MethodDefinition method in type.Methods) { @@ -78,7 +77,7 @@ 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 && fr.DeclaringType.FullName == declTypeName && fr.Resolve() == analyzedField) { + if (fr != null && fr.Name == name && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) { found = true; break; } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index e80c77b68..fca078f9d 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -80,7 +80,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) { string name = analyzedMethod.Name; - string declTypeName = analyzedMethod.DeclaringType.FullName; foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { ct.ThrowIfCancellationRequested(); foreach (MethodDefinition method in type.Methods) { @@ -90,7 +89,7 @@ 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 && mr.DeclaringType.FullName == declTypeName && mr.Resolve() == analyzedMethod) { + if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) { found = true; break; } diff --git a/ILSpy/TreeNodes/Analyzer/Helpers.cs b/ILSpy/TreeNodes/Analyzer/Helpers.cs new file mode 100644 index 000000000..25a74348f --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/Helpers.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + static class Helpers + { + public static bool IsReferencedBy(TypeDefinition type, TypeReference typeRef) + { + // TODO: move it to a better place after adding support for more cases. + if (type == null) + throw new ArgumentNullException("type"); + if (typeRef == null) + throw new ArgumentNullException("typeRef"); + + if (type == typeRef) + return true; + if (type.Name != typeRef.Name) + return false; + if (type.Namespace != typeRef.Namespace) + return false; + + if (type.DeclaringType != null || typeRef.DeclaringType != null) { + if (type.DeclaringType == null || typeRef.DeclaringType == null) + return false; + if (!IsReferencedBy(type.DeclaringType, typeRef.DeclaringType)) + return false; + } + + return true; + } + } +}