XiHan.Framework.Kernel.Analyzers
Roslyn 分析器:把公开 API 的稳定性标注、类型命名与 Ring 0/1 零反射这些规则交给编译器执行,诊断 XH0001–XH0005 全部是错误级。框架的每个正式包都以分析器形式引用它;写框架扩展包的人可以在自己的项目里启用同一套规则。
| 项 | 内容 |
|---|---|
| 包 ID | XiHan.Framework.Kernel.Analyzers |
| 环层 | 工具链 |
| 能力 | — |
| 特性入口 | —(分析器 PublicTypeAnalyzer、InternalApiUsageAnalyzer、ReflectionUsageAnalyzer) |
| 配置节 | —(范围由 MSBuild 属性 XiHanFrameworkPackage、XiHanRing 控制) |
| 依赖 | 只在构建期使用 Microsoft.CodeAnalysis.CSharp;目标 netstandard2.0,开发依赖,不进入运行时 |
| AOT | 不适用(编译期组件) |
| 稳定性 | —(编译期组件,不标注 [ApiLevel];五条规则可用) |
概述
| 规则 | 范围 | 含义 | 消息 |
|---|---|---|---|
XH0001 | 框架包 | 公开类型必须标注 [ApiLevel] | Public type '{0}' must be annotated with [ApiLevel] |
XH0002 | 框架包 | 公开类型名不得以 XiHan 开头:归属由命名空间表达 | Type name '{0}' must not start with 'XiHan' because the namespace already identifies ownership |
XH0003 | 所有引用了分析器的项目 | 不得在定义程序集之外使用标注为 Stability.Internal 的类型或成员 | '{0}' is annotated with Internal stability and must not be used outside its own assembly |
XH0004 | 框架包 | 公开类型名不得用禁用词:Default 前缀,Manager、Helper、Utils、Util、Common、Shared、Impl、Base 后缀 | Type name '{0}' uses the forbidden word '{1}' |
XH0005 | Ring 0/1 | 不得使用反射 API | '{0}' is a reflection API, which is forbidden in the primitives and kernel rings |
全部规则的类别是 XiHan、级别 Error,帮助链接指向本包 README 的规则表。判定细节:
- XH0001 / XH0002 / XH0004 只看「有效公开」的类型(自身与全部包含类型都是
public),跳过编译器生成的类型;编译里找不到ApiLevelAttribute(没引用原语层)时不报 XH0001。名字恰好等于禁用词本身(如Base)不算;一个类型只报一次 XH0004。 - XH0003 按
[ApiLevel]构造参数的整数值判定Internal(Stability.Internal = 3),以成员的原始定义判定,泛型实例化后仍能命中;类型或其任一包含类型标为 Internal 时,类型名出现在源码里也报。程序集内部可以用自己的 Internal API。 - XH0005 把
System.Reflection命名空间下的一切视为反射,只放行MemberInfo上的Name、DeclaringType、ReflectedType、MemberType、MetadataToken、IsCollectible;Activator的任何成员都是反射;Type上的成员查找(GetMethod、GetProperty、GetCustomAttributes、MakeGenericType、Assembly等,以及带参数的Type.GetType(string))是反射,object.GetType()不是。
何时使用
- 向框架仓库提交正式包:已由
framework/src/Directory.Build.props统一引用并设置XiHanFrameworkPackage=true,不需要再做什么。 - 自己维护框架扩展包,想遵守同样的命名与稳定性规则:按下文启用。
- 应用想在编译期挡住对 Internal API 的使用:只引用分析器即可得到 XH0003,命名规则不会作用于应用代码。
安装与启用
bash
dotnet add package XiHan.Framework.Kernel.Analyzers --prerelease当前是预览版,安装要带 --prerelease;从源码或本地包源引用见快速上手。框架包对分析器的引用带 PrivateAssets="all",不会传递给应用;应用要用 XH0003 时自己引用。
框架包规则与零反射规则只在对应的 MSBuild 属性存在时生效。分析器经 build_property.* 读取它们,属性必须声明为编译器可见:包里带的 buildTransitive/XiHan.Framework.Kernel.Analyzers.props 已把 XiHanFrameworkPackage 与 XiHanRing 声明为 CompilerVisibleProperty,以包引用分析器的项目只需设置属性(框架仓库内以项目引用分析器,由 framework/src/Directory.Build.props 声明同样的两项):
xml
<PropertyGroup>
<!-- 启用 XH0001 / XH0002 / XH0004 -->
<XiHanFrameworkPackage>true</XiHanFrameworkPackage>
</PropertyGroup>XiHanRing 只有原语层(0)与内核(1)设置,用来启用 XH0005;更高环层允许反射,例如 Plugins.InProcess 在标注 RequiresDynamicCode 后使用。
配置
| MSBuild 属性 | 值 | 作用 |
|---|---|---|
XiHanFrameworkPackage | true(不区分大小写) | 启用 XH0001、XH0002、XH0004 |
XiHanRing | 0 或 1 | 启用 XH0005;未设置或不是整数视为不在 Ring 0/1 |
主要类型
| 类型 | 说明 |
|---|---|
PublicTypeAnalyzer | XH0001、XH0002、XH0004 |
InternalApiUsageAnalyzer | XH0003 |
ReflectionUsageAnalyzer | XH0005 |
使用示例
在设置了 XiHanFrameworkPackage=true 的扩展包里:
csharp
using XiHan.Framework.Primitives;
namespace Contoso.Reports;
// 通过:标注了稳定性,名字不带前缀与禁用词
[ApiLevel(Stability.Preview, "1.0")]
public sealed class ReportWriter;
// XH0001:缺少 [ApiLevel]
public sealed class ReportExporter;
// XH0004:禁用后缀 Manager
[ApiLevel(Stability.Preview, "1.0")]
public sealed class ReportManager;
// XH0004:Default 前缀;默认实现的角色写在清单的 role: default,不进类型名
[ApiLevel(Stability.Preview, "1.0")]
public sealed class DefaultReportStore;行为与限制
- 全部规则是 Error 级。框架仓库把警告也当错误(
TreatWarningsAsErrors),也不允许以NoWarn关掉这些诊断。 - 分析器只检查源码里的声明与调用,不检查经反射或动态代码间接触达的 API。
- 规则的单元测试在
framework/test/XiHan.Framework.Kernel.Analyzers.Tests,覆盖每条规则的报出与不报出两侧。同一测试项目核对包里带的 props:声明的属性与分析器实际读取的一致、打进buildTransitive/。
