在FxCop的自定义规则只适用于方法调用特定类型的方法方法、适用于、自定义、规则

2023-09-03 16:48:33 作者:俗雅无味

我要创建适用方法的FxRule,只有当该方法被从一个特定的类调用。

I want to create an FxRule that applies a method, only if the method gets called from a specific class.

注:我不希望只是规则应用于特定类的方法,我希望能够处理方法调用其他方法调用里面做拳击等方法

NOTE: I don't want to just apply a rule to a method of a particular class, i want to be able to handle methods calling other methods calling other methods which do the boxing.

我想获得FxCop的举报,做拳击的方法有关的问题。

I'd like to get FxCop to report problems associated with the method that does the boxing.

下面是code我到目前为止有:

Below is the code i have so far:

using System;
using System.Linq;
using Microsoft.FxCop.Sdk;
using System.Collections.Generic;

class CheckUpdatableComponents : BaseIntrospectionRule
{
    private string[] MethodsToCheck = new string[] { "BeginDraw", "BeginRun", "Draw", "EndRun", "EndDraw", "Update" };

    /// <summary>Gets the base class hooked up.</summary>
    public CheckUpdatableComponents()
        : base("CheckUpdatableComponents", "FxCopRules.Rules", typeof(CheckUpdatableComponents).Assembly)
    {
    }

    public override ProblemCollection Check(string namespaceName, TypeNodeCollection types)
    {
        foreach (var type in types.Where(T => IsSubClassOf(T, "Microsoft.Xna.Framework.Game")))
        {
            foreach (var MethodToCheck in MethodsToCheck)
            {
                Method RunMethod = type.GetMethod(Identifier.For(MethodToCheck));

                if (RunMethod != null)
                {
                    Visit(RunMethod);
                }
            }
        }

        return Problems;
    }

    public override void VisitMethod(Method method)
    {
                Problems.Add(new Problem(GetResolution(), method, method.ToString())); // This problem only appears for each of the RunMethods, and doesn't seem to be recursing down the tree.


        foreach (var Instruction in method.Instructions)
        {
            if (Instruction.NodeType == NodeType.Box ||
                Instruction.NodeType == NodeType.Unbox ||
                Instruction.NodeType == NodeType.UnboxAny ||
                Instruction.OpCode == OpCode.Box ||
                Instruction.OpCode == OpCode.Unbox ||
                Instruction.OpCode == OpCode.Unbox_Any)
            {
            }
        }

        base.VisitMethod(method);
    }

    private bool IsSubClassOf(TypeNode type, string typeName)
    {
        if (type.FullName == typeName)
            return true;
        if (type.BaseType == null)
            return false;
        else
            return IsSubClassOf(type.BaseType, typeName);
    }
}

我的问题与上述code,首先是,它似乎并没有被递归。其次,FxCop的报告的问题为与命名空间(可能是因为我开球使用检查(命名空间....)部分的访问有关。

My issue with the above code, is firstly, that it doesn't appear to be recursing. Secondly, that FxCop reports the problems as being associated with the namespace (probably because i kick off the visit using the Check(namespace....) part.

我的问题是,我想FxCop的报告,有拳击作为一个问题的方法,但只有当它被调用特定的方法,但是我没有办法走了调用树的,我只能访问较低的节点检查问题,我的出发位置。

My problem is that i want FxCop to report a method that has boxing as a problem, but only if it gets called by a particular method, however i have no way of walking up the call tree, i can only visit lower nodes to check for problems with my starting location.

有没有人做过这样的事情?

Has anyone done this sort of thing before?

我要如何找出方法调用一个给定的方法?

How can i find out what methods call a given method?

推荐答案

编辑:这并不在虚拟方法的情况下,工作电话,其中IL为 callvirt 。见我的问题here.

This doesn't work in the case of virtual method calls where the IL is callvirt. See my question here.

我设法去解决问题,通过发现方法 CallGraph.CallersFor()。我现在想找一个给定的属性用一类具有特定属性的声明,或声明的方法,但主要是相同的。

I managed to work it out, by discovering the method CallGraph.CallersFor(). I'm now looking for methods declared with a given attribute, or declared by a class with a given attribute, but the principal is the same.

using System;
using System.Linq;
using Microsoft.FxCop.Sdk;
using System.Collections.Generic;

class CheckUpdatableComponents : BaseIntrospectionRule
{
    // private string[] MethodsToCheckNames = new string[] { "BeginDraw", "BeginRun", "Draw", "EndRun", "EndDraw", "Update" };

    /// <summary>Gets the base class hooked up.</summary>
    public CheckUpdatableComponents()
        : base("CheckUpdatableComponents", "FxCopRules.Rules", typeof(CheckUpdatableComponents).Assembly)
    {
    }

    public override ProblemCollection Check(Member member)
    {

        Method method = member as Method;

        if (method != null)
        {
            if (ShouldCheckMethod(method))
            {
                foreach (var Instruction in method.Instructions)
                {
                    if (Instruction.NodeType == NodeType.Box ||
                        Instruction.NodeType == NodeType.Unbox ||
                        Instruction.NodeType == NodeType.UnboxAny ||
                        Instruction.OpCode == OpCode.Box ||
                        Instruction.OpCode == OpCode.Unbox ||
                        Instruction.OpCode == OpCode.Unbox_Any)
                    {
                        Problems.Add(new Problem(GetResolution(), Instruction, Instruction.SourceContext.StartLine.ToString()));
                    }
                }
            }
        }

        return Problems;
    }

    public bool ShouldCheckMethod(Method method)
    {
        Queue<Method> MethodsToCheck = new Queue<Method>();

        List<Method> MethodsChecked = new List<Method>();

        MethodsToCheck.Enqueue(method);

        while (MethodsToCheck.Count != 0)
        {
            Method MethodToCheck = MethodsToCheck.Dequeue();

            if (!MethodsChecked.Contains(MethodToCheck) && MethodToCheck != null)
            {
                /*if (IsSubClassOf(MethodToCheck.DeclaringType, "Microsoft.Xna.Framework.Game") &&
                    MethodsToCheckNames.Contains(MethodToCheck.Name.Name))
                {
                    return true;
                }*/

                foreach (var attribute in MethodToCheck.Attributes.Union(MethodToCheck.DeclaringType.Attributes))
                {
                    if (attribute.Type != null &&
                        attribute.Type.FullName == "GridEngine.Components.Debugging.Attributes.FxCop.PerformanceCriticalAttribute")
                    {
                        return true;
                    }
                }

                // Add methods up the class tree
                MethodsToCheck.Enqueue(MethodToCheck.OverriddenMethod);
                MethodsToCheck.Enqueue(MethodToCheck.HiddenMethod);



                // Add calling methods
                foreach (var CallingMethod in CallGraph.CallersFor(MethodToCheck))
                {
                    MethodsToCheck.Enqueue(CallingMethod);
                }
            }

            MethodsChecked.Add(MethodToCheck);
        }

        return false;
    }

    private bool IsSubClassOf(TypeNode type, string typeName)
    {
        if (type.FullName == typeName)
            return true;
        if (type.BaseType == null)
            return false;
        else
            return IsSubClassOf(type.BaseType, typeName);
    }
}