starlight54
starlight54

Reputation: 1091

How do I get the current value of a given variable name when writing a Roslyn Analyser?

The following code snippet is the code I wish to analyse:

var name = "Michael";
name = "John";
var person = new Person(name);

And let's say my analyser should complain if the length of name given to the constructor of Person is less than 5.

I know how to get the value of a string literal var person = new Person("John") that is passed in to this object creation expression, check the first arguments type and then if it's a string literal grab it's Value property.

But how do I get the analyser to give me the value of name at the Person object creation expression site. This name is clearly well defined in the code, so should be possible in this case.

Thus far I've tried something along the lines of...

var nameExpr = (IdentifierNameSyntax)objectCreation.ArgumentList?.Arguments.First()?.Expression;
var nameDataFlow = context.SemanticModel.AnalyzeDataFlow(nameExpr);

It looks like I can figure out by using this data flow the value of name, but it would seem to involve a very complex and flaky set of code, and would appear to me to only work if the declarations were inside the data flow code block. I'd like it to be able to resolve this token to it's actual value (if possible) even across the global compilation.

Even if I wrote global compilation hooks myself, I'd have to manually track every assignment to the variable (including from other variables and method calls etc.)

Is there an easy way to ask the library to do this for me, and just give me the variable's value at the call site if it can?

Upvotes: 3

Views: 1013

Answers (1)

Matthew
Matthew

Reputation: 29206

Is there an easy way to ask the library to do this for me, and just give me the variable's value at the call site if it can?

No, in fact this is provably impossible for an arbitrary program with arbitrary inputs.

One exception is when the variable is a compile-type constant (const), in which case you can get its value using SemanticModel.GetConstantValue.

I can report on the possible values of it, and if the analysis reaches a certain complexity then I could finally bail on it and say "I don't know" what this variable's value is or could be.

This would be complex for even simple cases. Think about all of the ways that the value could change:

  • The variable could be conditionally assigned to within the code block. How are you going to try to determine whether the condition is true?
  • The variable could be captured in a lambda function. How are you going to analyze the lambda function and its invocations?
  • The variable could be assigned to an expression, which could include calls to other methods, etc. How are you going to determine the value of an arbitrary expression?
  • The value of the variable could depend on data read by your program at runtime. For a simple example, what is the value of DateTime.Now? You can't determine this using static analysis.
  • Many others.

Upvotes: 2

Related Questions