我怎样才能访问 Roslyn 中的 return 项?
How can I have access to return item in Roslyn?
在开发自定义独立代码分析以帮助开发人员根据 VS 中的最佳实践编写 C# 代码时,我们正在使用 Roslyn 及其功能。
我们的一个要求有点棘手,我们需要解析和编译一个有如下概念问题的方法:
var myVariable = SomeExpression...;
return myVariable;
这意味着如果定义了一个变量,然后立即return编辑并且不再使用,[GCop][1]应该警告开发人员并说变量声明是不必要的。
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
if (varDeclareSyntax == null) return;
var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (variableDeclare == null) return;
var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
if (varDeclarator == null) return;
var identifierToken = varDeclarator.Identifier.Text;
var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();
var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);
/// ??????? TO DO :
现在我们可以访问节点 => (var item = 10;
)
问题是我们如何才能准确访问下一行
return item;
我找到了 myVariable Syntax 节点及其值,但我不知道如何找到 return Identider excatly
LocalDeclarationStatement 包含在一个更大的语法节点中,并且是 ReturnStatementSyntax.
的兄弟节点 您的分析真的不应该从 LocalDeclarationStatement 开始——从 BlockSyntax 或其他东西开始,然后寻找声明和 returns 从那里。
尝试此操作的另一种方法是首先开始查找 ReturnStatementSyntax ,一旦您看到它是一个简单变量的 return,您就可以调用 SemanticModel.GetSymbolInfo() 找到符号,然后从该符号转到定义它的语法。从那里你可以看到它们是否并排。
希望完成...这是我的代码
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
if (varDeclareSyntax == null) return;
var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (variableDeclare == null) return;
var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
if (varDeclarator == null) return;
//var identifierToken = varDeclarator.Identifier.Text; // <- here we find [item] in ( var item=expression; )
var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();
var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);
var allNodes = method.DescendantNodes().OfType<CSharpSyntaxNode>().Select((node, index) => new Node
{
Index = index,
Syntax = node,
Location = node.GetLocation(),
Kind = node.Kind(),
Ancestors = node.Ancestors()
}).ToArray();
var maxIndex = allNodes.Where(it => it.Ancestors.Any(x => x == varDeclarator)).Max(it => it.Index.Value);
if (maxIndex >= allNodes.Length) return;
var nextReturn = allNodes[maxIndex + 1];
if (nextReturn.Kind != SyntaxKind.ReturnStatement) return;
var @return = nextReturn.Syntax as ReturnStatementSyntax;
if ((@return.Expression as IdentifierNameSyntax)?.Identifier.ValueText == varDeclarator.Identifier.ValueText)
{
ReportDiagnostic(context, varDeclareSyntax);
}
}
protected override RuleDescription GetDescription()
{
return new RuleDescription
{
ID = "176",
Category = Category.Design,
Message = "Variable declaration is unnecessary due to it used only for return statement"
};
}
private class Node : NodeDefinition
{
public IEnumerable<SyntaxNode> Ancestors { get; set; }
public SyntaxNode Syntax { get; set; }
public SyntaxKind Kind { get; set; }
}
在开发自定义独立代码分析以帮助开发人员根据 VS 中的最佳实践编写 C# 代码时,我们正在使用 Roslyn 及其功能。
我们的一个要求有点棘手,我们需要解析和编译一个有如下概念问题的方法:
var myVariable = SomeExpression...;
return myVariable;
这意味着如果定义了一个变量,然后立即return编辑并且不再使用,[GCop][1]应该警告开发人员并说变量声明是不必要的。
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
if (varDeclareSyntax == null) return;
var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (variableDeclare == null) return;
var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
if (varDeclarator == null) return;
var identifierToken = varDeclarator.Identifier.Text;
var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();
var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);
/// ??????? TO DO :
现在我们可以访问节点 => (var item = 10;
)
问题是我们如何才能准确访问下一行
return item;
我找到了 myVariable Syntax 节点及其值,但我不知道如何找到 return Identider excatly
LocalDeclarationStatement 包含在一个更大的语法节点中,并且是 ReturnStatementSyntax.
的兄弟节点 您的分析真的不应该从 LocalDeclarationStatement 开始——从 BlockSyntax 或其他东西开始,然后寻找声明和 returns 从那里。
尝试此操作的另一种方法是首先开始查找 ReturnStatementSyntax ,一旦您看到它是一个简单变量的 return,您就可以调用 SemanticModel.GetSymbolInfo() 找到符号,然后从该符号转到定义它的语法。从那里你可以看到它们是否并排。
希望完成...这是我的代码
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
if (varDeclareSyntax == null) return;
var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
if (variableDeclare == null) return;
var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
if (varDeclarator == null) return;
//var identifierToken = varDeclarator.Identifier.Text; // <- here we find [item] in ( var item=expression; )
var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();
var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);
var allNodes = method.DescendantNodes().OfType<CSharpSyntaxNode>().Select((node, index) => new Node
{
Index = index,
Syntax = node,
Location = node.GetLocation(),
Kind = node.Kind(),
Ancestors = node.Ancestors()
}).ToArray();
var maxIndex = allNodes.Where(it => it.Ancestors.Any(x => x == varDeclarator)).Max(it => it.Index.Value);
if (maxIndex >= allNodes.Length) return;
var nextReturn = allNodes[maxIndex + 1];
if (nextReturn.Kind != SyntaxKind.ReturnStatement) return;
var @return = nextReturn.Syntax as ReturnStatementSyntax;
if ((@return.Expression as IdentifierNameSyntax)?.Identifier.ValueText == varDeclarator.Identifier.ValueText)
{
ReportDiagnostic(context, varDeclareSyntax);
}
}
protected override RuleDescription GetDescription()
{
return new RuleDescription
{
ID = "176",
Category = Category.Design,
Message = "Variable declaration is unnecessary due to it used only for return statement"
};
}
private class Node : NodeDefinition
{
public IEnumerable<SyntaxNode> Ancestors { get; set; }
public SyntaxNode Syntax { get; set; }
public SyntaxKind Kind { get; set; }
}