上一篇教程编写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中看到规则的两个开关值。