public static MultiDictionary <Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node)
        {
            var emptyStructs = new CaptureWalkerEmptyStructTypeCache();
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs);

            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables);

            bool badRegion = false;

            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            var result = walker.variablesCaptured;


            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                result.Add(method.ThisParameter, node.Syntax);
            }

            foreach (var variable in result.Keys.ToArray()) // take a snapshot, as we are modifying the underlying multidictionary
            {
                var local = variable as LocalSymbol;
                if ((object)local != null && local.RefKind != RefKind.None)
                {
                    walker.AddSpillsForRef(walker.refLocalInitializers[local], result[local]);
                }
            }

            walker.Free();
            return(result);
        }
        public static MultiDictionary<Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node)
        {
            var emptyStructs = new CaptureWalkerEmptyStructTypeCache();
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs);

            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables);

            bool badRegion = false;
            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            var result = walker.variablesCaptured;


            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                result.Add(method.ThisParameter, node.Syntax);
            }

            foreach (var variable in result.Keys.ToArray()) // take a snapshot, as we are modifying the underlying multidictionary
            {
                var local = variable as LocalSymbol;
                if ((object)local != null && local.RefKind != RefKind.None)
                {
                    walker.AddSpillsForRef(walker.refLocalInitializers[local], result[local]);
                }
            }

            walker.Free();
            return result;
        }
 private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, CaptureWalkerEmptyStructTypeCache emptyStructCache, HashSet<Symbol> initiallyAssignedVariables)
     : base(compilation, 
           method, 
           node, 
           emptyStructCache, 
           trackUnassignments: true, 
           initiallyAssignedVariables: initiallyAssignedVariables)
 {
 }
        public static MultiDictionary<Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node)
        {
            var emptyStructs = new CaptureWalkerEmptyStructTypeCache();
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs);

            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables);

            bool badRegion = false;
            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            var result = walker.variablesCaptured;

            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                result.Add(method.ThisParameter, node.Syntax);
            }

            walker.Free();
            return result;
        }
 private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, CaptureWalkerEmptyStructTypeCache emptyStructCache, HashSet <Symbol> initiallyAssignedVariables)
     : base(compilation,
            method,
            node,
            emptyStructCache,
            trackUnassignments: true,
            initiallyAssignedVariables: initiallyAssignedVariables)
 {
 }