开发者

Static analysis of .net assembly

I have a C# project for which I need to find the all private methods which are not called from any other public method directly or indirectly.

In addition, for each private method which is called from a public method, I need to know which public method it is. Then I will detemine if that method is really called from a client of the class an开发者_运维知识库d if not I will be able to remove it.

In the past I used a code from Lutz Rorder which is the base of Reflector - it had an option to analyze IL code and gave object model on top of it. I cannot find this code now.

Any suggestion? Maybe a point to that Lutz Rorder code?

Saar


You should check out Nitriq Static Code Analysis for .Net - They have a free community edition and their full blown license is pretty reasonable.


As pointed Thomas the tool NDepend can help you to find unused code in a .NET code base. Disclaimer: I am one of the developer of this tool.

NDepend proposes to write Code Rule over LINQ Query (CQLinq). Around 200 default code rules are proposed, 3 of them being dedicated to unused/dead code detection:

  • Potentially dead Types (hence detect unused class, struct, interface, delegate...)
  • Potentially dead Methods (hence detect unused method, ctor, property getter/setter...)
  • Potentially dead Fields

NDepend is integrated in Visual Studio, thus these rules can be checked/browsed/edited right inside the IDE. The tool can also be integrated into your CI process and it can build reports that will show rules violated and culprit code elements.

If you click these 3 links above toward the source code of these rules, you'll see that the ones concerning types and methods are a bit complex. This is because they detect not only unused types and methods, but also types and methods used only by unused dead types and methods (recursive).

This is static analysis, hence the prefix Potentially in the rule names. If a code element is used only through reflection, these rules might consider it as unused which is not the case.

In addition to using these 3 rules, I'd advise measuring code coverage by tests and striving for having full coverage. Often, you'll see that code that cannot be covered by tests, is actually unused/dead code that can be safely discarded. This is especially useful in complex algorithms where it is not clear if a branch of code is reachable or not.


In addition, for each private method which is called from a public method, I need to know which public method it is.

To obtain this information, with CQLinq you just need to write:

from m in Application.Methods
where m.IsPrivate
let publicMethodsCallingMe = m.MethodsCallingMe.Where(m1 => m1.IsPublic)
where publicMethodsCallingMe.Count() > 0
select new { m, publicMethodsCallingMe }

The query result will be easily browsable:

Static analysis of .net assembly


Well, the only method to do this (at least the only one that I know...) implies the use of a commercial (but not so expensive) tool, namely NDepend.

Among many other things, you can write SQL-like queries against your compiled assemblies, which allows for very fine-grained analysis. They call it CQL, the syntax is self-explaining, and NDepend's IntelliSense/auto-completion support as well as the general help/documentation are quite good.

(AFAIK they also provide a fully-featured trial, if that helps you...)

HTH!


Not sure if it will fulfil all these needs, but FXCop will do most of these for you and will help do a whole lot of coding standards as well. It's worth running over your c# code either way.

FXCop (MSDN)


Reflector still has this functionality. Just right click the method, and click Analyze. Follow the links in the tree view.

You do not say whether you need to do it in code, or just 'visually'.

If needed for code, I am sure you can use the Reflector SDK.


I might be able to help you with this one using the Query Editor in the PowerCommands for Reflector addin (http://powercommands.codeplex.com) ... I'll see what I can come up with tonight, then let you know tomorrow.

Otherwise you could also write a quick application using the CCI or Cecil that would do it.

Query:

from a in AssemblyManager.Assemblies.Cast<IAssembly>()
where a.Name != "mscorlib" 
    && !a.Name.Contains("System")
from m in a.Modules.Cast<IModule>()
from t in m.Types.Cast<ITypeDeclaration>()
from mt in t.Methods.Cast<IMethodDeclaration>()
where mt.Visibility == MethodVisibility.Public 
    && !mt.RuntimeSpecialName 
    && !mt.SpecialName 
    && mt.Body is IMethodBody
from i in ((IMethodBody)mt.Body).Instructions.Cast<IInstruction>()
where i != null 
    && i.Value != null 
    && i.Value is IMethodReference 
    && ((IMethodReference)i.Value).Resolve() != null
    && ((IMethodReference)i.Value).Resolve().Visibility == MethodVisibility.Private
select new { 
    CallingMethod=t.Namespace + "." + t.Name + "." + mt.Name, 
    PrivateReferencedMethod=((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Namespace + "."
        + ((ITypeReference)((IMemberReference)((IMethodReference)i.Value).Resolve()).DeclaringType).Name + "."
        + ((IMethodReference)i.Value).ToString()
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜