2011-06-21 7 views
5

Tôi muốn tạo một FxRule áp dụng một phương thức, chỉ khi phương thức được gọi từ một lớp cụ thể. Chú ý: Tôi không muốn chỉ áp dụng một quy tắc cho một phương thức của một lớp cụ thể, tôi muốn có khả năng xử lý các phương thức gọi các phương thức khác gọi các phương thức khác làm boxing.Quy tắc tùy chỉnh trong FxCop chỉ áp dụng cho các phương thức được gọi theo phương pháp kiểu cụ thể

Tôi muốn yêu cầu FxCop báo cáo các sự cố liên quan đến phương pháp thực hiện quyền anh.

Dưới đây là đoạn code tôi có cho đến nay:

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

Vấn đề của tôi với đoạn code trên, là trước hết, nó không xuất hiện để được recursing. Thứ hai, rằng FxCop báo cáo các vấn đề liên quan đến không gian tên (có lẽ vì tôi bắt đầu chuyến thăm bằng cách sử dụng phần Kiểm tra (không gian tên ....)

Vấn đề của tôi là tôi muốn FxCop báo cáo một phương pháp có boxing là một vấn đề, nhưng chỉ khi nó được gọi bằng một phương pháp cụ thể, tuy nhiên tôi không có cách nào để đi lên cây gọi, tôi chỉ có thể ghé thăm các nút thấp hơn để kiểm tra các vấn đề với vị trí bắt đầu của tôi. loại này trước đây?

Làm cách nào tôi có thể tìm ra phương pháp nào gọi một phương thức nhất định?

Trả lời

4

EDIT: Điều này không hoạt động trong trường hợp các cuộc gọi phương thức ảo trong đó IL là callvirt. Xem câu hỏi của tôi here.

Tôi đã cố gắng giải quyết nó bằng cách khám phá phương thức CallGraph.CallersFor(). Bây giờ tôi đang tìm các phương thức được khai báo với một thuộc tính đã cho, hoặc được khai báo bởi một lớp với một thuộc tính đã cho, nhưng hiệu trưởng là giống nhau.

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