Roslyn 分析器:Linq 中的可空注释
Roslyn analyser: Nullable annotations in Linq
我是 Roslyn 的新手,我必须编写一个分析器来帮助改进使用 Linq 时可为空的注释。目标是强制将 .XYZOrDefault() 的任何用法存储在可空类型 variable/property/method 签名中。例如:如果我们使用 "var x = SomeKindOfList.FirstOrDefault()","x" 需要标记为可空。我们将使用 C# 8,所以我指的是 NRT。实现这一目标的想法是:
- 正在确定泛型类型是否在变量中使用或
方法声明
- 使用语义模型判断是否是左手
表达式类型的一侧是可空类型
- 如果表达式的左侧不是可空类型,则生成
诊断
我的编码已经走到这一步了:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
Compilation compilation = context.Compilation;
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
// Find implicitly typed variable declarations.
if (declaration.Type.IsVar)
{
foreach (var variable in declaration.Variables)
{
var variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
var invocationSymbol = context.SemanticModel.GetOperation(variable.Initializer.Value).Type;
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variableSymbol.Locations[0], variableSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
}
我已经阅读了很多关于您在现阶段可以做什么的信息,这是一个信息过载。任何可以给我更多指导的文章、代码片段或建议都将不胜感激!
最后,我们最终编写了自己的分析器作为临时解决方案,直到我们可以迁移到 .Net 5。我们想出的最基本的实现是以下代码:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
foreach (var variable in declaration.Variables)
{
ITypeSymbol? variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
IOperation? invocationOperationInfo = context.SemanticModel.GetOperation(variable.Initializer.Value);
if (invocationOperationInfo is IInvocationOperation op)
{
if (op.TargetMethod.IsGenericMethod)
{
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variable.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
}
希望这可以帮助其他人,他们可能只是在开发类似的东西时寻找一个好的起点。
我是 Roslyn 的新手,我必须编写一个分析器来帮助改进使用 Linq 时可为空的注释。目标是强制将 .XYZOrDefault() 的任何用法存储在可空类型 variable/property/method 签名中。例如:如果我们使用 "var x = SomeKindOfList.FirstOrDefault()","x" 需要标记为可空。我们将使用 C# 8,所以我指的是 NRT。实现这一目标的想法是:
- 正在确定泛型类型是否在变量中使用或 方法声明
- 使用语义模型判断是否是左手 表达式类型的一侧是可空类型
- 如果表达式的左侧不是可空类型,则生成 诊断
我的编码已经走到这一步了:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
Compilation compilation = context.Compilation;
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
// Find implicitly typed variable declarations.
if (declaration.Type.IsVar)
{
foreach (var variable in declaration.Variables)
{
var variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
var invocationSymbol = context.SemanticModel.GetOperation(variable.Initializer.Value).Type;
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variableSymbol.Locations[0], variableSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
}
我已经阅读了很多关于您在现阶段可以做什么的信息,这是一个信息过载。任何可以给我更多指导的文章、代码片段或建议都将不胜感激!
最后,我们最终编写了自己的分析器作为临时解决方案,直到我们可以迁移到 .Net 5。我们想出的最基本的实现是以下代码:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
foreach (var variable in declaration.Variables)
{
ITypeSymbol? variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
IOperation? invocationOperationInfo = context.SemanticModel.GetOperation(variable.Initializer.Value);
if (invocationOperationInfo is IInvocationOperation op)
{
if (op.TargetMethod.IsGenericMethod)
{
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variable.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
}
希望这可以帮助其他人,他们可能只是在开发类似的东西时寻找一个好的起点。