roslyn分析器必须在语义模型就绪后才能获取符号信息,registersemanticmodelaction是唯一安全入口;语法节点分析无法获取类型信息,且需显式判空、配置构建管道与vsix兼容性。

Roslyn 分析器不是“写个正则找 if 里写了 null”就能上线的东西;它必须在语义就绪后才能判断类型、符号、调用链,否则 GetSymbolInfo() 和 GetTypeInfo() 全是 null,诊断永远不触发。
RegisterSemanticModelAction 是语义分析的唯一入口
很多新手在 RegisterSyntaxNodeAction<binaryexpressionsyntax></binaryexpressionsyntax> 里直接调 semanticModel.GetSymbolInfo(node),结果始终返回 null——因为此时 SemanticModel 还没构造完成,语法节点虽已解析,但类型绑定尚未发生。
正确做法只有一处:必须用 context.RegisterSemanticModelAction() 注册回调,在该回调中才可安全使用 semanticModel。
-
RegisterSyntaxNodeAction只能做纯语法层面的事,比如检查节点结构、文本内容、是否含特定关键字 -
RegisterSemanticModelAction才能拿到完整语义模型,进而查ISymbol、ITypeSymbol、调用链、泛型实参等 - 若需同时响应语法结构 + 语义信息(如检测某个方法调用是否传了非字符串字面量),得注册两个 action,并靠
AnalysisContext.Options或自定义上下文缓存共享状态
获取 Symbol 时必须逐层判空,不能链式调用
semanticModel.GetSymbolInfo(expression).Symbol?.ContainingType?.SpecialType 看起来简洁,但在用户编辑中途(如刚敲完 str. 还没输方法名)会直接抛 NullReferenceException,导致整个分析器崩溃静默失效。
Roslyn 明确要求所有语义查询结果都视为可能为 null,尤其在 IDE 实时分析场景下。
- 必须拆解判断:
var symbol = semanticModel.GetSymbolInfo(node).Symbol;→ 检查symbol != null→ 再取symbol.ContainingType→ 再判空 → 最后比SpecialType - 对泛型类型(如
List<string></string>),SpecialType是None,得改用symbol.Type?.IsString()或symbol.Type?.ToString() == "string"(后者慎用于泛型上下文) - C# 8+ 推荐用空合并与模式匹配组合:
if (symbol is { ContainingType.SpecialType: SpecialType.System_String }),但注意这仍会触发ContainingType的 getter,内部可能 throw,所以最稳仍是显式判空
dotnet build 不报错?你没让分析器进编译管道
本地 VS 里灯泡亮、波浪线有,但 dotnet build 或 CI 流水线完全没警告——这是最常被忽略的部署盲点。
Roslyn 分析器默认只在 Visual Studio 设计时启用,dotnet build 默认跳过所有 analyzer,除非显式开启。
- 必须在项目文件(
.csproj)中添加:<enablenetanalyzers>true</enablenetanalyzers> - 若引用的是第三方 analyzer NuGet 包(如
SonarAnalyzer.CSharp),还需确认其PrivateAssets="all"没误锁住分析器资产 - 旧项目(TargetFramework 小于
net5.0)需额外加<analysismode>AllEnabledByDefault</analysismode>,否则即使启用也只跑极少数规则 - CI 中建议加
/p:AnalysisLevel=latest防止因 SDK 版本差异漏规则
调试时实验实例不加载你的 Analyzer?检查 VSIX 清单和目标框架
F5 启动实验实例后,测试项目里完全看不到波浪线或灯泡——大概率是 VSIX 清单没配对,或目标框架不兼容。
模板生成的 .vsixmanifest 默认声明支持 [17.0,18.0),但如果你用的是 VS 2022 17.12 或 VS 2026 预览版,版本范围不匹配就会静默禁用。
- 打开
source.extension.vsixmanifest,检查<installationtarget></installationtarget>的Version是否覆盖当前 VS 版本(可用devenv /rootsuffix Exp查实验实例版本) - Analyzer 项目目标框架必须是
netstandard2.0或更高(net6.0也可,但会限制 VS 版本兼容性);netstandard1.3已被 VS 2022+ 拒绝加载 - 确保
Microsoft.CodeAnalysis.CSharp和Microsoft.VisualStudio.LanguageServices版本与当前 VS SDK 匹配;混用 4.x 和 5.x 的 Roslyn 包会导致AssemblyLoadException
真正卡住人的从来不是“怎么写一个诊断”,而是“为什么它在某个环节突然不工作”——语义时机、判空逻辑、构建管道开关、VSIX 兼容性,四者任一出错,分析器就变成不可见的幽灵。











