Skip to content

Commit

Permalink
Constrain where-used searches to accessibility domain.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ed Harvey committed Apr 22, 2011
1 parent fc9a914 commit 1aaa720
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 70 deletions.
1 change: 1 addition & 0 deletions ILSpy/ILSpy.csproj
Expand Up @@ -132,6 +132,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" />
<Compile Include="TreeNodes\IMemberTreeNode.cs" />
<Compile Include="TreeNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyAccessorsTreeNode.cs" />
Expand Down
66 changes: 30 additions & 36 deletions ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs
Expand Up @@ -18,31 +18,33 @@ class AnalyzedFieldAccessNode : AnalyzerTreeNode
readonly bool showWrites; // true: show writes; false: show read access
readonly FieldDefinition analyzedField;
readonly ThreadingSupport threading;

public AnalyzedFieldAccessNode(FieldDefinition analyzedField, bool showWrites)
{
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");

this.analyzedField = analyzedField;
this.showWrites = showWrites;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}

public override object Text {

public override object Text
{
get { return showWrites ? "Assigned By" : "Read By"; }
}

public override object Icon {

public override object Icon
{
get { return Images.Search; }
}

protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}

protected override void OnCollapsing()
{
if (threading.IsRunning) {
Expand All @@ -51,44 +53,36 @@ protected override void OnCollapsing()
this.Children.Clear();
}
}

IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}

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)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
var analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedField, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)

IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
string name = analyzedField.Name;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
foreach (MethodDefinition method in type.Methods) {
ct.ThrowIfCancellationRequested();
bool found = false;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
if (CanBeReference(instr.OpCode.Code)) {
FieldReference fr = instr.Operand as FieldReference;
if (fr != null && fr.Name == name && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) {
found = true;
break;
}
string declTypeName = analyzedField.DeclaringType.FullName;

foreach (MethodDefinition method in type.Methods) {
bool found = false;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
if (CanBeReference(instr.OpCode.Code)) {
FieldReference fr = instr.Operand as FieldReference;
if (fr != null && fr.Name == name && Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) && fr.Resolve() == analyzedField) {
found = true;
break;
}
}
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
}

bool CanBeReference(Code code)
{
switch (code) {
Expand Down
62 changes: 28 additions & 34 deletions ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
Expand Up @@ -32,30 +32,32 @@ class AnalyzedMethodUsedByTreeNode : AnalyzerTreeNode
{
MethodDefinition analyzedMethod;
ThreadingSupport threading;

public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod)
{
if (analyzedMethod == null)
throw new ArgumentNullException("analyzedMethod");

this.analyzedMethod = analyzedMethod;
this.threading = new ThreadingSupport();
this.LazyLoading = true;
}

public override object Text {

public override object Text
{
get { return "Used By"; }
}

public override object Icon {

public override object Icon
{
get { return Images.Search; }
}

protected override void LoadChildren()
{
threading.LoadChildren(this, FetchChildren);
}

protected override void OnCollapsing()
{
if (threading.IsRunning) {
Expand All @@ -64,39 +66,31 @@ protected override void OnCollapsing()
this.Children.Clear();
}
}

IEnumerable<SharpTreeNode> FetchChildren(CancellationToken ct)
{
return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct);
}

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)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
ScopedWhereUsedScopeAnalyzer<SharpTreeNode> analyzer;

analyzer = new ScopedWhereUsedScopeAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly asm, CancellationToken ct)

IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
string name = analyzedMethod.Name;
foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
foreach (MethodDefinition method in type.Methods) {
ct.ThrowIfCancellationRequested();
bool found = false;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) {
found = true;
break;
}
foreach (MethodDefinition method in type.Methods) {
bool found = false;
if (!method.HasBody)
continue;
foreach (Instruction instr in method.Body.Instructions) {
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) {
found = true;
break;
}
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
if (found)
yield return new AnalyzedMethodTreeNode(method);
}
}
}
Expand Down

0 comments on commit 1aaa720

Please sign in to comment.