[英]Custom Rule in FxCop to only apply to methods called by particular type's method
I want to create an FxRule that applies a method, only if the method gets called from a specific class. 我想创建一个应用方法的FxRule,只有在从特定类调用该方法时才会这样。
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. 注意:我不想只是将规则应用于特定类的方法,我希望能够处理调用其他方法调用其他方法进行装箱的方法。
I'd like to get FxCop to report problems associated with the method that does the boxing. 我想让FxCop报告与拳击方法相关的问题。
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);
}
}
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将问题报告为与命名空间相关联(可能是因为我使用Check(名称空间....)部分启动了访问。
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. 我的问题是我希望FxCop报告一个有拳击作为问题的方法,但只有当它被特定方法调用时,但是我无法走向调用树,我只能访问较低的节点来检查我的起始位置问题。
Has anyone done this sort of thing before? 有没有人以前做过这种事情?
How can i find out what methods call a given method? 我怎样才能找出调用给定方法的方法?
EDIT: This doesn't work in the case of virtual method calls where the IL is callvirt
. 编辑:这在IL是
callvirt
的虚方法调用的情况下callvirt
。 See my question here . 在这里看我的问题。
I managed to work it out, by discovering the method CallGraph.CallersFor()
. 我设法通过发现
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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.