作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 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");
}
}
我可以获取 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?");
}
}
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();
}
对于您的第一个方法,它正确检测到 a
未在第一个 if
之前分配,但肯定在第二个 if
之前分配>.
对于你的第二种方法,Roslyn 似乎认为不必分配 a
。但这与 C# 编译器的行为方式一致。例如,以下方法将无法编译:
private void BooleanTest(bool b)
{
string a;
if (b)
a = "";
if (!b)
a = "42";
if (a == "")
Console.WriteLine("What Do I Do?");
}
但是如果将第二个 if
替换为 else
,它将编译。同样,Roslyn 会检测到该变量始终被赋值。
关于.net - 有没有办法使用 Roslyn 确定变量的潜在值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10130502/
我是一名优秀的程序员,十分优秀!