Browse Source

Remove old analyzer code.

pull/1213/head
Siegfried Pammer 7 years ago
parent
commit
9f7475022a
  1. 4
      ILSpy/ILSpy.csproj
  2. 372
      ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs
  3. 132
      ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs
  4. 74
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  5. 88
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs
  6. 83
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs
  7. 86
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs
  8. 86
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  9. 118
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  10. 119
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  11. 74
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  12. 173
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  13. 84
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs
  14. 152
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  15. 239
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs
  16. 139
      ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

4
ILSpy/ILSpy.csproj

@ -391,10 +391,6 @@ @@ -391,10 +391,6 @@
<None Include="@(Resource)" />
</ItemGroup>
<ItemGroup>
<Folder Include="TreeNodes\Analyzer\" />
</ItemGroup>
<!--
Work around to fix Intellisense file generation for XAML projects
https://github.com/dotnet/project-system/issues/2488

372
ILSpy/TreeNodes/Analyzer/AnalyzedAttributeAppliedToTreeNode.cs

@ -1,372 +0,0 @@ @@ -1,372 +0,0 @@
// 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 System.Collections.Concurrent;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedAttributeAppliedToTreeNode : AnalyzerSearchTreeNode
{
private readonly TypeDefinition analyzedType;
private readonly string attributeName;
private AttributeTargets usage = AttributeTargets.All;
private bool allowMutiple;
private bool inherited = true;
private ConcurrentDictionary<MethodDefinition, int> foundMethods;
public static bool CanShow(TypeDefinition type)
{
return type.IsClass && type.IsCustomAttribute();
}
public AnalyzedAttributeAppliedToTreeNode(TypeDefinition analyzedType)
{
if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
attributeName = this.analyzedType.FullName;
GetAttributeUsage();
}
private void GetAttributeUsage()
{
if (analyzedType.HasCustomAttributes) {
foreach (CustomAttribute ca in analyzedType.CustomAttributes) {
TypeReference t = ca.AttributeType;
if (t.Name == "AttributeUsageAttribute" && t.Namespace == "System") {
this.usage = (AttributeTargets)ca.ConstructorArguments[0].Value;
if (ca.ConstructorArguments.Count > 1) {
this.allowMutiple = (bool)ca.ConstructorArguments[1].Value;
this.inherited = (bool)ca.ConstructorArguments[2].Value;
}
if (ca.HasProperties) {
foreach (var namedArgument in ca.Properties) {
switch (namedArgument.Name) {
case "AllowMultiple":
this.allowMutiple = (bool)namedArgument.Argument.Value;
break;
case "Inherited":
this.inherited = (bool)namedArgument.Argument.Value;
break;
}
}
}
}
}
}
}
public override object Text
{
get { return "Applied To"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
//get the assemblies to search
var currentAssembly = analyzedType.Module.Assembly;
var assemblies = analyzedType.IsPublic ? GetReferencingAssemblies(currentAssembly, ct) : GetAssemblyAndAnyFriends(currentAssembly, ct);
var results = assemblies.AsParallel().WithCancellation(ct).SelectMany(a => FindReferencesInAssembly(a.Item1.MainModule, a.Item2, ct));
foreach (var result in results.OrderBy(n => n.Text)) {
yield return result;
}
foundMethods = null;
}
#region standard custom attributes
private IEnumerable<AnalyzerTreeNode> FindReferencesInAssembly(PEFile module, TypeReference tr, CancellationToken ct)
{
//since we do not display modules as separate entities, coalesce the assembly and module searches
bool foundInAssyOrModule = false;
if ((usage & AttributeTargets.Assembly) != 0) {
AssemblyDefinition asm = module.Assembly;
if (asm != null && asm.HasCustomAttributes) {
foreach (var attribute in asm.CustomAttributes) {
if (attribute.AttributeType == tr) {
foundInAssyOrModule = true;
break;
}
}
}
}
if (!foundInAssyOrModule) {
ct.ThrowIfCancellationRequested();
//search module
if ((usage & AttributeTargets.Module) != 0) {
if (module.HasCustomAttributes) {
foreach (var attribute in module.CustomAttributes) {
if (attribute.AttributeType == tr) {
foundInAssyOrModule = true;
break;
}
}
}
}
}
if (foundInAssyOrModule) {
yield return new AnalyzedAssemblyTreeNode(module);
}
ct.ThrowIfCancellationRequested();
foreach (TypeDefinition type in TreeTraversal.PreOrder(module.Types, t => t.NestedTypes).OrderBy(t => t.FullName)) {
ct.ThrowIfCancellationRequested();
foreach (var result in FindReferencesWithinInType(type, tr)) {
ct.ThrowIfCancellationRequested();
yield return result;
}
}
}
private IEnumerable<AnalyzerTreeNode> FindReferencesWithinInType(TypeDefinition type, TypeReference attrTypeRef)
{
bool searchRequired = (type.IsClass && usage.HasFlag(AttributeTargets.Class))
|| (type.IsEnum && usage.HasFlag(AttributeTargets.Enum))
|| (type.IsInterface && usage.HasFlag(AttributeTargets.Interface))
|| (type.IsValueType && usage.HasFlag(AttributeTargets.Struct));
if (searchRequired) {
if (type.HasCustomAttributes) {
foreach (var attribute in type.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
var node = new AnalyzedTypeTreeNode(type);
node.Language = this.Language;
yield return node;
break;
}
}
}
}
if ((this.usage & AttributeTargets.GenericParameter) != 0 && type.HasGenericParameters) {
foreach (var parameter in type.GenericParameters) {
if (parameter.HasCustomAttributes) {
foreach (var attribute in parameter.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
var node = new AnalyzedTypeTreeNode(type);
node.Language = this.Language;
yield return node;
break;
}
}
}
}
}
if ((this.usage & AttributeTargets.Field) != 0 && type.HasFields) {
foreach (var field in type.Fields) {
if (field.HasCustomAttributes) {
foreach (var attribute in field.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
var node = new AnalyzedFieldTreeNode(field);
node.Language = this.Language;
yield return node;
break;
}
}
}
}
}
if (((usage & AttributeTargets.Property) != 0) && type.HasProperties) {
foreach (var property in type.Properties) {
if (property.HasCustomAttributes) {
foreach (var attribute in property.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
break;
}
}
}
}
}
if (((usage & AttributeTargets.Event) != 0) && type.HasEvents) {
foreach (var _event in type.Events) {
if (_event.HasCustomAttributes) {
foreach (var attribute in _event.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
var node = new AnalyzedEventTreeNode(_event);
node.Language = this.Language;
yield return node;
break;
}
}
}
}
}
if (type.HasMethods) {
foreach (var method in type.Methods) {
bool found = false;
if ((usage & (AttributeTargets.Method | AttributeTargets.Constructor)) != 0) {
if (method.HasCustomAttributes) {
foreach (var attribute in method.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
found = true;
break;
}
}
}
}
if (!found &&
((usage & AttributeTargets.ReturnValue) != 0) &&
method.MethodReturnType.HasCustomAttributes) {
foreach (var attribute in method.MethodReturnType.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
found = true;
break;
}
}
}
if (!found &&
((usage & AttributeTargets.Parameter) != 0) &&
method.HasParameters) {
foreach (var parameter in method.Parameters) {
foreach (var attribute in parameter.CustomAttributes) {
if (attribute.AttributeType == attrTypeRef) {
found = true;
break;
}
}
}
}
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}
}
}
private bool HasAlreadyBeenFound(MethodDefinition method)
{
return !foundMethods.TryAdd(method, 0);
}
#endregion
#region search scope
private IEnumerable<Tuple<AssemblyDefinition, TypeReference>> GetReferencingAssemblies(AssemblyDefinition asm, CancellationToken ct)
{
yield return new Tuple<AssemblyDefinition, TypeReference>(asm, this.analyzedType);
string requiredAssemblyFullName = asm.FullName;
IEnumerable<LoadedAssembly> assemblies = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().Where(assy => assy.GetAssemblyDefinitionOrNull() != null);
foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested();
bool found = false;
var module = assembly.GetModuleDefinitionOrNull();
if (module == null)
continue;
foreach (var reference in module.AssemblyReferences) {
if (requiredAssemblyFullName == reference.FullName) {
found = true;
break;
}
}
if (found) {
var typeref = GetScopeTypeReferenceInAssembly(module.Assembly);
if (typeref != null)
yield return new Tuple<AssemblyDefinition, TypeReference>(module.Assembly, typeref);
}
}
}
private IEnumerable<Tuple<AssemblyDefinition, TypeReference>> GetAssemblyAndAnyFriends(AssemblyDefinition asm, CancellationToken ct)
{
yield return new Tuple<AssemblyDefinition, TypeReference>(asm, analyzedType);
if (asm.HasCustomAttributes) {
var attributes = asm.CustomAttributes
.Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var friendAssemblies = new HashSet<string>();
foreach (var attribute in attributes) {
string assemblyName = attribute.ConstructorArguments[0].Value as string;
assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
friendAssemblies.Add(assemblyName);
}
if (friendAssemblies.Count > 0) {
IEnumerable<LoadedAssembly> assemblies = MainWindow.Instance.CurrentAssemblyList.GetAssemblies();
foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested();
var module = assembly.GetModuleDefinitionOrNull();
if (module == null)
continue;
if (friendAssemblies.Contains(assembly.ShortName)) {
var typeref = GetScopeTypeReferenceInAssembly(module.Assembly);
if (typeref != null) {
yield return new Tuple<AssemblyDefinition, TypeReference>(module.Assembly, typeref);
}
}
}
}
}
}
private TypeReference GetScopeTypeReferenceInAssembly(AssemblyDefinition asm)
{
foreach (var typeref in asm.MainModule.GetTypeReferences()) {
if (typeref.Name == analyzedType.Name && typeref.Namespace == analyzedType.Namespace) {
return typeref;
}
}
return null;
}
#endregion
}
internal static class ExtensionMethods
{
public static bool HasCustomAttribute(this MemberReference member, string attributeTypeName)
{
return false;
}
}
}

132
ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs

@ -1,132 +0,0 @@ @@ -1,132 +0,0 @@
// 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedEventFiredByTreeNode : AnalyzerSearchTreeNode
{
private readonly EventDefinition analyzedEvent;
private readonly FieldDefinition eventBackingField;
private readonly MethodDefinition eventFiringMethod;
private ConcurrentDictionary<MethodDefinition, int> foundMethods;
public AnalyzedEventFiredByTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
this.eventBackingField = GetBackingField(analyzedEvent);
this.eventFiringMethod = analyzedEvent.EventType.Resolve().Methods.First(md => md.Name == "Invoke");
}
public override object Text
{
get { return "Raised By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType).OrderBy(n => n.Text)) {
yield return child;
}
foundMethods = null;
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
// HACK: in lieu of proper flow analysis, I'm going to use a simple heuristic
// If the method accesses the event's backing field, and calls invoke on a delegate
// with the same signature, then it is (most likely) raise the given event.
foreach (MethodDefinition method in type.Methods) {
bool readBackingField = false;
bool found = false;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
Code code = instr.OpCode.Code;
if (code == Code.Ldfld || code == Code.Ldflda) {
FieldReference fr = instr.Operand as FieldReference;
if (fr != null && fr.Name == eventBackingField.Name && fr == eventBackingField) {
readBackingField = true;
}
}
if (readBackingField && (code == Code.Callvirt || code == Code.Call)) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == eventFiringMethod.Name && mr.Resolve() == eventFiringMethod) {
found = true;
break;
}
}
}
method.Body = null;
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}
}
private bool HasAlreadyBeenFound(MethodDefinition method)
{
return !foundMethods.TryAdd(method, 0);
}
// HACK: we should probably examine add/remove methods to determine this
private static FieldDefinition GetBackingField(EventDefinition ev)
{
var fieldName = ev.Name;
var vbStyleFieldName = fieldName + "Event";
var fieldType = ev.EventType;
foreach (var fd in ev.DeclaringType.Fields) {
if (fd.Name == fieldName || fd.Name == vbStyleFieldName)
if (fd.FieldType.FullName == fieldType.FullName)
return fd;
}
return null;
}
public static bool CanShow(EventDefinition ev)
{
return GetBackingField(ev) != null;
}
}
}

74
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -1,74 +0,0 @@ @@ -1,74 +0,0 @@
// 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.Reflection;
using System.Threading;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedEventOverridesTreeNode : AnalyzerSearchTreeNode
{
private readonly EventDefinition analyzedEvent;
public AnalyzedEventOverridesTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent.IsNil)
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
}
public override object Text
{
get { return "Overridden By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedEvent, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!analyzedEvent.DeclaringType.IsBaseTypeOf(type))
yield break;
foreach (EventDefinition eventDef in type.Events) {
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
var node = new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : "");
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(EventDefinition property)
{
var accessor = property.GetAccessors().First().Method;
return accessor.HasFlag(MethodAttributes.Virtual) && !accessor.HasFlag(MethodAttributes.Final) && !accessor.DeclaringType.IsInterface;
}
}
}

88
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs

@ -1,88 +0,0 @@ @@ -1,88 +0,0 @@
// 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.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfaceEventImplementedByTreeNode : AnalyzerSearchTreeNode
{
private readonly EventDefinition analyzedEvent;
private readonly MethodDefinition analyzedMethod;
public AnalyzedInterfaceEventImplementedByTreeNode(EventDefinition analyzedEvent)
{
if (analyzedEvent == null)
throw new ArgumentNullException(nameof(analyzedEvent));
this.analyzedEvent = analyzedEvent;
this.analyzedMethod = this.analyzedEvent.AddMethod ?? this.analyzedEvent.RemoveMethod;
}
public override object Text
{
get { return "Implemented By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.InterfaceType.Resolve() == analyzedMethod.DeclaringType)?.InterfaceType;
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)) {
var node = new AnalyzedEventTreeNode(ev);
node.Language = this.Language;
yield return node;
}
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)) {
var node = new AnalyzedEventTreeNode(ev);
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(EventDefinition ev)
{
return ev.DeclaringType.IsInterface;
}
}
}

83
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs

@ -1,83 +0,0 @@ @@ -1,83 +0,0 @@
// 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.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfaceMethodImplementedByTreeNode : AnalyzerSearchTreeNode
{
private readonly MethodDefinitionHandle analyzedMethod;
public AnalyzedInterfaceMethodImplementedByTreeNode(MethodDefinitionHandle analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}
public override object Text
{
get { return "Implemented By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.InterfaceType.Resolve() == analyzedMethod.DeclaringType)?.InterfaceType;
if (implementedInterfaceRef == null)
yield break;
foreach (MethodDefinition method in type.Methods.Where(m => m.Name == analyzedMethod.Name)) {
if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef)) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
yield break;
}
foreach (MethodDefinition method in type.Methods) {
if (method.HasOverrides && method.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(MethodDefinition method)
{
return method.DeclaringType.IsInterface;
}
}
}

86
ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs

@ -1,86 +0,0 @@ @@ -1,86 +0,0 @@
// 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.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedInterfacePropertyImplementedByTreeNode : AnalyzerSearchTreeNode
{
private readonly PropertyDefinition analyzedProperty;
private readonly MethodDefinition analyzedMethod;
public AnalyzedInterfacePropertyImplementedByTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException(nameof(analyzedProperty));
this.analyzedProperty = analyzedProperty;
this.analyzedMethod = this.analyzedProperty.GetMethod ?? this.analyzedProperty.SetMethod;
}
public override object Text
{
get { return "Implemented By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!type.HasInterfaces)
yield break;
TypeReference implementedInterfaceRef = type.Interfaces.FirstOrDefault(i => i.InterfaceType.Resolve() == analyzedMethod.DeclaringType)?.InterfaceType;
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)) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
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)) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(PropertyDefinition property)
{
return property.DeclaringType.IsInterface;
}
}
}

86
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -1,86 +0,0 @@ @@ -1,86 +0,0 @@
// 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.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
/// <summary>
/// Searches for overrides of the analyzed method.
/// </summary>
internal sealed class AnalyzedMethodOverridesTreeNode : AnalyzerSearchTreeNode
{
private readonly MethodDefinition analyzedMethod;
public AnalyzedMethodOverridesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}
public override object Text
{
get { return "Overridden By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
AnalyzerTreeNode newNode = null;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
yield break;
foreach (MethodDefinition method in type.Methods) {
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) {
newNode.Language = this.Language;
yield return newNode;
}
}
public static bool CanShow(MethodDefinition method)
{
return method.IsVirtual &&
!method.IsFinal &&
!method.DeclaringType.IsSealed &&
!method.DeclaringType.IsInterface; // interface methods are definitions not implementations - cannot be overridden
}
}
}

118
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -1,118 +0,0 @@ @@ -1,118 +0,0 @@
// 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
/// <summary>
/// Finds members where this method is referenced.
/// </summary>
internal sealed class AnalyzedMethodUsedByTreeNode : AnalyzerSearchTreeNode
{
readonly Decompiler.Metadata.PEFile module;
readonly MethodDefinitionHandle analyzedMethod;
public AnalyzedMethodUsedByTreeNode(Decompiler.Metadata.PEFile module, MethodDefinitionHandle analyzedMethod)
{
this.module = module ?? throw new ArgumentNullException(nameof(module));
if (analyzedMethod.IsNil)
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}
public override object Text => "Used By";
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(this.Language, module, analyzedMethod, provideTypeSystem: false, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
IEnumerable<AnalyzerTreeNode> FindReferencesInType(Decompiler.Metadata.PEFile module, TypeDefinitionHandle type, CodeMappingInfo codeMapping, IDecompilerTypeSystem typeSystem)
{
var methodDef = this.module.Metadata.GetMethodDefinition(analyzedMethod);
var name = this.module.Metadata.GetString(methodDef.Name);
var td = module.Metadata.GetTypeDefinition(type);
HashSet<MethodDefinitionHandle> alreadyFoundMethods = new HashSet<MethodDefinitionHandle>();
foreach (var method in td.GetMethods()) {
var currentMethod = module.Metadata.GetMethodDefinition(method);
if (!currentMethod.HasBody())
continue;
if (ScanMethodBody(module, currentMethod.RelativeVirtualAddress)) {
var parentMethod = codeMapping.GetParentMethod(method);
if (!parentMethod.IsNil && alreadyFoundMethods.Add(parentMethod)) {
var node = new AnalyzedMethodTreeNode(module, parentMethod);
node.Language = this.Language;
yield return node;
}
}
}
}
bool ScanMethodBody(PEFile module, int rva)
{
var blob = module.Reader.GetMethodBody(rva).GetILReader();
while (blob.RemainingBytes > 0) {
var opCode = blob.DecodeOpCode();
switch (opCode.GetOperandType()) {
case OperandType.Field:
case OperandType.Method:
case OperandType.Sig:
case OperandType.Tok:
case OperandType.Type:
var member = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (member.Kind) {
case HandleKind.MethodDefinition:
if (this.module != module || analyzedMethod != (MethodDefinitionHandle)member)
break;
return true;
case HandleKind.MemberReference:
var mr = module.Metadata.GetMemberReference((MemberReferenceHandle)member);
if (mr.GetKind() != MemberReferenceKind.Method)
break;
return Helpers.IsSameMethod(analyzedMethod, this.module, member, module);
case HandleKind.MethodSpecification:
return Helpers.IsSameMethod(analyzedMethod, this.module, member, module);
}
break;
default:
blob.SkipOperand(opCode);
break;
}
}
return false;
}
}
}

119
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -1,119 +0,0 @@ @@ -1,119 +0,0 @@
// 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.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
/// <summary>
/// Shows the methods that are used by this method.
/// </summary>
internal sealed class AnalyzedMethodUsesTreeNode : AnalyzerSearchTreeNode
{
readonly Decompiler.Metadata.PEFile module;
readonly MethodDefinitionHandle analyzedMethod;
public AnalyzedMethodUsesTreeNode(Decompiler.Metadata.PEFile module, MethodDefinitionHandle analyzedMethod)
{
if (analyzedMethod.IsNil)
throw new ArgumentNullException(nameof(analyzedMethod));
this.module = module;
this.analyzedMethod = analyzedMethod;
}
public override object Text => "Uses";
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var mapping = Language.GetCodeMappingInfo(module, analyzedMethod);
foreach (var part in mapping.GetMethodParts(analyzedMethod)) {
foreach (var node in ScanMethod(part)) {
node.Language = this.Language;
yield return node;
}
}
IEnumerable<AnalyzerTreeNode> ScanMethod(MethodDefinitionHandle handle)
{
var md = module.Metadata.GetMethodDefinition(handle);
if (!md.HasBody()) yield break;
var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader();
var resolveContext = new SimpleMetadataResolveContext(module);
while (blob.RemainingBytes > 0) {
var opCode = ILParser.DecodeOpCode(ref blob);
Decompiler.Metadata.MethodDefinition method;
switch (opCode.GetOperandType()) {
case OperandType.Field:
case OperandType.Method:
case OperandType.Sig:
case OperandType.Tok:
var member = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (member.Kind) {
case HandleKind.FieldDefinition:
if (!Language.ShowMember(new Decompiler.Metadata.TypeDefinition(module, member.GetDeclaringType(module.Metadata))) || !Language.ShowMember(new Decompiler.Metadata.FieldDefinition(module, (FieldDefinitionHandle)member))) break;
yield return new AnalyzedFieldTreeNode(module, (FieldDefinitionHandle)member);
break;
case HandleKind.MethodDefinition:
if (!Language.ShowMember(new Decompiler.Metadata.TypeDefinition(module, member.GetDeclaringType(module.Metadata))) || !Language.ShowMember(new Decompiler.Metadata.MethodDefinition(module, (MethodDefinitionHandle)member))) break;
yield return new AnalyzedMethodTreeNode(module, (MethodDefinitionHandle)member);
break;
case HandleKind.MemberReference:
var mr = module.Metadata.GetMemberReference((MemberReferenceHandle)member);
switch (mr.GetKind()) {
case MemberReferenceKind.Method:
method = MetadataResolver.ResolveAsMethod(member, resolveContext);
if (method.IsNil || !Language.ShowMember(new Decompiler.Metadata.TypeDefinition(method.Module, method.Handle.GetDeclaringType(method.Module.Metadata))) || !Language.ShowMember(method)) break;
yield return new AnalyzedMethodTreeNode(method.Module, method.Handle);
break;
case MemberReferenceKind.Field:
var field = MetadataResolver.ResolveAsField(member, resolveContext);
if (field.IsNil || !Language.ShowMember(new Decompiler.Metadata.TypeDefinition(field.Module, field.Handle.GetDeclaringType(field.Module.Metadata))) || !Language.ShowMember(field)) break;
yield return new AnalyzedFieldTreeNode(field.Module, field.Handle);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case HandleKind.MethodSpecification:
method = MetadataResolver.ResolveAsMethod(member, resolveContext);
if (method.IsNil || !Language.ShowMember(new Decompiler.Metadata.TypeDefinition(method.Module, method.Handle.GetDeclaringType(method.Module.Metadata))) || !Language.ShowMember(method)) break;
yield return new AnalyzedMethodTreeNode(method.Module, method.Handle);
break;
}
break;
default:
ILParser.SkipOperand(ref blob, opCode);
break;
}
}
}
}
}
}

74
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -1,74 +0,0 @@ @@ -1,74 +0,0 @@
// 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.Reflection;
using System.Threading;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedPropertyOverridesTreeNode : AnalyzerSearchTreeNode
{
private readonly PropertyDefinition analyzedProperty;
public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException(nameof(analyzedProperty));
this.analyzedProperty = analyzedProperty;
}
public override object Text
{
get { return "Overridden By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedProperty, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!analyzedProperty.DeclaringType.IsBaseTypeOf(type))
yield break;
foreach (PropertyDefinition property in type.Properties) {
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
var node = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(PropertyDefinition property)
{
var accessor = property.GetAccessors().First().Method;
return accessor.HasFlag(MethodAttributes.Virtual) && !accessor.HasFlag(MethodAttributes.Final) && !accessor.DeclaringType.IsInterface;
}
}
}

173
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -1,173 +0,0 @@ @@ -1,173 +0,0 @@
// 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.Reflection;
using System.Threading;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedTypeExposedByTreeNode : AnalyzerSearchTreeNode
{
private readonly Decompiler.Metadata.TypeDefinition analyzedType;
public AnalyzedTypeExposedByTreeNode(TypeDefinition analyzedType)
{
if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
}
public override object Text
{
get { return "Exposed By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> 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)) {
var node = new AnalyzedFieldTreeNode(field);
node.Language = this.Language;
yield return node;
}
}
foreach (PropertyDefinition property in type.Properties) {
if (TypeIsExposedBy(property)) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
}
foreach (EventDefinition eventDef in type.Events) {
if (TypeIsExposedBy(eventDef)) {
var node = new AnalyzedEventTreeNode(eventDef);
node.Language = this.Language;
yield return node;
}
}
foreach (MethodDefinition method in type.Methods) {
if (TypeIsExposedBy(method)) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}
private bool TypeIsExposedBy(FieldDefinition field)
{
if (field.IsPrivate)
return false;
if (field.FieldType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(Decompiler.Metadata.PropertyDefinition property)
{
if (IsPrivate(property))
return false;
if (property.PropertyType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(Decompiler.Metadata.EventDefinition eventDef)
{
if (IsPrivate(eventDef))
return false;
if (eventDef.EventType.Resolve() == analyzedType)
return true;
return false;
}
private bool TypeIsExposedBy(Decompiler.Metadata.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;
var typeDefinition = method.Overrides[0].DeclaringType.Resolve();
if (typeDefinition != null && !typeDefinition.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.GetMethodSemanticsAttributes() != 0)
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 static bool IsPrivate(Decompiler.Metadata.PropertyDefinition property)
{
bool isGetterPublic = (!property.GetMethod.IsNil && !property.GetMethod.IsPrivate);
bool isSetterPublic = (!property.SetMethod.IsNil && !property.SetMethod.IsPrivate);
return !(isGetterPublic || isSetterPublic);
}
private static bool IsPrivate(Decompiler.Metadata.EventDefinition eventDef)
{
bool isAdderPublic = (eventDef.AddMethod != null && !eventDef.AddMethod.IsPrivate);
bool isRemoverPublic = (eventDef.RemoveMethod != null && !eventDef.RemoveMethod.IsPrivate);
return !(isAdderPublic || isRemoverPublic);
}
public static bool CanShow(Decompiler.Metadata.TypeDefinition type)
{
return true;
}
}
}

84
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs

@ -1,84 +0,0 @@ @@ -1,84 +0,0 @@
// 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;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal class AnalyzedTypeExtensionMethodsTreeNode : AnalyzerSearchTreeNode
{
private readonly TypeDefinition analyzedType;
public AnalyzedTypeExtensionMethodsTreeNode(TypeDefinition analyzedType)
{
if (analyzedType == null)
throw new ArgumentNullException(nameof(analyzedType));
this.analyzedType = analyzedType;
}
public override object Text
{
get { return "Extension Methods"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
if (!HasExtensionAttribute(type))
yield break;
foreach (MethodDefinition method in type.Methods) {
if (method.IsStatic && HasExtensionAttribute(method)) {
if (method.HasParameters && method.Parameters[0].ParameterType.Resolve() == analyzedType) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}
}
bool HasExtensionAttribute(ICustomAttributeProvider p)
{
if (p.HasCustomAttributes) {
foreach (CustomAttribute ca in p.CustomAttributes) {
TypeReference t = ca.AttributeType;
if (t.Name == "ExtensionAttribute" && t.Namespace == "System.Runtime.CompilerServices")
return true;
}
}
return false;
}
public static bool CanShow(TypeDefinition type)
{
// show on all types except static classes
return !(type.IsAbstract && type.IsSealed);
}
}
}

152
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -1,152 +0,0 @@ @@ -1,152 +0,0 @@
// 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.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
sealed class AnalyzedTypeInstantiationsTreeNode : AnalyzerSearchTreeNode
{
readonly Decompiler.Metadata.PEFile module;
readonly TypeDefinitionHandle analyzedType;
readonly FullTypeName analyzedTypeName;
public AnalyzedTypeInstantiationsTreeNode(Decompiler.Metadata.PEFile module, TypeDefinitionHandle analyzedType)
{
if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType));
this.module = module;
this.analyzedType = analyzedType;
this.analyzedTypeName = analyzedType.GetFullTypeName(module.Metadata);
}
public override object Text => "Instantiated By";
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(this.Language, module, analyzedType, provideTypeSystem: false, FindReferencesInType);
return analyzer.PerformAnalysis(ct).OrderBy(n => n.Text);
}
IEnumerable<AnalyzerTreeNode> FindReferencesInType(Decompiler.Metadata.PEFile module, TypeDefinitionHandle type, CodeMappingInfo codeMapping, IDecompilerTypeSystem typeSystem)
{
var td = module.Metadata.GetTypeDefinition(type);
foreach (var h in td.GetMethods()) {
bool found = false;
var method = module.Metadata.GetMethodDefinition(h);
if (!method.HasBody())
continue;
var blob = module.Reader.GetMethodBody(method.RelativeVirtualAddress).GetILReader();
while (!found && blob.RemainingBytes > 0) {
var opCode = blob.DecodeOpCode();
switch (opCode) {
case ILOpCode.Newobj:
var member = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (member.Kind) {
case HandleKind.MethodDefinition:
// check whether we're looking at the defining assembly:
if (module != this.module)
break;
var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)member);
if (!module.Metadata.StringComparer.Equals(md.Name, ".ctor"))
break;
found = md.GetDeclaringType() == analyzedType;
break;
case HandleKind.MemberReference:
var mr = module.Metadata.GetMemberReference((MemberReferenceHandle)member);
// safety-check: should always be a method
if (mr.GetKind() != MemberReferenceKind.Method)
break;
if (!module.Metadata.StringComparer.Equals(mr.Name, ".ctor"))
break;
switch (mr.Parent.Kind) {
case HandleKind.MethodDefinition: // varargs method
var parentMD = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)mr.Parent);
found = parentMD.GetDeclaringType() == analyzedType;
break;
case HandleKind.ModuleReference: // global function
throw new NotSupportedException();
default:
var typeName = mr.Parent.GetFullTypeName(module.Metadata);
found = typeName == analyzedTypeName;
break;
}
break;
case HandleKind.MethodSpecification: // do we need to handle these?
throw new NotSupportedException();
default:
throw new ArgumentOutOfRangeException();
}
break;
case ILOpCode.Initobj:
var referencedType = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (referencedType.Kind) {
case HandleKind.TypeDefinition:
// check whether we're looking at the defining assembly:
if (module != this.module)
break;
found = referencedType == analyzedType;
break;
case HandleKind.TypeReference:
case HandleKind.TypeSpecification:
var referencedTypeName = referencedType.GetFullTypeName(module.Metadata);
found = referencedTypeName == analyzedTypeName;
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
default:
blob.SkipOperand(opCode);
break;
}
}
if (found) {
var node = new AnalyzedMethodTreeNode(module, h);
node.Language = this.Language;
yield return node;
}
}
}
public static bool CanShow(MetadataReader metadata, TypeDefinitionHandle handle)
{
var td = metadata.GetTypeDefinition(handle);
return (td.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class
&& !((td.Attributes & TypeAttributes.Abstract) != 0 && (td.Attributes & TypeAttributes.Sealed) != 0)
&& !handle.IsEnum(metadata);
}
}
}

239
ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs

@ -1,239 +0,0 @@ @@ -1,239 +0,0 @@
// 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.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedTypeUsedByTreeNode : AnalyzerSearchTreeNode
{
readonly Decompiler.Metadata.PEFile module;
readonly TypeDefinitionHandle analyzedType;
readonly FullTypeName analyzedTypeName;
public AnalyzedTypeUsedByTreeNode(Decompiler.Metadata.PEFile module, TypeDefinitionHandle analyzedType)
{
if (analyzedType.IsNil)
throw new ArgumentNullException(nameof(analyzedType));
this.module = module;
this.analyzedType = analyzedType;
this.analyzedTypeName = analyzedType.GetFullTypeName(module.Metadata);
}
public override object Text => "Used By";
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerEntityTreeNode>(this.Language, module, analyzedType, provideTypeSystem: true, FindTypeUsage);
return analyzer.PerformAnalysis(ct).Distinct(AnalyzerEntityTreeNodeComparer.Instance).OrderBy(n => n.Text);
}
IEnumerable<AnalyzerEntityTreeNode> FindTypeUsage(Decompiler.Metadata.PEFile module, TypeDefinitionHandle type, CodeMappingInfo codeMapping, IDecompilerTypeSystem typeSystem)
{
if (type == this.analyzedType && module == this.module)
yield break;
// TODO : cache / optimize this per assembly
var analyzedTypeDefinition = typeSystem.Compilation.FindType(analyzedTypeName).GetDefinition();
var typeDefinition = typeSystem.ResolveAsType(type).GetDefinition();
if (analyzedTypeDefinition == null || typeDefinition == null)
yield break;
var visitor = new TypeDefinitionUsedVisitor(analyzedTypeDefinition);
if (typeDefinition.DirectBaseTypes.Any(bt => analyzedTypeDefinition.Equals(bt.GetDefinition())))
yield return new AnalyzedTypeTreeNode(new Decompiler.Metadata.TypeDefinition(module, type)) { Language = Language };
foreach (var field in typeDefinition.Fields.Where(f => IsUsedInField(f, visitor)))
yield return new AnalyzedFieldTreeNode(module, (FieldDefinitionHandle)field.MetadataToken) { Language = Language };
foreach (var method in typeDefinition.Methods.Where(m => IsUsedInMethodDefinition(m, visitor, typeSystem, module)))
yield return new AnalyzedMethodTreeNode(module, (MethodDefinitionHandle)method.MetadataToken) { Language = Language };
foreach (var property in typeDefinition.Properties.Where(p => IsUsedInProperty(p, visitor, typeSystem, module)))
yield return new AnalyzedPropertyTreeNode(module, (PropertyDefinitionHandle)property.MetadataToken) { Language = Language };
}
bool IsUsedInField(IField field, TypeDefinitionUsedVisitor visitor)
{
visitor.Found = false;
field.ReturnType.AcceptVisitor(visitor);
return visitor.Found;
}
bool IsUsedInProperty(IProperty property, TypeDefinitionUsedVisitor visitor, IDecompilerTypeSystem typeSystem, PEFile module)
{
visitor.Found = false;
property.ReturnType.AcceptVisitor(visitor);
for (int i = 0; i < property.Parameters.Count && !visitor.Found; i++)
property.Parameters[i].Type.AcceptVisitor(visitor);
return visitor.Found
|| (property.CanGet && IsUsedInMethodBody(module, visitor, typeSystem, (MethodDefinitionHandle)property.Getter.MetadataToken))
|| (property.CanSet && IsUsedInMethodBody(module, visitor, typeSystem, (MethodDefinitionHandle)property.Setter.MetadataToken));
}
bool IsUsedInMethodDefinition(IMethod method, TypeDefinitionUsedVisitor visitor, IDecompilerTypeSystem typeSystem, PEFile module)
{
visitor.Found = false;
method.ReturnType.AcceptVisitor(visitor);
for (int i = 0; i < method.Parameters.Count && !visitor.Found; i++)
method.Parameters[i].Type.AcceptVisitor(visitor);
return visitor.Found || IsUsedInMethodBody(module, visitor, typeSystem, (MethodDefinitionHandle)method.MetadataToken);
}
bool IsUsedInMethod(IMethod method, TypeDefinitionUsedVisitor visitor)
{
visitor.Found = false;
method.ReturnType.AcceptVisitor(visitor);
for (int i = 0; i < method.Parameters.Count && !visitor.Found; i++)
method.Parameters[i].Type.AcceptVisitor(visitor);
return visitor.Found;
}
bool IsUsedInMethodBody(PEFile module, TypeDefinitionUsedVisitor visitor, IDecompilerTypeSystem typeSystem, MethodDefinitionHandle method)
{
if (method.IsNil)
return false;
var md = module.Metadata.GetMethodDefinition(method);
if (!md.HasBody())
return false;
var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader();
while (blob.RemainingBytes > 0) {
var opCode = blob.DecodeOpCode();
switch (opCode.GetOperandType()) {
case OperandType.Field:
case OperandType.Method:
case OperandType.Sig:
case OperandType.Tok:
case OperandType.Type:
var member = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (member.Kind) {
case HandleKind.TypeReference:
case HandleKind.TypeSpecification:
var resolvedType = typeSystem.ResolveAsType(member);
resolvedType.AcceptVisitor(visitor);
if (visitor.Found)
return true;
break;
case HandleKind.TypeDefinition:
if (this.module != module)
break;
if (member == analyzedType)
return true;
break;
case HandleKind.FieldDefinition:
if (this.module != module)
break;
var resolvedField = typeSystem.ResolveAsField(member);
if (IsUsedInField(resolvedField, visitor))
return true;
break;
case HandleKind.MethodDefinition:
var resolvedMethod = typeSystem.ResolveAsMethod(member);
if (resolvedMethod == null)
break;
if (IsUsedInMethod(resolvedMethod, visitor))
return true;
break;
case HandleKind.MemberReference:
var resolvedMember = typeSystem.ResolveAsMember(member);
if (resolvedMember == null)
break;
if (resolvedMember is IField f && IsUsedInField(f, visitor))
return true;
if (resolvedMember is IMethod m && IsUsedInMethod(m, visitor))
return true;
break;
case HandleKind.MethodSpecification:
resolvedMethod = typeSystem.ResolveAsMethod(member);
if (resolvedMethod == null)
break;
if (IsUsedInMethod(resolvedMethod, visitor))
return true;
break;
default:
break;
}
break;
default:
blob.SkipOperand(opCode);
break;
}
}
return false;
}
public static bool CanShow(Decompiler.Metadata.PEFile module, TypeDefinitionHandle type)
{
return !type.IsNil;
}
}
class AnalyzerEntityTreeNodeComparer : IEqualityComparer<AnalyzerEntityTreeNode>
{
public static readonly AnalyzerEntityTreeNodeComparer Instance = new AnalyzerEntityTreeNodeComparer();
public bool Equals(AnalyzerEntityTreeNode x, AnalyzerEntityTreeNode y)
{
return x.Member == y.Member;
}
public int GetHashCode(AnalyzerEntityTreeNode obj)
{
return obj.Member.GetHashCode();
}
}
class TypeDefinitionUsedVisitor : TypeVisitor
{
readonly ITypeDefinition typeDefinition;
public bool Found { get; set; }
public TypeDefinitionUsedVisitor(ITypeDefinition definition)
{
this.typeDefinition = definition;
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
Found |= typeDefinition.Equals(type);
return base.VisitTypeDefinition(type);
}
}
}

139
ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

@ -1,139 +0,0 @@ @@ -1,139 +0,0 @@
// 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerSearchTreeNode
{
private readonly MethodDefinition analyzedMethod;
private ConcurrentDictionary<MethodDefinition, int> foundMethods;
private MethodDefinition baseMethod;
private List<TypeReference> possibleTypes;
public AnalyzedVirtualMethodUsedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException(nameof(analyzedMethod));
this.analyzedMethod = analyzedMethod;
}
public override object Text
{
get { return "Used By"; }
}
protected override IEnumerable<AnalyzerTreeNode> FetchChildren(CancellationToken ct)
{
InitializeAnalyzer();
var analyzer = new ScopedWhereUsedAnalyzer<AnalyzerTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
ReleaseAnalyzer();
}
private void InitializeAnalyzer()
{
foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
var baseMethods = TypesHierarchyHelpers.FindBaseMethods(analyzedMethod).ToArray();
if (baseMethods.Length > 0) {
baseMethod = baseMethods[baseMethods.Length - 1];
} else
baseMethod = analyzedMethod;
possibleTypes = new List<TypeReference>();
TypeReference type = analyzedMethod.DeclaringType.BaseType;
while (type != null) {
possibleTypes.Add(type);
type = type.Resolve().BaseType;
}
}
private void ReleaseAnalyzer()
{
foundMethods = null;
baseMethod = null;
}
private IEnumerable<AnalyzerTreeNode> FindReferencesInType(TypeDefinition type)
{
string name = analyzedMethod.Name;
foreach (MethodDefinition method in type.Methods) {
bool found = false;
string prefix = string.Empty;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name) {
// explicit call to the requested method
if (instr.OpCode.Code == Code.Call
&& Helpers.IsSameType(analyzedMethod.DeclaringType, mr.DeclaringType)
&& mr.Resolve() == analyzedMethod) {
found = true;
prefix = "(as base) ";
break;
}
// virtual call to base method
if (instr.OpCode.Code == Code.Callvirt) {
MethodDefinition md = mr.Resolve();
if (md == null) {
// cannot resolve the operand, so ignore this method
break;
}
if (md == baseMethod) {
found = true;
break;
}
}
}
}
method.Body = null;
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}
}
private bool HasAlreadyBeenFound(MethodDefinition method)
{
return !foundMethods.TryAdd(method, 0);
}
}
}
Loading…
Cancel
Save