Is there a way to determine the potential value of a variable using Roslyn?
.net, roslyn
Solution
You could try to use `SemanticModel.AnalyzeRegionDataFlow()` for this. You give it a text span and it tells you information about the dataflow in that piece of text, including what variables are sure to be assigned in the `AlwaysAssigned` property.
The whole code (assuming you have a compilation unit, not just a method) could look like this:
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();
}
For your first method, it correctly detects that `a` wasn't assigned before the first `if`, but is certainly assigned before the second `if`.
For your second method, Roslyn seems to think that `a` doesn't have to be assigned. But that is in line with how the C# compiler behaves. For example, the following method won't compile:
private void BooleanTest(bool b)
{
string a;
if (b)
a = "";
if (!b)
a = "42";
if (a == "")
Console.WriteLine("What Do I Do?");
}
But if you replace the second `if` with `else`, it will compile. And similarly, Roslyn will detect that the variable is always assigned.
Problem
I am using the Roslyn CTP and I am trying to determine if the value of a variable in a class has a value. Lets say I am trying to detect when someone is using a BinaryExpressionSyntax to determine if a string is equal to nothing "". For example: ``` 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"); } } ``` I can get the BinaryExpressionSyntax and examine both the left and right sides using Semantic and Syntax but I don't see anything in the debugger that tracks the possible value. I know this could get sketchy e.g.: ``` 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?"); } } ``` Is it possible with the Roslyn CTP to determine if a potential value has been set on a variable? I would think that this would come into play a lot in the StyleCOp/FxCop rules.