我正在使用Roslyn CTP,并且试图确定类中变量的值是否具有值。可以说我正在尝试检测某人何时使用BinaryExpressionSyntax来确定字符串是否等于“”。
例如:
private void StringLiteral(string a)
{
if (a == "") //flagged because we do not see a explicit set of 'a'
{
Console.WriteLine("Empty String");
}
a="42";
if (a == "") //not flagged because 'a' has been set
{
Console.WriteLine("Empty String");
}
}
Run Code Online (Sandbox Code Playgroud)
我可以获取BinaryExpressionSyntax并使用语义和语法检查左侧和右侧,但是在调试器中看不到任何跟踪可能值的内容。我知道这可能会很简单,例如:
private void BooleanTest(string a, bool b)
{
if (b)
{
a="";
}
if (!b)
{
a="42";
}
if (a == "") // Maybe 'a' is set maybe it isn't so we will probably not flag this one
{
Console.WriteLine("What Do I Do?");
}
}
Run Code Online (Sandbox Code Playgroud)
Roslyn CTP是否可以确定是否在变量上设置了潜在值?我认为这将在StyleCOp / FxCop规则中发挥很大作用。
您可以尝试使用SemanticModel.AnalyzeRegionDataFlow()此功能。您给它一个文本范围,它会告诉您有关该文本片段中的数据流的信息,包括确定在属性中分配哪些变量AlwaysAssigned。
整个代码(假设您有一个编译单元,而不仅仅是一个方法)可能如下所示:
var tree = SyntaxTree.ParseCompilationUnit(code);
var compilation = Compilation.Create("foo")
.AddSyntaxTrees(tree);
var semanticModel = compilation.GetSemanticModel(tree);
var methods = tree.Root.DescendentNodes().OfType<MethodDeclarationSyntax>();
foreach (var method in methods)
{
Console.WriteLine(method.Identifier.ValueText);
var binaryExpressions = method.DescendentNodes()
.OfType<BinaryExpressionSyntax>()
.Where(e => e.Kind == SyntaxKind.EqualsExpression);
foreach (var binaryExpression in binaryExpressions)
{
Console.WriteLine(binaryExpression);
// get TextSpan that starts at the beginning of the method body
// and ends at the beginning of the binary expression
var textBefore = TextSpan.FromBounds(
method.BodyOpt.Span.Start, binaryExpression.Span.Start);
//Console.WriteLine(tree.Root.GetFullTextAsIText().GetText(textBefore));
var alwaysAssigned = semanticModel.AnalyzeRegionDataFlow(textBefore)
.AlwaysAssigned;
var isAAlwaysAssigned = alwaysAssigned.Any(s => s.Name == "a");
Console.WriteLine(isAAlwaysAssigned);
}
Console.WriteLine();
}
Run Code Online (Sandbox Code Playgroud)
对于您的第一个方法,它正确地检测到a在第一个之前没有分配if,但肯定在第二个之前分配if。
对于你的第二种方法,罗斯林似乎认为a不必分配。但这与 C# 编译器的行为方式一致。例如,以下方法将无法编译:
private void BooleanTest(bool b)
{
string a;
if (b)
a = "";
if (!b)
a = "42";
if (a == "")
Console.WriteLine("What Do I Do?");
}
Run Code Online (Sandbox Code Playgroud)
但如果你用 替换第二个if,else它就会编译。同样,Roslyn 会检测到该变量始终被赋值。
| 归档时间: |
|
| 查看次数: |
601 次 |
| 最近记录: |