上一篇教程编写StyleCop自定义规则教程(一)---编写中文备注的简单校验规则 中使用的例子是校验代码中所有属性,不区分Public、Internal等。本文沿用原有例子增加两个规则的属性(IncludePublic和InculdeInternal),规则根据这两个属性的开关值,控制是否检查代码中访问权限是Public或Internal的代码。
在规则的xml文件中加入Properties节点
View Code
<Properties>
<BooleanProperty
Name="IncludePublic"
DefaultValue="True"
FriendlyName="包括Pulbic"
Description="代码分析时检验Public属性"
/>
<BooleanProperty
Name="IncludeInternal"
DefaultValue="True"
FriendlyName="包括Internal"
Description="代码分析时检验Internal属性"
/>
</Properties>
<BooleanProperty
Name="IncludePublic"
DefaultValue="True"
FriendlyName="包括Pulbic"
Description="代码分析时检验Public属性"
/>
<BooleanProperty
Name="IncludeInternal"
DefaultValue="True"
FriendlyName="包括Internal"
Description="代码分析时检验Internal属性"
/>
</Properties>
CsDocument 类重载了多个WalkDocument方法,上一篇教程使用的是
WalkDocument(CodeWalkerElementVisitor<object> elementCallback,object context); 最后一个参数传入了空值,本文需要传入属性校验的开关值。因此使用void WalkDocument<T>(CodeWalkerElementVisitor<T> elementCallback, T context),定义一个结构体传入用户配置的值。
View Code
[StructLayout(LayoutKind.Sequential)]
private struct AnalyzerSettings
{
public bool IncludePublic;
public bool IncludeInternal;
}
private AnalyzerSettings LoadSettings(CodeDocument document)
{
AnalyzerSettings result = new AnalyzerSettings();
result.IncludeInternal = true;
result.IncludePublic = true;
if (document.Settings != null)
{
BooleanProperty addInSetting = document.Settings.GetAddInSetting(this, "IncludePublic") as BooleanProperty;
if (addInSetting != null)
{
result.IncludePublic = addInSetting.Value;
}
addInSetting = document.Settings.GetAddInSetting(this, "IncludeInternal") as BooleanProperty;
if (addInSetting != null)
{
result.IncludeInternal = addInSetting.Value;
}
}
return result;
}
private struct AnalyzerSettings
{
public bool IncludePublic;
public bool IncludeInternal;
}
private AnalyzerSettings LoadSettings(CodeDocument document)
{
AnalyzerSettings result = new AnalyzerSettings();
result.IncludeInternal = true;
result.IncludePublic = true;
if (document.Settings != null)
{
BooleanProperty addInSetting = document.Settings.GetAddInSetting(this, "IncludePublic") as BooleanProperty;
if (addInSetting != null)
{
result.IncludePublic = addInSetting.Value;
}
addInSetting = document.Settings.GetAddInSetting(this, "IncludeInternal") as BooleanProperty;
if (addInSetting != null)
{
result.IncludeInternal = addInSetting.Value;
}
}
return result;
}
修改规则子类必须重写的AnalyzeDocument方法
View Code
public override void AnalyzeDocument(CodeDocument document)
{
Param.RequireNotNull(document, "document");
CsDocument document2 = (CsDocument)document;
if ((document2.RootElement != null) && !document2.RootElement.Generated)
{
AnalyzerSettings settings = LoadSettings(document);
document2.WalkDocument<AnalyzerSettings>(new CodeWalkerElementVisitor<AnalyzerSettings>(this.CheckDocumentationForElement), settings);
}
}
{
Param.RequireNotNull(document, "document");
CsDocument document2 = (CsDocument)document;
if ((document2.RootElement != null) && !document2.RootElement.Generated)
{
AnalyzerSettings settings = LoadSettings(document);
document2.WalkDocument<AnalyzerSettings>(new CodeWalkerElementVisitor<AnalyzerSettings>(this.CheckDocumentationForElement), settings);
}
}
原有的CheckDocumentationForElement方法最后一个参数就是传入的配置值,方法根据代码节点的类型和访问权限进行校验
View Code
private bool CheckDocumentationForElement(CsElement element, CsElement parentElement, AnalyzerSettings settings)
{
if (base.Cancel)
{
return false;
}
if (!element.Generated)
{
if ((element.ElementType == ElementType.Property) &&
((settings.IncludePublic && element.AccessModifier == AccessModifierType.Public) ||
(settings.IncludeInternal && element.AccessModifier == AccessModifierType.Internal)))
{
this.ParseHeader(element, element.Header, element.LineNumber, false);
}
}
return true;
}
{
if (base.Cancel)
{
return false;
}
if (!element.Generated)
{
if ((element.ElementType == ElementType.Property) &&
((settings.IncludePublic && element.AccessModifier == AccessModifierType.Public) ||
(settings.IncludeInternal && element.AccessModifier == AccessModifierType.Internal)))
{
this.ParseHeader(element, element.Header, element.LineNumber, false);
}
}
return true;
}
编译后将dll放到stylecop目录,在stylecop settings中选中新的规则,可以在右侧Detailed settings中看到规则的两个开关值。