Browse Source

Analyzer - Limit scope of overrides search

pull/170/head
Ed Harvey 15 years ago
parent
commit
e43f6abcf0
  1. 33
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  2. 51
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  3. 40
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  4. 65
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

33
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -68,36 +68,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -68,36 +68,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedEvent, FindReferencesInType);
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 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))
continue;
foreach (EventDefinition eventDef in type.Events) {
ct.ThrowIfCancellationRequested();
if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false))
yield break;
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : "");
}
foreach (EventDefinition eventDef in type.Events) {
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : "");
}
}
}

51
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -73,45 +73,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -73,45 +73,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
private IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}
private IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
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;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
continue;
foreach (MethodDefinition method in type.Methods) {
ct.ThrowIfCancellationRequested();
if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) {
bool hidesParent = !method.IsVirtual ^ method.IsNewSlot;
newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : "");
}
SharpTreeNode 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)
yield return newNode;
}
catch (ReferenceResolvingException) {
// ignore this type definition. maybe add a notification about such cases.
}
if (newNode != null)
yield return newNode;
}
public static bool CanShow(MethodDefinition method)

40
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

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

65
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -47,27 +47,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -47,27 +47,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public ScopedWhereUsedScopeAnalyzer(MethodDefinition method, Func<TypeDefinition, IEnumerable<T>> typeAnalysisFunction)
: this(method.DeclaringType, typeAnalysisFunction)
{
switch (method.Attributes & MethodAttributes.MemberAccessMask) {
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;
}
this.memberAccessibility = GetMethodAccessibility(method);
}
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)
@ -96,6 +92,33 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -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)
{
if (memberAccessibility == Accessibility.Private) {

Loading…
Cancel
Save