Browse Source

Fixed "Overrided By" method analyzer. Added similar analyzer for properties.

pull/112/head
Artur Zgodziski 15 years ago
parent
commit
e8d81ed17c
  1. 195
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 247
      ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 6
      ILSpy/ContextMenuEntry.cs
  5. 2
      ILSpy/ILSpy.csproj
  6. 7
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  7. 7
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs
  8. 92
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  9. 80
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  10. 121
      ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs
  11. 20
      ILSpy/TreeNodes/PropertyTreeNode.cs

195
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -630,7 +630,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -630,7 +630,7 @@ namespace ICSharpCode.Decompiler.Ast
if (!methodDef.HasOverrides) {
astMethod.Modifiers = ConvertModifiers(methodDef);
if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) {
if (TypeMap.FindBaseMethods(methodDef).Any())
if (TypesHierarchyHelpers.FindBaseMethods(methodDef).Any())
astMethod.Modifiers |= Modifiers.New;
}
} else
@ -745,7 +745,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -745,7 +745,7 @@ namespace ICSharpCode.Decompiler.Ast
setterModifiers = ConvertModifiers(propDef.SetMethod);
astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null))
foreach (var basePropDef in TypeMap.FindBaseProperties(propDef))
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));
@ -753,7 +753,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -753,7 +753,7 @@ namespace ICSharpCode.Decompiler.Ast
} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot)
break;
if (accessor.IsVirtual ^ !accessor.IsNewSlot) {
if (TypeMap.FindBaseProperties(propDef).Any())
if (TypesHierarchyHelpers.FindBaseProperties(propDef).Any())
astProp.Modifiers |= Modifiers.New;
}
}
@ -1300,194 +1300,5 @@ namespace ICSharpCode.Decompiler.Ast @@ -1300,194 +1300,5 @@ namespace ICSharpCode.Decompiler.Ast
return Tuple.Create(ca.ConstructorArguments.Single().Value as string, ca);
return new Tuple<string,CustomAttribute>(null, null);
}
class TypeMap
{
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
{
var typeContext = CreateGenericContext(method.DeclaringType);
var gMethod = typeContext.ApplyTo(method);
foreach (var baseType in BaseTypes(method.DeclaringType))
foreach (var baseMethod in baseType.Item.Methods)
if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisbleFrom(baseMethod, method)) {
yield return baseMethod;
if (!(baseMethod.IsNewSlot ^ baseMethod.IsVirtual))
yield break;
}
}
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
{
var typeContext = CreateGenericContext(property.DeclaringType);
var gProperty = typeContext.ApplyTo(property);
foreach (var baseType in BaseTypes(property.DeclaringType))
foreach (var baseProperty in baseType.Item.Properties)
if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) && IsVisbleFrom(baseProperty, property)) {
yield return baseProperty;
var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod;
if (!(anyPropertyAccessor.IsNewSlot ^ anyPropertyAccessor.IsVirtual))
yield break;
}
}
private static bool IsVisbleFrom(MethodDefinition baseCandidate, MethodDefinition method)
{
if (baseCandidate.IsPrivate)
return false;
if ((baseCandidate.IsAssembly || baseCandidate.IsFamilyAndAssembly) && baseCandidate.Module != method.Module)
return false;
return true;
}
private static bool IsVisbleFrom(PropertyDefinition baseCandidate, PropertyDefinition property)
{
if (baseCandidate.GetMethod != null && property.GetMethod != null && IsVisbleFrom(baseCandidate.GetMethod, property.GetMethod))
return true;
if (baseCandidate.SetMethod != null && property.SetMethod != null && IsVisbleFrom(baseCandidate.SetMethod, property.SetMethod))
return true;
return false;
}
private static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method)
{
var mCandidate = candidate.Item;
var mMethod = method.Item;
if (mCandidate.Name != mMethod.Name)
return false;
if (mCandidate.HasOverrides)
return false;
if (candidate.Resolve(mCandidate.ReturnType) != method.Resolve(mMethod.ReturnType))
return false;
if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count)
return false;
}
if (mCandidate.HasParameters || mMethod.HasParameters) {
if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
{
var mCandidate = candidate.Item;
var mProperty = property.Item;
if (mCandidate.Name != mProperty.Name)
return false;
if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
return false;
if (candidate.Resolve(mCandidate.PropertyType) != property.Resolve(mProperty.PropertyType))
return false;
if (mCandidate.HasParameters || mProperty.HasParameters) {
if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
{
var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType);
var param = parameterType.Resolve(parameterType.Item.ParameterType);
return baseParam == param;
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type)
{
return BaseTypes(CreateGenericContext(type));
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type)
{
while (type.Item.BaseType != null) {
var baseType = type.Item.BaseType;
var genericBaseType = baseType as GenericInstanceType;
if (genericBaseType != null) {
type = new GenericContext<TypeDefinition>(genericBaseType.Resolve(),
genericBaseType.GenericArguments.Select(t => type.Resolve(t)));
} else
type = new GenericContext<TypeDefinition>(baseType.Resolve());
yield return type;
}
}
private static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type)
{
return new GenericContext<TypeDefinition>(type, type.GenericParameters);
}
struct GenericContext<T>
{
private static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
public readonly T Item;
public readonly ReadOnlyCollection<TypeReference> TypeArguments;
public GenericContext(T item)
{
Item = item;
TypeArguments = Empty;
}
public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
{
Item = item;
var list = new List<TypeReference>();
foreach (var arg in typeArguments) {
if (arg == null)
throw new ArgumentNullException("typeArguments");
if (!arg.IsGenericParameter)
list.Add(arg.Resolve());
else
list.Add(arg);
}
TypeArguments = new ReadOnlyCollection<TypeReference>(list);
}
private GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments)
{
Item = item;
TypeArguments = typeArguments;
}
public TypeReference Resolve(TypeReference type)
{
var genericParameter = type as GenericParameter;
if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) {
return this.TypeArguments[genericParameter.Position];
}
return type.Resolve();
}
public GenericContext<T2> ApplyTo<T2>(T2 item)
{
return new GenericContext<T2>(item, this.TypeArguments);
}
}
}
}
}

247
ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs

@ -0,0 +1,247 @@ @@ -0,0 +1,247 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.Ast
{
public static class TypesHierarchyHelpers
{
public static bool IsBaseType(TypeDefinition baseType, TypeDefinition derivedType, bool resolveTypeArguments)
{
if (resolveTypeArguments)
return BaseTypes(derivedType).Any(t => t.Item == baseType);
else {
var comparableBaseType = baseType.Resolve();
while (derivedType.BaseType != null) {
var resolvedBaseType = derivedType.BaseType.Resolve();
if (resolvedBaseType == null)
return false;
if (comparableBaseType == resolvedBaseType)
return true;
derivedType = resolvedBaseType;
}
return false;
}
}
public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod)
{
if (parentMethod.Name != childMethod.Name)
return false;
if (parentMethod.HasParameters || childMethod.HasParameters)
if(!parentMethod.HasParameters || ! childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count)
return false;
return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.);
}
public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty)
{
if (parentProperty.Name != childProperty.Name)
return false;
if (parentProperty.HasParameters || childProperty.HasParameters)
if (!parentProperty.HasParameters || !childProperty.HasParameters || parentProperty.Parameters.Count != childProperty.Parameters.Count)
return false;
return FindBaseProperties(childProperty).Any(m => m == parentProperty);
}
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
{
var typeContext = CreateGenericContext(method.DeclaringType);
var gMethod = typeContext.ApplyTo(method);
foreach (var baseType in BaseTypes(method.DeclaringType))
foreach (var baseMethod in baseType.Item.Methods)
if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisbleFrom(baseMethod, method)) {
yield return baseMethod;
if (!(baseMethod.IsNewSlot ^ baseMethod.IsVirtual))
yield break;
}
}
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
{
var typeContext = CreateGenericContext(property.DeclaringType);
var gProperty = typeContext.ApplyTo(property);
foreach (var baseType in BaseTypes(property.DeclaringType))
foreach (var baseProperty in baseType.Item.Properties)
if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) && IsVisbleFrom(baseProperty, property)) {
yield return baseProperty;
var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod;
if (!(anyPropertyAccessor.IsNewSlot ^ anyPropertyAccessor.IsVirtual))
yield break;
}
}
private static bool IsVisbleFrom(MethodDefinition baseCandidate, MethodDefinition method)
{
if (baseCandidate.IsPrivate)
return false;
if ((baseCandidate.IsAssembly || baseCandidate.IsFamilyAndAssembly) && baseCandidate.Module != method.Module)
return false;
return true;
}
private static bool IsVisbleFrom(PropertyDefinition baseCandidate, PropertyDefinition property)
{
if (baseCandidate.GetMethod != null && property.GetMethod != null && IsVisbleFrom(baseCandidate.GetMethod, property.GetMethod))
return true;
if (baseCandidate.SetMethod != null && property.SetMethod != null && IsVisbleFrom(baseCandidate.SetMethod, property.SetMethod))
return true;
return false;
}
private static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method)
{
var mCandidate = candidate.Item;
var mMethod = method.Item;
if (mCandidate.Name != mMethod.Name)
return false;
if (mCandidate.HasOverrides)
return false;
if (candidate.Resolve(mCandidate.ReturnType) != method.Resolve(mMethod.ReturnType))
return false;
if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count)
return false;
}
if (mCandidate.HasParameters || mMethod.HasParameters) {
if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
{
var mCandidate = candidate.Item;
var mProperty = property.Item;
if (mCandidate.Name != mProperty.Name)
return false;
if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
return false;
if (candidate.Resolve(mCandidate.PropertyType) != property.Resolve(mProperty.PropertyType))
return false;
if (mCandidate.HasParameters || mProperty.HasParameters) {
if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
{
var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType);
var param = parameterType.Resolve(parameterType.Item.ParameterType);
return baseParam == param;
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type)
{
return BaseTypes(CreateGenericContext(type));
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type)
{
while (type.Item.BaseType != null) {
var baseType = type.Item.BaseType;
var genericBaseType = baseType as GenericInstanceType;
if (genericBaseType != null) {
type = new GenericContext<TypeDefinition>(genericBaseType.Resolve(),
genericBaseType.GenericArguments.Select(t => type.Resolve(t)));
} else
type = new GenericContext<TypeDefinition>(baseType.Resolve());
yield return type;
}
}
private static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type)
{
return type.HasGenericParameters
? new GenericContext<TypeDefinition>(type, type.GenericParameters)
: new GenericContext<TypeDefinition>(type);
}
struct GenericContext<T>
{
private static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
public readonly T Item;
public readonly ReadOnlyCollection<TypeReference> TypeArguments;
public GenericContext(T item)
{
Item = item;
TypeArguments = Empty;
}
public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
{
Item = item;
var list = new List<TypeReference>();
foreach (var arg in typeArguments) {
var resolved = arg != null ? arg.Resolve() : arg;
list.Add(resolved != null ? resolved : arg);
}
TypeArguments = new ReadOnlyCollection<TypeReference>(list);
}
private GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments)
{
Item = item;
TypeArguments = typeArguments;
}
public TypeReference Resolve(TypeReference type)
{
var genericParameter = type as GenericParameter;
if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) {
return this.TypeArguments[genericParameter.Position];
}
var arrayType = type as ArrayType;
if (arrayType != null) {
var resolvedElementType = Resolve(arrayType.ElementType);
if (resolvedElementType == null)
return null;
var newArrayType = new ArrayType(resolvedElementType, arrayType.Rank);
for (int dimension = 0; dimension < arrayType.Rank; dimension++)
newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension];
return newArrayType;
}
return type.Resolve();
}
public GenericContext<T2> ApplyTo<T2>(T2 item)
{
return new GenericContext<T2>(item, this.TypeArguments);
}
}
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -68,6 +68,7 @@ @@ -68,6 +68,7 @@
<Compile Include="Ast\Transforms\PushNegation.cs" />
<Compile Include="Ast\Transforms\TransformationPipeline.cs" />
<Compile Include="Ast\Transforms\PatternStatementTransform.cs" />
<Compile Include="Ast\TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />
<Compile Include="DecompilerException.cs" />
<Compile Include="DecompilerSettings.cs" />

6
ILSpy/ContextMenuEntry.cs

@ -102,10 +102,12 @@ namespace ICSharpCode.ILSpy @@ -102,10 +102,12 @@ namespace ICSharpCode.ILSpy
};
}
if (entryPair.Value.IsEnabled(selectedNodes)) {
menuItem.Click += delegate {
menuItem.Click += delegate
{
entry.Execute(selectedNodes);
};
}
} else
menuItem.IsEnabled = false;
menu.Items.Add(menuItem);
}
}

2
ILSpy/ILSpy.csproj

@ -129,6 +129,8 @@ @@ -129,6 +129,8 @@
<Compile Include="TreeNodes\IMemberTreeNode.cs" />
<Compile Include="TreeNodes\XamlResourceNode.cs" />
<Compile Include="XmlDocKeyProvider.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyTreeNode.cs" />
<EmbeddedResource Include="..\README.txt">
<Link>README.txt</Link>
</EmbeddedResource>

7
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -34,7 +34,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -34,7 +34,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public bool IsEnabled(SharpTreeNode[] selectedNodes)
{
foreach (IMemberTreeNode node in selectedNodes) {
if (!(node.Member is FieldDefinition || node.Member is MethodDefinition))
if (!(node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)))
return false;
}
return true;
@ -51,6 +53,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -51,6 +53,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
MethodDefinition method = node.Member as MethodDefinition;
if (method != null)
MainWindow.Instance.AddToAnalyzer(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member);
if(propertyAnalyzer != null)
MainWindow.Instance.AddToAnalyzer(propertyAnalyzer);
}
}
}

7
ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs

@ -24,12 +24,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -24,12 +24,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
class AnalyzedMethodTreeNode : AnalyzerTreeNode, IMemberTreeNode
{
MethodDefinition analyzedMethod;
string prefix;
public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod)
public AnalyzedMethodTreeNode(MethodDefinition analyzedMethod, string prefix = "")
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");
this.analyzedMethod = analyzedMethod;
this.prefix = prefix;
this.LazyLoading = true;
}
@ -38,7 +40,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -38,7 +40,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
public override object Text {
get { return Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language); }
get {
return prefix + Language.TypeToString(analyzedMethod.DeclaringType, true) + "." + MethodTreeNode.GetText(analyzedMethod, Language); }
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)

92
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyOverridesTreeNode : AnalyzerTreeNode
{
readonly PropertyDefinition analyzedProperty;
readonly ThreadingSupport threading;
public AnalyzedPropertyOverridesTreeNode(PropertyDefinition analyzedProperty)
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedProperty");
this.analyzedProperty = analyzedProperty;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}
public override object Text
{
get { return "Overrided By"; }
}
public override object Icon
{
get { return Images.Search; }
}
protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}
protected override void OnCollapsing()
{
if (threading.IsRunning) {
this.LazyLoading = true;
threading.Cancel();
this.Children.Clear();
}
}
IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.AssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly[] assemblies, CancellationToken ct)
{
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)
{
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedProperty.Name;
string declTypeName = analyzedProperty.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false))
continue;
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) " : "");
}
}
}
}
public static bool CanShowAnalyzer(PropertyDefinition property)
{
var accessor = property.GetMethod ?? property.SetMethod;
return accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface;
}
}
}

80
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyTreeNode : AnalyzerTreeNode
{
PropertyDefinition analyzedProperty;
string prefix;
public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "")
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedMethod");
this.analyzedProperty = analyzedProperty;
this.prefix = prefix;
this.LazyLoading = true;
}
public override object Icon {
get { return PropertyTreeNode.GetIcon(analyzedProperty); }
}
public override object Text {
get {
return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language); }
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = true;
MainWindow.Instance.JumpToReference(analyzedProperty);
}
protected override void LoadChildren()
{
if (AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(analyzedProperty))
this.Children.Add(new AnalyzedPropertyOverridesTreeNode(analyzedProperty));
//if (analyzedProperty.HasBody)
// this.Children.Add(new AnalyzedMethodUsesNode(analyzedProperty));
//this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedProperty));
}
public static AnalyzerTreeNode TryCreateAnalyzer(MemberReference member)
{
if (CanShow(member))
return new AnalyzedPropertyTreeNode(member as PropertyDefinition);
else
return null;
}
public static bool CanShow(MemberReference member)
{
var property = member as PropertyDefinition;
if (property == null)
return false;
return AnalyzedPropertyOverridesTreeNode.CanShowAnalyzer(property);
}
}
}

121
ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -17,11 +18,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -17,11 +18,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
readonly MethodDefinition analyzedMethod;
readonly ThreadingSupport threading;
/// <summary>
/// Controls whether overrides of already overriden method should be included.
/// </summary>
readonly bool onlyDirectOverrides = false;
public AnalyzerMethodOverridesTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
@ -77,127 +73,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -77,127 +73,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
ct.ThrowIfCancellationRequested();
if (!IsDerived(type, analyzedMethod.DeclaringType))
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
continue;
foreach (MethodDefinition method in type.Methods)
{
ct.ThrowIfCancellationRequested();
if (HasCompatibleSpecification(method) && !method.IsNewSlot && DoesOverrideCorrectMethod(method))
if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method))
{
yield return new AnalyzedMethodTreeNode(method);
bool hidesParent = !method.IsVirtual ^ method.IsNewSlot;
yield return new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : "");
}
}
}
}
/// <summary>
/// Tests whether the method could override analyzed method by comparing its name, return type and parameters.
/// </summary>
/// <param name="method">The method to test.</param>
/// <returns>true if the method has the same specyfication as analyzed method, otherwise false.</returns>
private bool HasCompatibleSpecification(MethodDefinition method)
{
return method.Name == analyzedMethod.Name
&& method.IsVirtual
&& AreSameType(method.ReturnType, analyzedMethod.ReturnType)
&& HaveTheSameParameters(method);
}
/// <summary>
/// Checks whether between given and analyzed method are overrides with <code>new</code> (newSlot) modifier.
/// </summary>
/// <param name="method">The method to test.</param>
/// <returns>true if the method overrides analyzed method, false if it overrides some other method that hides analyzed method.</returns>
private bool DoesOverrideCorrectMethod(MethodDefinition method)
{
var type = method.DeclaringType.BaseType.Resolve();
while (type != analyzedMethod.DeclaringType)
{
var parentOverride = type.Methods.Where(m => HasCompatibleSpecification(m)).SingleOrDefault();
if (parentOverride != null)
{
if (parentOverride.IsNewSlot)
return false;
else
return !onlyDirectOverrides;
}
type = type.BaseType.Resolve();
}
return true;
}
/// <summary>
/// Checks whether one type derives (directly or indirectly) from base type.
/// </summary>
/// <param name="derivedType">The possible derived type.</param>
/// <param name="baseType">The base type.</param>
/// <returns>true if <paramref name="derivedType"/> derives from <paramref name="baseType"/>, overwise false.</returns>
private static bool IsDerived(TypeDefinition derivedType, TypeDefinition baseType)
{
while (derivedType != null && derivedType.BaseType != null)
{
if (AreSameType(derivedType.BaseType, baseType))
return true;
derivedType = derivedType.BaseType.Resolve();
}
return false;
}
/// <summary>
/// Checks whether both <see cref="TypeReference"/> instances references the same type.
/// </summary>
/// <param name="ref1">The first type reference.</param>
/// <param name="ref2">The second type reference.</param>
/// <returns>true if both instances references the same type, overwise false.</returns>
private static bool AreSameType(TypeReference ref1, TypeReference ref2)
{
if (ref1 == ref2)
return true;
if (ref1.Name != ref2.Name || ref1.FullName != ref2.FullName)
return false;
return ref1.Resolve() == ref2.Resolve();
}
/// <summary>
/// Checkes whether the given method and the analyzed one has identical lists of parameters.
/// </summary>
/// <param name="method">The method to test.</param>
/// <returns>true if both methods has the same parameters, otherwise false.</returns>
private bool HaveTheSameParameters(MethodDefinition method)
{
if (analyzedMethod.HasParameters)
{
return CompareParameterLists(analyzedMethod.Parameters, method.Parameters);
}
else
{
return !method.HasParameters;
}
}
/// <summary>
/// Compares the list of method's parameters.
/// </summary>
/// <param name="coll1">The first list to compare.</param>
/// <param name="coll2">The second list to copare.</param>
/// <returns>true if both list have parameters of the same types at the same positions.</returns>
private static bool CompareParameterLists(Mono.Collections.Generic.Collection<ParameterDefinition> coll1, Mono.Collections.Generic.Collection<ParameterDefinition> coll2)
{
if (coll1.Count != coll2.Count)
return false;
for (int index = 0; index < coll1.Count; index++)
{
var param1 = coll1[index];
var param2 = coll2[index];
if (param1.Attributes != param2.Attributes || !AreSameType(param1.ParameterType, param2.ParameterType))
return false;
}
return true;
}
}
}

20
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler;
using Mono.Cecil;
@ -36,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -36,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
throw new ArgumentNullException("property");
this.property = property;
this.isIndexer = isIndexer;
if (property.GetMethod != null)
this.Children.Add(new MethodTreeNode(property.GetMethod));
if (property.SetMethod != null)
@ -45,21 +46,32 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -45,21 +46,32 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (var m in property.OtherMethods)
this.Children.Add(new MethodTreeNode(m));
}
}
public PropertyDefinition PropertyDefinition {
get { return property; }
}
public override object Text {
get { return HighlightSearchMatch(property.Name, " : " + this.Language.TypeToString(property.PropertyType, false, property)); }
get { return GetText(property, Language); }
}
public static object GetText(PropertyDefinition property, Language language)
{
return HighlightSearchMatch(property.Name, " : " + language.TypeToString(property.PropertyType, false, property));
}
public override object Icon {
get {
return isIndexer ? Images.Indexer : Images.Property;
return GetIcon(property, isIndexer);
}
}
public static BitmapImage GetIcon(PropertyDefinition property, bool? isIndexer = null)
{
return (isIndexer ?? false) ? Images.Indexer : Images.Property;
}
public override FilterResult Filter(FilterSettings settings)
{

Loading…
Cancel
Save