簡體   English   中英

FxCop中的自定義規則僅適用於特定類型方法調用的方法

[英]Custom Rule in FxCop to only apply to methods called by particular type's method

我想創建一個應用方法的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(名稱空間....)部分啟動了訪問。

我的問題是我希望FxCop報告一個有拳擊作為問題的方法,但只有當它被特定方法調用時,但是我無法走向調用樹,我只能訪問較低的節點來檢查我的起始位置問題。

有沒有人以前做過這種事情?

我怎樣才能找出調用給定方法的方法?

編輯:這在IL是callvirt的虛方法調用的情況下callvirt 在這里看我的問題。

我設法通過發現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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM