FxCop 中的自定义规则仅适用于由特定类型的方法调用的方法

Posted

技术标签:

【中文标题】FxCop 中的自定义规则仅适用于由特定类型的方法调用的方法【英文标题】:Custom Rule in FxCop to only apply to methods called by particular type's method 【发布时间】:2011-06-21 13:34:27 【问题描述】:

我想创建一个应用方法的 FxRule,仅当从特定类调用该方法时。

注意:我不想只将规则应用于特定类的方法,我希望能够处理调用其他方法的方法调用其他执行装箱的方法。

我想让 FxCop 报告与进行装箱的方法相关的问题。

以下是我目前的代码:

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);
    

我对上述代码的问题首先是它似乎没有递归。其次,FxCop 将问题报告为与命名空间相关联(可能是因为我使用 Check(namespace....) 部分开始访问。

我的问题是我希望 FxCop 报告一个有装箱问题的方法,但前提是它被特定方法调用,但是我无法向上走调用树,我只能访问较低的节点检查我的起始位置是否存在问题。

以前有人做过这种事吗?

我怎样才能知道哪些方法调用了给定的方法?

【问题讨论】:

【参考方案1】:

编辑: 这在 IL 为 callvirt 的虚拟方法调用的情况下不起作用。请参阅我的问题here。

通过发现CallGraph.CallersFor() 方法,我设法解决了这个问题。我现在正在寻找使用给定属性声明的方法,或者由具有给定属性的类声明的方法,但主体是相同的。

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);
    

【讨论】:

以上是关于FxCop 中的自定义规则仅适用于由特定类型的方法调用的方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FxCop 的自定义规则中获取传递给方法的参数值?

如何编写代码分析 (FxCop) 规则以防止方法调用

忽略某些特定情况的内置 FxCop 规则。自定义 FxCop 规则?

自定义控件的 FxCop 自定义规则

我可以将自定义令牌规则应用于由 spaCy 中的前缀拆分的令牌吗?

是否有自定义 FxCop 规则可以检测未使用的 PUBLIC 方法?