如何解决为什么我的 Roslyn 分析器不报告警告?
我正在编写一个 Roslyn 分析器来检查 JSON 反序列化的目标类型是否遵循一些规则。本质上,如果表达式 Foo
中出现类型 JsonConvert.DeserializeObject<Foo>
,那么它应该是一个简单的 DTO(默认构造函数,具有 JSON 友好类型的公共属性)。
我已经注册了一个语法节点操作来触发调用表达式。找到合适的调用工作得很好。然后我继续使用语义模型从泛型方法调用中获取类型符号(在本例中为 Foo
)。最后,我使用类型符号对 Foo
类型进行检查。到现在为止还挺好。问题是当我想报告警告时。如果我在对 SyntaxNodeAnalysisContext.ReportDiagnostic
的调用中使用调用表达式的位置,它会起作用:我的警告出现,并且我在调用下得到一个波浪线。但这不是我想要的。我希望波浪线出现在 Foo
的声明中,例如在有问题的属性或非默认构造函数下。但是,这似乎不起作用。警告根本没有出现在警告列表中,也没有波浪线。由于某种原因,报告似乎被忽略或静默失败。
- 直接使用符号的
Locations
:symbol.Locations[0]
- 在源代码树上使用
FindNode
查找符号的SyntaxNode
:symbolLocation.sourceTree?.GetRoot()?.FindNode(symbolLocation.sourceSpan)?.GetLocation()
- 使用
DeclaringSyntaxReferences
:symbol.DeclaringSyntaxReferences[0].GetSyntax().GetLocation()
所有这些方法都会产生一个位置(它不为空)。但是我的警告没有出现。
代码如下:
private void DoAnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
if (invocation.Expression is MemberAccessExpressionSyntax memberAccess)
{
if (memberAccess.Expression is IdentifierNameSyntax typeIdentifierSyntax)
{
var textIdentifierText = typeIdentifierSyntax.Identifier.Text;
if (textIdentifierText == "JsonConvert")
{
if (memberAccess.Name is GenericNameSyntax genericNameSyntax)
{
if (genericNameSyntax.Identifier is SyntaxToken SyntaxToken)
{
if (SyntaxToken.Text == "DeserializeObject")
{
var typeArgs = genericNameSyntax.TypeArgumentList.Arguments;
if (typeArgs.Count == 1)
{
var typeArg = typeArgs[0];
var symbolInfo = context.SemanticModel.GetSymbolInfo(typeArg);
var typeSymbol = (INamedTypeSymbol)symbolInfo.Symbol;
var incompatibilities = VerifyDeserializationType(typeSymbol);
var diagnostics = incompatibilities.Select(it => ToSyntaxNodeAnalysisDiagnostic(it,memberAccess));
if (diagnostics.Any())
{
// This works,and gives an overall warning that the deserialization has problems.
context.ReportDiagnostic(Diagnostic.Create(DeserializeRule,invocation.GetLocation(),typeSymbol.Name));
try
{
foreach (var d in diagnostics)
{
// These don't work,presumably because there is something wrong with the location.
context.ReportDiagnostic(d);
}
}
catch (Exception ex)
{
// This doesn't happen.
context.ReportDiagnostic(Diagnostic.Create(DebugRule,memberAccess.GetLocation(),$"EXCEPTION: {ex.Message}"));
}
}
}
}
}
}
}
}
}
}
private static Diagnostic ToSyntaxNodeAnalysisDiagnostic(Incompatibility incompatibility,SyntaxNode sourceNode)
{
var symbolLocation = incompatibility.Symbol.Locations[0];
var SyntaxRef = incompatibility.Symbol.DeclaringSyntaxReferences[0];
var Syntax = SyntaxRef.GetSyntax();
//var node = symbolLocation.sourceTree?.GetRoot()?.FindNode(symbolLocation.sourceSpan);
var sourceLocation = sourceNode.GetLocation();
if (Syntax == null)
{
return Diagnostic.Create(DebugRule,sourceLocation,"node == null");
}
var location = Syntax.GetLocation();
if (location == null)
{
return Diagnostic.Create(DebugRule,"location == null");
}
if (incompatibility is PropIncompatibility propIncompatibility)
{
return Diagnostic.Create(PropRule,location,propIncompatibility.Symbol.Name,propIncompatibility.Explanation);
}
if (incompatibility is CtorIncompatibility)
{
return Diagnostic.Create(CtorRule,incompatibility.Symbol.ContainingSymbol.Name);
}
return Diagnostic.Create(DebugRule,"Unhandled incompatibility...");
}
欢迎提出任何建议。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。