Visual Studio 代码分析 - 创建新规则来计算方法中的行数

发布于 2024-09-17 20:25:55 字数 3267 浏览 3 评论 0原文

更新

我反映了 Microsoft.Cci.dll 并构建了我的规则。效果很好。但是,我遇到了一些问题,我把 此处包含所有详细信息。源代码是 这里。我不想通过添加所有细节来增加这个问题的长度。

我正在尝试编写一个代码分析规则,该规则会对具有以下特征的方法发出警告: 超过100行。我正在关注 这篇文章。但是,我无法按照CodeAnalysis提供的API来计算行数。例如,

public override ProblemCollection Check(Member member)
        {
            Method method = member as Method;
            if (method == null)
            {
                return null;
            }
            CheckForLOC(method);
            return Problems;
        }

以下是 CheckForLOC()

private void CheckForLOC(Method method)
    {
        int startLineForMethod = method.Body.SourceContext.StartLine;
        int endLineForMethod = method.Body.SourceContext.EndLine;
        if (endLineForMethod > startLineForMethod
            && ((endLineForMethod - startLineForMethod) > constMaximumLOCforAMethod))
        {
            Resolution resolution = GetResolution(method, constMaximumLOCforAMethod);
            Problem problem = new Problem(resolution);
            Problems.Add(problem);
        }
    }

在上面的代码中,method.Body.SourceContext.StartLine 和 method.Body.SourceContext.EndLine 返回相同的值。不知道为什么。

我还尝试使用 StatementCollection :-

private void CheckForLOC(Method method)
        {
            int LOCPerMethod = 0;

            if (method.Body.Statements.Count >= 1)
            {
                foreach (var statement in method.Body.Statements)
                {
                    LOCPerMethod += GetNumberOfLinesPerStatement(statement);
                }

            }
            if (LOCPerMethod > constMaximumLOCforAMethod)
            {
                Resolution resolution = GetResolution(method, constMaximumLOCforAMethod);
                Problem problem = new Problem(resolution);
                Problems.Add(problem);
            }
        }

        private int GetNumberOfLinesPerStatement(Statement statement)
        {
            int LOCperStatement = 0;
            if (statement.SourceContext.EndLine > statement.SourceContext.StartLine)
            {
                LOCperStatement = statement.SourceContext.EndLine - statement.SourceContext.StartLine;
            }
            return LOCperStatement;
        }

这里,Statement.SourceContext.StartLine 和 Statement.SourceContext.EndLine 返回相同的值。我看到每个语句的 StartLine 都不同,需要从前一个语句的 StartLine 值中减去一个语句的 StartLine 值。但是,我发现结果不稳定。例如,在下面的方法片段中,它给出了 Statement1 的行号作为 StartLineNumber,而它应该给出 If(SomeCondition) 的 StartLineNumber:-

if(SomeCondition)
{
   Statement1
   Statement2
   Statement3
}

有人可以对此提供一些指导吗?

UPDATE

I reflected Microsoft.Cci.dll and build my rule. It works fine. However, I am facing some problem which I put here with all the details. Source code is here. I didn't want to increase the length of this question by putting all the details.

I am trying to write a code analysis rule which would raise warnings for methods having
more than 100 lines. I am following this article. However, I am unable to count the number of lines by following the API provided by CodeAnalysis. for example,

public override ProblemCollection Check(Member member)
        {
            Method method = member as Method;
            if (method == null)
            {
                return null;
            }
            CheckForLOC(method);
            return Problems;
        }

Following is the CheckForLOC()

private void CheckForLOC(Method method)
    {
        int startLineForMethod = method.Body.SourceContext.StartLine;
        int endLineForMethod = method.Body.SourceContext.EndLine;
        if (endLineForMethod > startLineForMethod
            && ((endLineForMethod - startLineForMethod) > constMaximumLOCforAMethod))
        {
            Resolution resolution = GetResolution(method, constMaximumLOCforAMethod);
            Problem problem = new Problem(resolution);
            Problems.Add(problem);
        }
    }

In the above code, method.Body.SourceContext.StartLine and method.Body.SourceContext.EndLine return the same value. Not sure why.

I also tried using the StatementCollection :-

private void CheckForLOC(Method method)
        {
            int LOCPerMethod = 0;

            if (method.Body.Statements.Count >= 1)
            {
                foreach (var statement in method.Body.Statements)
                {
                    LOCPerMethod += GetNumberOfLinesPerStatement(statement);
                }

            }
            if (LOCPerMethod > constMaximumLOCforAMethod)
            {
                Resolution resolution = GetResolution(method, constMaximumLOCforAMethod);
                Problem problem = new Problem(resolution);
                Problems.Add(problem);
            }
        }

        private int GetNumberOfLinesPerStatement(Statement statement)
        {
            int LOCperStatement = 0;
            if (statement.SourceContext.EndLine > statement.SourceContext.StartLine)
            {
                LOCperStatement = statement.SourceContext.EndLine - statement.SourceContext.StartLine;
            }
            return LOCperStatement;
        }

Here also, Statement.SourceContext.StartLine and Statement.SourceContext.EndLine return the same value. I see that the StartLine for each statement is different and one needs to substract the StartLine value of the one statement from its previous one's. However, I see that result is erratic. For example, in the below snippet in a method, It gives me the line number of Statement1 as StartLineNumber whereas It should give the StartLineNumber of If(SomeCondition):-

if(SomeCondition)
{
   Statement1
   Statement2
   Statement3
}

Could anybody provide some direction on this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋叶绚丽 2024-09-24 20:25:55

这更像是一种样式规则,而不是正确性规则,因此它比 FxCop 规则更适合 StyleCop 规则。

也就是说,如果您确实想通过 FxCop 实现它,您应该看看 Microsoft.FxCop.Sdk.MethodMetrics.CalculateLinesOfCode(Method) 如何完成相同的任务。

This is more of a style rule than a correctness rule, so it would be a better candidate for a StyleCop rule than an FxCop rule.

That said, if you really want to implement it via FxCop, you should take a look at how the Microsoft.FxCop.Sdk.MethodMetrics.CalculateLinesOfCode(Method) accomplishes the same task.

安人多梦 2024-09-24 20:25:55

NDepend 工具支持任何 .NET 语言的指标 NbLinesOfCode。此外,它还集成在 Visual Studio 2012、2010、2008 中。免责声明:我是该工具的开发人员之一

您要求...

创建新规则来计算方法中的行数

使用 NDepend,您可以编写 基于 LINQ 查询的代码规则 (即CQLinq)。因此,创建一个新规则来计算方法中的行数,可以像编写...一样简单

warnif count > 0 
from m in JustMyCode.Methods
where m.NbLinesOfCode > 10
orderby m.NbLinesOfCode descending 
select new { m, m.NbLinesOfCode }

,并在 Visual Studio 中立即获得结果。只需双击结果中的方法即可跳转到代码中的方法声明:

在此处输入图像描述

周围 默认建议 200 个默认 CQLinq 代码查询和规则

The tool NDepend supports the metric NbLinesOfCode on any .NET language. Also, it integrates in Visual Studio 2012, 2010, 2008. Disclaimer: I am one of the developers of the tool

You are asking for...

Creating a new rule to count number of lines in methods

With NDepend you can write Code Rules over LINQ Queries (namely CQLinq). Hence creating a new rule to count number of lines in methods, can be as simple as writing...

warnif count > 0 
from m in JustMyCode.Methods
where m.NbLinesOfCode > 10
orderby m.NbLinesOfCode descending 
select new { m, m.NbLinesOfCode }

...and get an immediate result in Visual Studio. Just by double-clicking a method in the result jumps to the method declaration in code:

enter image description here

Around 200 default CQLinq code queries and rules are proposed by default.

只是一片海 2024-09-24 20:25:55

我一直在寻找相同的方法(以获取方法中的总行数),并且找到了解决方案。

下面是示例:

public override ProblemCollection Check(Member member)
    {
        Method method = member as Method;
        if (method != null)
        {
            **if (method.Metrics.ClassCoupling > 20)**
            {
                Resolution resolu = GetResolution(new string[] { method.ToString() });
                Problems.Add(new Problem(resolu));
            }
        }
        return Problems;
    }

您可以尝试 method.Metrics.ClassCoupling 来获取方法的总行数。

I was looking for the same (to get total no of lines in a method) and I found solution.

Below is the sample:

public override ProblemCollection Check(Member member)
    {
        Method method = member as Method;
        if (method != null)
        {
            **if (method.Metrics.ClassCoupling > 20)**
            {
                Resolution resolu = GetResolution(new string[] { method.ToString() });
                Problems.Add(new Problem(resolu));
            }
        }
        return Problems;
    }

You can try method.Metrics.ClassCoupling to get the total lines a method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文