/// <summary> /// Rewrite an async method into a state machine type. /// </summary> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, int methodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics, out AsyncStateMachine stateMachineType) { if (!method.IsAsync) { stateMachineType = null; return(body); } // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class. var typeKind = compilationState.Compilation.Options.EnableEditAndContinue ? TypeKind.Class : TypeKind.Struct; var bodyWithAwaitLifted = AwaitExpressionSpiller.Rewrite(body, method, compilationState, diagnostics); stateMachineType = new AsyncStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, typeKind); compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType); var rewriter = new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics); if (!rewriter._constructedSuccessfully) { return(body); } return(rewriter.Rewrite()); }
/// <summary> /// Rewrite an async method into a state machine type. /// </summary> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, int methodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics, out AsyncStateMachine stateMachineType) { if (!method.IsAsync) { stateMachineType = null; return body; } // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class. var typeKind = compilationState.Compilation.Options.EnableEditAndContinue ? TypeKind.Class : TypeKind.Struct; var bodyWithAwaitLifted = AwaitExpressionSpiller.Rewrite(body, method, compilationState, diagnostics); stateMachineType = new AsyncStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, typeKind); compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType); var rewriter = new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics); if (!rewriter.VerifyPresenceOfRequiredAPIs()) { return body; } return rewriter.Rewrite(); }
/// <summary> /// Rewrite an async method into a state machine class. /// </summary> /// <param name="body">The original body of the method</param> /// <param name="method">The method's identity</param> /// <param name="compilationState">The collection of generated methods that result from this transformation and which must be emitted</param> /// <param name="diagnostics">Diagnostic bag for diagnostics.</param> /// <param name="generateDebugInfo"></param> /// <param name="stateMachineType"></param> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo, out AsyncStateMachine stateMachineType) { if (!method.IsAsync) { stateMachineType = null; return body; } // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class. var typeKind = compilationState.Compilation.Options.EnableEditAndContinue ? TypeKind.Class : TypeKind.Struct; var bodyWithAwaitLifted = AwaitLiftingRewriter.Rewrite(body, method, compilationState, diagnostics); stateMachineType = new AsyncStateMachine(method, typeKind); compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType); var rewriter = new AsyncRewriter(bodyWithAwaitLifted, method, stateMachineType, compilationState, diagnostics, generateDebugInfo); if (!rewriter.constructedSuccessfully) { return body; } return rewriter.Rewrite(); }
/// <summary> /// Rewrite an async method into a state machine type. /// </summary> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, int methodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics, out AsyncStateMachine stateMachineType) { if (!method.IsAsync) { stateMachineType = null; return(body); } CSharpCompilation compilation = method.DeclaringCompilation; bool isAsyncEnumerableOrEnumerator = method.IsIAsyncEnumerableReturningAsync(compilation) || method.IsIAsyncEnumeratorReturningAsync(compilation); if (isAsyncEnumerableOrEnumerator && !method.IsIterator) { bool containsAwait = AwaitDetector.ContainsAwait(body); diagnostics.Add(containsAwait ? ErrorCode.ERR_PossibleAsyncIteratorWithoutYield : ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait, method.Locations[0], method.ReturnType); stateMachineType = null; return(body); } // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class. // For async-iterators, we also need to generate a class. var typeKind = (compilationState.Compilation.Options.EnableEditAndContinue || method.IsIterator) ? TypeKind.Class : TypeKind.Struct; var bodyWithAwaitLifted = AwaitExpressionSpiller.Rewrite(body, method, compilationState, diagnostics); stateMachineType = new AsyncStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, typeKind); compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType); AsyncRewriter rewriter = isAsyncEnumerableOrEnumerator ? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics) : new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics); if (!rewriter.VerifyPresenceOfRequiredAPIs()) { return(body); } try { return(rewriter.Rewrite()); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); return(new BoundBadStatement(body.Syntax, ImmutableArray.Create <BoundNode>(body), hasErrors: true)); } }
/// <summary> /// Rewrite an async method into a state machine type. /// </summary> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, int methodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics, out AsyncStateMachine stateMachineType) { if (!method.IsAsync) { stateMachineType = null; return(body); } // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class. var typeKind = compilationState.Compilation.Options.EnableEditAndContinue ? TypeKind.Class : TypeKind.Struct; var bodyWithAwaitLifted = AwaitExpressionSpiller.Rewrite(body, method, compilationState, diagnostics); stateMachineType = new AsyncStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, typeKind); compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType); var rewriter = new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics); if (!rewriter.VerifyPresenceOfRequiredAPIs()) { return(body); } try { return(rewriter.Rewrite()); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); return(new BoundBadStatement(body.Syntax, ImmutableArray.Create <BoundNode>(body), hasErrors: true)); } }
/// <summary> /// Rewrite an async method into a state machine class. /// </summary> /// <param name="body">The original body of the method</param> /// <param name="method">The method's identity</param> /// <param name="compilationState">The collection of generated methods that result from this transformation and which must be emitted</param> /// <param name="diagnostics">Diagnostic bag for diagnostics.</param> /// <param name="generateDebugInfo"></param> internal static BoundStatement Rewrite( BoundStatement body, MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo) { if (!method.IsAsync) { return body; } var bodyWithAwaitLifted = AwaitLiftingRewriter.Rewrite(body, method, compilationState, diagnostics); var rewriter = new AsyncRewriter(bodyWithAwaitLifted, method, ((SourceMethodSymbol)method).AsyncStateMachineType, compilationState, diagnostics, generateDebugInfo); if (!rewriter.constructedSuccessfully) { return body; } var bodyReplacement = rewriter.Rewrite(); return bodyReplacement; }