drizzt
drizzt

Reputation: 2886

Find exception hiding/swallowing in C# code in VS2013

is there some way built in function/extension/tool to find all exception hidings/exception swallowing in C# solution(ASP.NET WebForms)n in VS2013.

Thanks

EDIT:

I have existing solution in which some programmers use hide/swallow exceptions(empty catch, catch only with some useless code). And I am looking for some way to find all these places in code, analyze them, and then fix them.

Upvotes: 3

Views: 976

Answers (2)

Daniel Mann
Daniel Mann

Reputation: 59045

You can write some code using Roslyn to handle this pretty easily.

I actually wrote some code to do exactly that for a friend. It was my first attempt at using the Roslyn SDK, so my code is probably a terrible mess, but it was definitely functional.

    static void Main(string[] args)
    {
        var result = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseFile(@"..\..\Test.cs");

        var root = result.GetRoot();

        var exceptionNodes = FindCatchNodes(root);

        foreach (var node in exceptionNodes)
        {
            var line = node.GetLocation().GetLineSpan().StartLinePosition.Line + 1;
            if (IsTotallyEmptyCatch(node))
            {
                Console.WriteLine("Totally empty catch: line {0}", line);
            }
            if (JustRethrows(node))
            {
                Console.WriteLine("Pointless rethrow: line {0}", line);
            }
        }
    }


    static List<SyntaxNodeOrToken> FindCatchNodes(SyntaxNodeOrToken node)
    {
        var exceptions = new List<SyntaxNodeOrToken>();
        var isCatchBlock = node.IsKind(SyntaxKind.CatchClause);
        if (isCatchBlock)
        {
            exceptions.Add(node);
        }

        foreach (var result in node.ChildNodesAndTokens().Select(FindCatchNodes).Where(result => result != null))
        {
            exceptions.AddRange(result);
        }
        return exceptions;

    }

    static bool IsTotallyEmptyCatch(SyntaxNodeOrToken catchBlock)
    {
        var block = catchBlock.ChildNodesAndTokens().First(t => t.CSharpKind() == SyntaxKind.Block);
        var children = block.ChildNodesAndTokens();
        return (children.Count == 2 && children.Any(c => c.CSharpKind() == SyntaxKind.OpenBraceToken) &&
                children.Any(c => c.CSharpKind() == SyntaxKind.CloseBraceToken));
    }

    static bool JustRethrows(SyntaxNodeOrToken catchBlock)
    {
        var block = catchBlock.ChildNodesAndTokens().First(t => t.CSharpKind() == SyntaxKind.Block);
        var children = block.ChildNodesAndTokens();
        return (children.Count == 3 && children.Any(c => c.CSharpKind() == SyntaxKind.OpenBraceToken) &&
                children.Any(c => c.CSharpKind() == SyntaxKind.CloseBraceToken) && children.Any(c=>c.CSharpKind() == SyntaxKind.ThrowStatement));
    } 

Given this test file:

using System;
namespace RoslynTest
{
    public class Test
    {
        public void Foo()
        {
            try
            {
                var x = 0;
            }
            catch
            {

            }
        }

        public void Bar()
        {
            try
            {
                var x = 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        public void Baz()
        {
            try
            {
                var x = 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}

The output is:

Totally empty catch: ....\Test.cs: line 12

Pointless rethrow: ....\Test.cs: line 24

Pointless rethrow: ....\Test.cs: line 37

Upvotes: 9

Vladimir Perevalov
Vladimir Perevalov

Reputation: 4157

I don't know about the built-in methods. But you can write your own tool to find such places. Just regex all your files in solution and count catch and throw. There should be the same amount for each file :)

Upvotes: 1

Related Questions