Browse Source

Analyzer - Limit scope of overrides search

pull/170/head
Ed Harvey 15 years ago
parent
commit
e43f6abcf0
  1. 21
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  2. 23
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  3. 30
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  4. 63
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

21
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -68,31 +68,21 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct) private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
}
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil) analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedEvent, FindReferencesInType);
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); return analyzer.PerformAnalysis(ct);
} }
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct) private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedEvent.Name; string name = analyzedEvent.Name;
string declTypeName = analyzedEvent.DeclaringType.FullName; string declTypeName = analyzedEvent.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false)) if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false))
continue; yield break;
foreach (EventDefinition eventDef in type.Events) { foreach (EventDefinition eventDef in type.Events) {
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) { if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod; MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
@ -100,7 +90,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
} }
} }
}
public static bool CanShow(EventDefinition property) public static bool CanShow(EventDefinition property)
{ {

23
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -73,32 +73,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct) private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
}
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil) analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); return analyzer.PerformAnalysis(ct);
} }
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct) private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedMethod.Name;
string declTypeName = analyzedMethod.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
SharpTreeNode newNode = null; SharpTreeNode newNode = null;
try { try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
continue; yield break;
foreach (MethodDefinition method in type.Methods) { foreach (MethodDefinition method in type.Methods) {
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) { if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) {
bool hidesParent = !method.IsVirtual ^ method.IsNewSlot; bool hidesParent = !method.IsVirtual ^ method.IsNewSlot;
newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : ""); newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : "");
@ -112,7 +100,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (newNode != null) if (newNode != null)
yield return newNode; yield return newNode;
} }
}
public static bool CanShow(MethodDefinition method) public static bool CanShow(MethodDefinition method)
{ {

30
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -69,45 +69,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct) private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{ {
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
}
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil) analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedProperty, FindReferencesInType);
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); return analyzer.PerformAnalysis(ct);
} }
private IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct) private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{ {
string asmName = asm.AssemblyDefinition.Name.Name;
string name = analyzedProperty.Name; string name = analyzedProperty.Name;
string declTypeName = analyzedProperty.DeclaringType.FullName; string declTypeName = analyzedProperty.DeclaringType.FullName;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
SharpTreeNode newNode = null;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false))
continue; yield break;
foreach (PropertyDefinition property in type.Properties) { foreach (PropertyDefinition property in type.Properties) {
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
newNode = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
}
}
}
catch (ReferenceResolvingException) {
// ignore this type definition.
} }
if (newNode != null)
yield return newNode;
} }
} }

63
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -47,27 +47,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public ScopedWhereUsedScopeAnalyzer(MethodDefinition method, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction) public ScopedWhereUsedScopeAnalyzer(MethodDefinition method, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
: this(method.DeclaringType, typeAnalysisFunction) : this(method.DeclaringType, typeAnalysisFunction)
{ {
switch (method.Attributes & MethodAttributes.MemberAccessMask) { this.memberAccessibility = GetMethodAccessibility(method);
case MethodAttributes.Private:
default:
memberAccessibility = Accessibility.Private;
break;
case MethodAttributes.FamANDAssem:
memberAccessibility = Accessibility.FamilyAndInternal;
break;
case MethodAttributes.Family:
memberAccessibility = Accessibility.Family;
break;
case MethodAttributes.Assembly:
memberAccessibility = Accessibility.Internal;
break;
case MethodAttributes.FamORAssem:
memberAccessibility = Accessibility.FamilyOrInternal;
break;
case MethodAttributes.Public:
memberAccessibility = Accessibility.Public;
break;
} }
public ScopedWhereUsedScopeAnalyzer(PropertyDefinition property, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
: this(property.DeclaringType, typeAnalysisFunction)
{
Accessibility getterAccessibility = (property.GetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.GetMethod);
Accessibility setterAccessibility = (property.SetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.SetMethod);
this.memberAccessibility = (Accessibility)Math.Max((int)getterAccessibility, (int)setterAccessibility);
}
public ScopedWhereUsedScopeAnalyzer(EventDefinition eventDef, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
: this(eventDef.DeclaringType, typeAnalysisFunction)
{
// we only have to check the accessibility of the the get method
// [CLS Rule 30: The accessibility of an event and of its accessors shall be identical.]
this.memberAccessibility = GetMethodAccessibility(eventDef.AddMethod);
} }
public ScopedWhereUsedScopeAnalyzer(FieldDefinition field, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction) public ScopedWhereUsedScopeAnalyzer(FieldDefinition field, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
@ -96,6 +92,33 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
} }
} }
private Accessibility GetMethodAccessibility(MethodDefinition method)
{
Accessibility accessibility;
switch (method.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Private:
default:
accessibility = Accessibility.Private;
break;
case MethodAttributes.FamANDAssem:
accessibility = Accessibility.FamilyAndInternal;
break;
case MethodAttributes.Family:
accessibility = Accessibility.Family;
break;
case MethodAttributes.Assembly:
accessibility = Accessibility.Internal;
break;
case MethodAttributes.FamORAssem:
accessibility = Accessibility.FamilyOrInternal;
break;
case MethodAttributes.Public:
accessibility = Accessibility.Public;
break;
}
return accessibility;
}
public IEnumerable<T> PerformAnalysis(CancellationToken ct) public IEnumerable<T> PerformAnalysis(CancellationToken ct)
{ {
if (memberAccessibility == Accessibility.Private) { if (memberAccessibility == Accessibility.Private) {

Loading…
Cancel
Save