PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs

https://gitlab.com/sharadag/Roslyn
C# | 245 lines | 166 code | 36 blank | 43 comment | 13 complexity | 570810ba58a16b30b838dcbc4c36367d MD5 | raw file
  1. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  2. using System.Linq;
  3. using Microsoft.CodeAnalysis.CSharp.Symbols;
  4. using Roslyn.Utilities;
  5. namespace Microsoft.CodeAnalysis.CSharp
  6. {
  7. /// <summary>
  8. /// Async methods have both a return type (void, Task, or Task&lt;T&gt;) and a 'result' type, which is the
  9. /// operand type of any return expressions in the async method. The result type is void in the case of
  10. /// Task-returning and void-returning async methods, and T in the case of Task&lt;T&gt;-returning async
  11. /// methods.
  12. ///
  13. /// System.Runtime.CompilerServices provides a collection of async method builders that are used in the
  14. /// generated code of async methods to create and manipulate the async method's task. There are three
  15. /// distinct async method builder types, one of each async return type: AsyncVoidMethodBuilder,
  16. /// AsyncTaskMethodBuilder, and AsyncTaskMethodBuilder&lt;T&gt;.
  17. ///
  18. /// AsyncMethodBuilderMemberCollection provides a common mechanism for accessing the well-known members of
  19. /// each async method builder type. This avoids having to inspect the return style of the current async method
  20. /// to pick the right async method builder member during async rewriting.
  21. /// </summary>
  22. internal struct AsyncMethodBuilderMemberCollection
  23. {
  24. /// <summary>
  25. /// The builder's constructed type.
  26. /// </summary>
  27. internal readonly NamedTypeSymbol BuilderType;
  28. /// <summary>
  29. /// The result type of the constructed task: T for Task&lt;T&gt;, void otherwise.
  30. /// </summary>
  31. internal readonly TypeSymbol ResultType;
  32. /// <summary>
  33. /// Binds an exception to the method builder.
  34. /// </summary>
  35. internal readonly MethodSymbol SetException;
  36. /// <summary>
  37. /// Marks the method builder as successfully completed, and sets the result if method is Task&lt;T&gt;-returning.
  38. /// </summary>
  39. internal readonly MethodSymbol SetResult;
  40. /// <summary>
  41. /// Schedules the state machine to proceed to the next action when the specified awaiter completes.
  42. /// </summary>
  43. internal readonly MethodSymbol AwaitOnCompleted;
  44. /// <summary>
  45. /// Schedules the state machine to proceed to the next action when the specified awaiter completes. This method can be called from partially trusted code.
  46. /// </summary>
  47. internal readonly MethodSymbol AwaitUnsafeOnCompleted;
  48. /// <summary>
  49. /// Begins running the builder with the associated state machine.
  50. /// </summary>
  51. internal readonly MethodSymbol Start;
  52. /// <summary>
  53. /// Associates the builder with the specified state machine.
  54. /// </summary>
  55. internal readonly MethodSymbol SetStateMachine;
  56. /// <summary>
  57. /// Get the constructed task for a Task-returning or Task&lt;T&gt;-returning async method.
  58. /// </summary>
  59. internal readonly PropertySymbol Task;
  60. internal AsyncMethodBuilderMemberCollection(
  61. NamedTypeSymbol builderType,
  62. TypeSymbol resultType,
  63. MethodSymbol setException,
  64. MethodSymbol setResult,
  65. MethodSymbol awaitOnCompleted,
  66. MethodSymbol awaitUnsafeOnCompleted,
  67. MethodSymbol start,
  68. MethodSymbol setStateMachine,
  69. PropertySymbol task)
  70. {
  71. BuilderType = builderType;
  72. ResultType = resultType;
  73. SetException = setException;
  74. SetResult = setResult;
  75. AwaitOnCompleted = awaitOnCompleted;
  76. AwaitUnsafeOnCompleted = awaitUnsafeOnCompleted;
  77. Start = start;
  78. SetStateMachine = setStateMachine;
  79. Task = task;
  80. }
  81. internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection)
  82. {
  83. if (method.IsVoidReturningAsync())
  84. {
  85. return TryCreate(
  86. F: F,
  87. builderType: F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder),
  88. resultType: F.SpecialType(SpecialType.System_Void),
  89. setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException,
  90. setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult,
  91. awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted,
  92. awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted,
  93. start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T,
  94. setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine,
  95. task: null,
  96. collection: out collection);
  97. }
  98. if (method.IsTaskReturningAsync(F.Compilation))
  99. {
  100. NamedTypeSymbol builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder);
  101. PropertySymbol task;
  102. if (!TryGetWellKnownPropertyAsMember(F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task, builderType, out task))
  103. {
  104. collection = default(AsyncMethodBuilderMemberCollection);
  105. return false;
  106. }
  107. return TryCreate(
  108. F: F,
  109. builderType: F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder),
  110. resultType: F.SpecialType(SpecialType.System_Void),
  111. setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException,
  112. setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult,
  113. awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted,
  114. awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted,
  115. start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T,
  116. setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine,
  117. task: task,
  118. collection: out collection);
  119. }
  120. if (method.IsGenericTaskReturningAsync(F.Compilation))
  121. {
  122. TypeSymbol resultType = method.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics().Single();
  123. if (resultType.IsDynamic())
  124. {
  125. resultType = F.SpecialType(SpecialType.System_Object);
  126. }
  127. if (typeMap != null)
  128. {
  129. resultType = typeMap.SubstituteType(resultType).Type;
  130. }
  131. NamedTypeSymbol builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T).Construct(resultType);
  132. PropertySymbol task;
  133. if (!TryGetWellKnownPropertyAsMember(F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task, builderType, out task))
  134. {
  135. collection = default(AsyncMethodBuilderMemberCollection);
  136. return false;
  137. }
  138. return TryCreate(
  139. F: F,
  140. builderType: builderType,
  141. resultType: resultType,
  142. setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException,
  143. setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult,
  144. awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted,
  145. awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted,
  146. start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T,
  147. setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine,
  148. task: task,
  149. collection: out collection);
  150. }
  151. throw ExceptionUtilities.UnexpectedValue(method);
  152. }
  153. private static bool TryCreate(
  154. SyntheticBoundNodeFactory F,
  155. NamedTypeSymbol builderType,
  156. TypeSymbol resultType,
  157. WellKnownMember setException,
  158. WellKnownMember setResult,
  159. WellKnownMember awaitOnCompleted,
  160. WellKnownMember awaitUnsafeOnCompleted,
  161. WellKnownMember start,
  162. WellKnownMember setStateMachine,
  163. PropertySymbol task,
  164. out AsyncMethodBuilderMemberCollection collection)
  165. {
  166. MethodSymbol setExceptionMethod;
  167. MethodSymbol setResultMethod;
  168. MethodSymbol awaitOnCompletedMethod;
  169. MethodSymbol awaitUnsafeOnCompletedMethod;
  170. MethodSymbol startMethod;
  171. MethodSymbol setStateMachineMethod;
  172. if (TryGetWellKnownMethodAsMember(F, setException, builderType, out setExceptionMethod) &&
  173. TryGetWellKnownMethodAsMember(F, setResult, builderType, out setResultMethod) &&
  174. TryGetWellKnownMethodAsMember(F, awaitOnCompleted, builderType, out awaitOnCompletedMethod) &&
  175. TryGetWellKnownMethodAsMember(F, awaitUnsafeOnCompleted, builderType, out awaitUnsafeOnCompletedMethod) &&
  176. TryGetWellKnownMethodAsMember(F, start, builderType, out startMethod) &&
  177. TryGetWellKnownMethodAsMember(F, setStateMachine, builderType, out setStateMachineMethod))
  178. {
  179. collection = new AsyncMethodBuilderMemberCollection(
  180. builderType,
  181. resultType,
  182. setExceptionMethod,
  183. setResultMethod,
  184. awaitOnCompletedMethod,
  185. awaitUnsafeOnCompletedMethod,
  186. startMethod,
  187. setStateMachineMethod,
  188. task);
  189. return true;
  190. }
  191. collection = default(AsyncMethodBuilderMemberCollection);
  192. return false;
  193. }
  194. private static bool TryGetWellKnownMethodAsMember(SyntheticBoundNodeFactory F, WellKnownMember wellKnownMethod, NamedTypeSymbol containingType, out MethodSymbol methodSymbol)
  195. {
  196. methodSymbol = F.WellKnownMember(wellKnownMethod) as MethodSymbol;
  197. if ((object)methodSymbol == null) return false;
  198. methodSymbol = methodSymbol.AsMember(containingType);
  199. return true;
  200. }
  201. private static bool TryGetWellKnownPropertyAsMember(SyntheticBoundNodeFactory F, WellKnownMember wellKnownProperty, NamedTypeSymbol containingType, out PropertySymbol propertySymbol)
  202. {
  203. propertySymbol = F.WellKnownMember(wellKnownProperty) as PropertySymbol;
  204. if ((object)propertySymbol == null) return false;
  205. propertySymbol = propertySymbol.AsMember(containingType);
  206. return true;
  207. }
  208. }
  209. }