简体   繁体   中英

How to detect closures in code with Roslyn?

Can I detect (using roslyn) that x reference in the lambda body is closure over outer variable x , not some variable local to lambda itself?

var x = "foo";
var a = string[0];
a.Any(i => i == x);

Yup. You can use the DataFlowAnalysis API.

var tree = CSharpSyntaxTree.ParseText(
    @"
class C{
void M(){
    var x = ""foo"";
    var a = new string[0];
    var testing = a.Any(i => i == x);
}
} 
");
var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
    syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);

var lambda = tree.GetRoot().DescendantNodes().OfType<LocalDeclarationStatementSyntax>().Last();

var dataFlowAnalysis = model.AnalyzeDataFlow(lambda);
var capturedVariables = dataFlowAnalysis.Captured;

foreach(var variable in capturedVariables)
{
    //Do something
}

https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/blob/master/ClrHeapAllocationsAnalyzer/DisplayClassAllocationAnalyzer.cs#L58

(1) Get Semantic Model

(2) Check for AnonymousMethodExpressionSyntax / SimpleLambdaExpressionSyntax / ParenthesizedLambdaExpressionSyntax

(3) Pass that node to AnalyzeDataFlow extension method on the SemanticModel

(4) Iterate over the .Captured property

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM