|
4 | 4 | using System.Collections.Immutable; |
5 | 5 | using System.IO; |
6 | 6 | using System.Linq; |
| 7 | +using Microsoft.CodeAnalysis.CSharp.Syntax; |
7 | 8 | using Microsoft.Macios.Generator.Context; |
8 | 9 | using Microsoft.Macios.Generator.DataModel; |
9 | 10 | using Microsoft.Macios.Generator.Extensions; |
@@ -168,56 +169,78 @@ static void EmitReturnMethodBody (in Method method, in MethodInvocations invocat |
168 | 169 | } |
169 | 170 |
|
170 | 171 | /// <summary> |
171 | | - /// Emit the code for all the methods in the class. |
| 172 | + /// Emits the code for a given method, including its async version if applicable. |
172 | 173 | /// </summary> |
| 174 | + /// <param name="self">The class emitter.</param> |
173 | 175 | /// <param name="context">The current binding context.</param> |
174 | | - /// <param name="classBlock">Current class block.</param> |
175 | | - public static void EmitMethods (this IClassEmitter self, in BindingContext context, TabbedWriter<StringWriter> classBlock) |
| 176 | + /// <param name="method">The method to emit.</param> |
| 177 | + /// <param name="classBlock">The current class block writer.</param> |
| 178 | + /// <param name="uiThreadCheck">An optional UI thread check expression. If not provided, it will be created based on the context.</param> |
| 179 | + public static void EmitMethod (this IClassEmitter self, in BindingContext context, in Method method, |
| 180 | + TabbedWriter<StringWriter> classBlock, ExpressionStatementSyntax? uiThreadCheck = null) |
176 | 181 | { |
177 | | - var uiThreadCheck = (context.NeedsThreadChecks) |
178 | | - ? EnsureUiThread (context.RootContext.CurrentPlatform) : null; |
179 | | - foreach (var method in context.Changes.Methods.OrderBy (m => m.Name)) { |
180 | | - classBlock.WriteLine (); |
181 | | - classBlock.AppendMemberAvailability (method.SymbolAvailability); |
182 | | - classBlock.AppendGeneratedCodeAttribute (optimizable: true); |
183 | 182 |
|
184 | | - using (var methodBlock = classBlock.CreateBlock (method.ToDeclaration ().ToString (), block: true)) { |
185 | | - // write any possible thread check at the beginning of the method |
186 | | - if (uiThreadCheck is not null) { |
187 | | - methodBlock.WriteLine (uiThreadCheck.ToString ()); |
188 | | - methodBlock.WriteLine (); |
189 | | - } |
| 183 | + // if not passed as an argument, we will create the ui thread check based on the context |
| 184 | + if (uiThreadCheck is null) { |
| 185 | + uiThreadCheck = (context.NeedsThreadChecks) |
| 186 | + ? EnsureUiThread (context.RootContext.CurrentPlatform) |
| 187 | + : null; |
| 188 | + } |
190 | 189 |
|
191 | | - // retrieve the method invocation via the factory, this will generate the necessary arguments |
192 | | - // transformations and the invocation |
193 | | - var invocations = GetInvocations (method); |
| 190 | + classBlock.WriteLine (); |
| 191 | + classBlock.AppendMemberAvailability (method.SymbolAvailability); |
| 192 | + classBlock.AppendGeneratedCodeAttribute (optimizable: true); |
194 | 193 |
|
195 | | - if (method.ReturnType.IsVoid) { |
196 | | - EmitVoidMethodBody (method, invocations, methodBlock); |
197 | | - } else { |
198 | | - EmitReturnMethodBody (method, invocations, methodBlock); |
199 | | - } |
| 194 | + using (var methodBlock = classBlock.CreateBlock (method.ToDeclaration ().ToString (), block: true)) { |
| 195 | + // write any possible thread check at the beginning of the method |
| 196 | + if (uiThreadCheck is not null) { |
| 197 | + methodBlock.WriteLine (uiThreadCheck.ToString ()); |
| 198 | + methodBlock.WriteLine (); |
200 | 199 | } |
201 | 200 |
|
202 | | - if (!method.IsAsync) |
203 | | - continue; |
| 201 | + // retrieve the method invocation via the factory, this will generate the necessary arguments |
| 202 | + // transformations and the invocation |
| 203 | + var invocations = GetInvocations (method); |
204 | 204 |
|
205 | | - // if the method is an async method, generate its async version |
206 | | - classBlock.WriteLine (); |
207 | | - classBlock.AppendMemberAvailability (method.SymbolAvailability); |
208 | | - classBlock.AppendGeneratedCodeAttribute (optimizable: true); |
| 205 | + if (method.ReturnType.IsVoid) { |
| 206 | + EmitVoidMethodBody (method, invocations, methodBlock); |
| 207 | + } else { |
| 208 | + EmitReturnMethodBody (method, invocations, methodBlock); |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + if (!method.IsAsync) |
| 213 | + return; |
209 | 214 |
|
210 | | - var asyncMethod = method.ToAsync (); |
211 | | - using (var methodBlock = classBlock.CreateBlock (asyncMethod.ToDeclaration ().ToString (), block: true)) { |
212 | | - // we need to create the tcs for the the async method |
213 | | - var tcsType = asyncMethod.ReturnType.ToTaskCompletionSource (); |
214 | | - var tcsName = Nomenclator.GetTaskCompletionSourceName (); |
215 | | - methodBlock.WriteRaw ( |
| 215 | + // if the method is an async method, generate its async version |
| 216 | + classBlock.WriteLine (); |
| 217 | + classBlock.AppendMemberAvailability (method.SymbolAvailability); |
| 218 | + classBlock.AppendGeneratedCodeAttribute (optimizable: true); |
| 219 | + |
| 220 | + var asyncMethod = method.ToAsync (); |
| 221 | + using (var methodBlock = classBlock.CreateBlock (asyncMethod.ToDeclaration ().ToString (), block: true)) { |
| 222 | + // we need to create the tcs for the the async method |
| 223 | + var tcsType = asyncMethod.ReturnType.ToTaskCompletionSource (); |
| 224 | + var tcsName = Nomenclator.GetTaskCompletionSourceName (); |
| 225 | + methodBlock.WriteRaw ( |
216 | 226 | $@"{tcsType.GetIdentifierSyntax ()} {tcsName} = new (); |
217 | 227 | {ExpressionStatement (ExecuteSyncCall (method))} |
218 | 228 | return {tcsName}.Task; |
219 | 229 | "); |
220 | | - } |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + /// <summary> |
| 234 | + /// Emit the code for all the methods in the class. |
| 235 | + /// </summary> |
| 236 | + /// <param name="context">The current binding context.</param> |
| 237 | + /// <param name="classBlock">Current class block.</param> |
| 238 | + public static void EmitMethods (this IClassEmitter self, in BindingContext context, TabbedWriter<StringWriter> classBlock) |
| 239 | + { |
| 240 | + var uiThreadCheck = (context.NeedsThreadChecks) |
| 241 | + ? EnsureUiThread (context.RootContext.CurrentPlatform) : null; |
| 242 | + foreach (var method in context.Changes.Methods.OrderBy (m => m.Name)) { |
| 243 | + EmitMethod (self, context, method, classBlock, uiThreadCheck); |
221 | 244 | } |
222 | 245 | } |
223 | 246 |
|
|
0 commit comments