@@ -32,7 +32,6 @@ namespace Azure.Generator.Management.Providers
32
32
internal class ResourceClientProvider : TypeProvider
33
33
{
34
34
private IReadOnlyCollection < InputServiceMethod > _resourceServiceMethods ;
35
- private readonly IReadOnlyList < string > _contextualParameters ;
36
35
37
36
private FieldProvider _dataField ;
38
37
private FieldProvider _resourcetypeField ;
@@ -56,11 +55,11 @@ public ResourceClientProvider(InputClient inputClient)
56
55
ResourceData = ManagementClientGenerator . Instance . TypeFactory . CreateModel ( resourceModel ) ! ;
57
56
_clientProvider = ManagementClientGenerator . Instance . TypeFactory . CreateClient ( inputClient ) ! ;
58
57
59
- _contextualParameters = GetContextualParameters ( requestPath ) ;
58
+ ContextualParameters = GetContextualParameters ( requestPath ) ;
60
59
61
- _dataField = new FieldProvider ( FieldModifiers . Private , ResourceData . Type , "_data" , this ) ;
62
- _clientDiagonosticsField = new FieldProvider ( FieldModifiers . Private , typeof ( ClientDiagnostics ) , $ "_{ SpecName . ToLower ( ) } ClientDiagnostics", this ) ;
63
- _restClientField = new FieldProvider ( FieldModifiers . Private , _clientProvider . Type , $ "_{ SpecName . ToLower ( ) } RestClient", this ) ;
60
+ _dataField = new FieldProvider ( FieldModifiers . Private | FieldModifiers . ReadOnly , ResourceData . Type , "_data" , this ) ;
61
+ _clientDiagonosticsField = new FieldProvider ( FieldModifiers . Private | FieldModifiers . ReadOnly , typeof ( ClientDiagnostics ) , $ "_{ SpecName . ToLower ( ) } ClientDiagnostics", this ) ;
62
+ _restClientField = new FieldProvider ( FieldModifiers . Private | FieldModifiers . ReadOnly , _clientProvider . Type , $ "_{ SpecName . ToLower ( ) } RestClient", this ) ;
64
63
}
65
64
66
65
private IReadOnlyList < string > GetContextualParameters ( string contextualRequestPath )
@@ -77,6 +76,8 @@ private IReadOnlyList<string> GetContextualParameters(string contextualRequestPa
77
76
return contextualParameters ;
78
77
}
79
78
79
+ protected IReadOnlyList < string > ContextualParameters { get ; }
80
+
80
81
protected override string BuildName ( ) => $ "{ SpecName } Resource";
81
82
82
83
private OperationSourceProvider ? _source ;
@@ -89,7 +90,7 @@ private IReadOnlyList<string> GetContextualParameters(string contextualRequestPa
89
90
90
91
protected override string BuildRelativeFilePath ( ) => Path . Combine ( "src" , "Generated" , $ "{ Name } .cs") ;
91
92
92
- protected override FieldProvider [ ] BuildFields ( ) => [ _dataField , _clientDiagonosticsField , _restClientField , _resourcetypeField ] ;
93
+ protected override FieldProvider [ ] BuildFields ( ) => [ _clientDiagonosticsField , _restClientField , _dataField , _resourcetypeField ] ;
93
94
94
95
protected override PropertyProvider [ ] BuildProperties ( )
95
96
{
@@ -199,6 +200,8 @@ protected MethodProvider BuildValidateResourceIdMethod()
199
200
200
201
protected virtual ValueExpression ExpectedResourceTypeForValidation => _resourcetypeField ;
201
202
203
+ protected virtual CSharpType ResourceClientCharpType => this . Type ;
204
+
202
205
protected override CSharpType [ ] BuildImplements ( ) => [ typeof ( ArmResource ) ] ;
203
206
204
207
protected override MethodProvider [ ] BuildMethods ( )
@@ -224,14 +227,14 @@ protected override MethodProvider[] BuildMethods()
224
227
return [ BuildValidateResourceIdMethod ( ) , .. operationMethods ] ;
225
228
}
226
229
227
- private MethodProvider BuildOperationMethod ( InputServiceMethod method , MethodProvider convenienceMethod , bool isAsync , bool isUpdateOnly = false )
230
+ // TODO: the BuildOperationMethod related code is kind of messy now need to be refactored in a following up PR
231
+ protected MethodProvider BuildOperationMethod ( InputServiceMethod method , MethodProvider convenienceMethod , bool isAsync , bool isUpdateOnly = false )
228
232
{
229
- var operation = method . Operation ;
230
233
var signature = new MethodSignature (
231
234
isUpdateOnly ? ( isAsync ? "UpdateAsync" : "Update" ) : convenienceMethod . Signature . Name ,
232
235
isUpdateOnly ? $ "Update a { SpecName } " : convenienceMethod . Signature . Description ,
233
236
convenienceMethod . Signature . Modifiers ,
234
- GetOperationMethodReturnType ( isAsync , method is InputLongRunningServiceMethod || method is InputLongRunningPagingServiceMethod , operation . Responses , out var isGeneric ) ,
237
+ GetOperationMethodReturnType ( method , isAsync , out var isGeneric ) ,
235
238
convenienceMethod . Signature . ReturnDescription ,
236
239
GetOperationMethodParameters ( convenienceMethod , method is InputLongRunningServiceMethod ) ,
237
240
convenienceMethod . Signature . Attributes ,
@@ -240,58 +243,85 @@ private MethodProvider BuildOperationMethod(InputServiceMethod method, MethodPro
240
243
convenienceMethod . Signature . ExplicitInterface ,
241
244
convenienceMethod . Signature . NonDocumentComment ) ;
242
245
246
+ return BuildOperationMethodCore ( method , convenienceMethod , signature , isAsync , isGeneric ) ;
247
+ }
248
+
249
+ protected MethodProvider BuildOperationMethodCore ( InputServiceMethod method , MethodProvider convenienceMethod , MethodSignature signature , bool isAsync , bool isGeneric )
250
+ {
243
251
var bodyStatements = new MethodBodyStatement [ ]
244
252
{
245
- UsingDeclare ( "scope" , typeof ( DiagnosticScope ) , _clientDiagonosticsField . Invoke ( nameof ( ClientDiagnostics . CreateScope ) , [ Literal ( $ "{ Type . Namespace } .{ operation . Name } ") ] ) , out var scopeVariable ) ,
253
+ UsingDeclare ( "scope" , typeof ( DiagnosticScope ) , _clientDiagonosticsField . Invoke ( nameof ( ClientDiagnostics . CreateScope ) , [ Literal ( $ "{ Name } .{ signature . Name } ") ] ) , out var scopeVariable ) ,
246
254
scopeVariable . Invoke ( nameof ( DiagnosticScope . Start ) ) . Terminate ( ) ,
247
255
new TryCatchFinallyStatement
248
- ( BuildOperationMethodTryStatement ( convenienceMethod , isAsync , method , isGeneric ) , Catch ( Declare < Exception > ( "e" , out var exceptionVarialble ) , [ scopeVariable . Invoke ( nameof ( DiagnosticScope . Failed ) , exceptionVarialble ) . Terminate ( ) , Throw ( ) ] ) )
256
+ ( BuildOperationMethodTryStatement ( method , convenienceMethod , signature , isAsync , isGeneric ) ,
257
+ Catch ( Declare < Exception > ( "e" , out var exceptionVarialble ) ,
258
+ [ scopeVariable . Invoke ( nameof ( DiagnosticScope . Failed ) , exceptionVarialble ) . Terminate ( ) , Throw ( ) ] ) )
249
259
} ;
250
260
251
261
return new MethodProvider ( signature , bodyStatements , this ) ;
252
262
}
253
263
264
+ protected virtual bool SkipMethodParameter ( ParameterProvider parameter )
265
+ {
266
+ return ContextualParameters . Contains ( parameter . Name ) ;
267
+ }
268
+
254
269
protected IReadOnlyList < ParameterProvider > GetOperationMethodParameters ( MethodProvider convenienceMethod , bool isLongRunning )
255
270
{
256
271
var result = new List < ParameterProvider > ( ) ;
257
272
if ( isLongRunning )
258
273
{
259
274
result . Add ( KnownAzureParameters . WaitUntil ) ;
260
275
}
276
+
261
277
foreach ( var parameter in convenienceMethod . Signature . Parameters )
262
278
{
263
- if ( ! _contextualParameters . Contains ( parameter . Name ) )
279
+ if ( ! SkipMethodParameter ( parameter ) )
264
280
{
265
281
result . Add ( parameter ) ;
266
282
}
267
283
}
284
+
268
285
return result ;
269
286
}
270
287
271
- protected CSharpType GetOperationMethodReturnType ( bool isAsync , bool isLongRunningOperation , IReadOnlyList < InputOperationResponse > operationResponses , out bool isGeneric )
288
+ protected bool IsLongRunningOperation ( InputServiceMethod method )
289
+ {
290
+ return method is InputLongRunningServiceMethod || method is InputLongRunningPagingServiceMethod ;
291
+ }
292
+
293
+ protected bool IsReturnTypeGeneric ( InputServiceMethod method )
294
+ {
295
+ var operationResponses = method . Operation . Responses ;
296
+ var response = operationResponses . FirstOrDefault ( r => ! r . IsErrorResponse ) ;
297
+ var responseBodyType = response ? . BodyType is null ? null : ManagementClientGenerator . Instance . TypeFactory . CreateCSharpType ( response . BodyType ) ;
298
+ return IsLongRunningOperation ( method ) && responseBodyType is not null ;
299
+ }
300
+
301
+ protected CSharpType GetOperationMethodReturnType ( InputServiceMethod method , bool isAsync , out bool isGeneric )
272
302
{
273
- isGeneric = false ;
303
+ bool isLongRunningOperation = IsLongRunningOperation ( method ) ;
304
+ isGeneric = IsReturnTypeGeneric ( method ) ;
305
+
274
306
if ( isLongRunningOperation )
275
307
{
276
- var response = operationResponses . FirstOrDefault ( r => ! r . IsErrorResponse ) ;
277
- var responseBodyType = response ? . BodyType is null ? null : ManagementClientGenerator . Instance . TypeFactory . CreateCSharpType ( response . BodyType ) ;
278
- if ( responseBodyType is null )
308
+ if ( ! isGeneric )
279
309
{
280
310
return isAsync ? new CSharpType ( typeof ( Task < > ) , typeof ( ArmOperation ) ) : typeof ( ArmOperation ) ;
281
311
}
282
312
else
283
313
{
284
- isGeneric = true ;
285
- return isAsync ? new CSharpType ( typeof ( Task < > ) , new CSharpType ( typeof ( ArmOperation < > ) , Type ) ) : new CSharpType ( typeof ( ArmOperation < > ) , Type ) ;
314
+ return isAsync ? new CSharpType ( typeof ( Task < > ) , new CSharpType ( typeof ( ArmOperation < > ) , ResourceClientCharpType ) ) : new CSharpType ( typeof ( ArmOperation < > ) , ResourceClientCharpType ) ;
286
315
}
287
316
}
288
- return isAsync ? new CSharpType ( typeof ( Task < > ) , new CSharpType ( typeof ( Response < > ) , Type ) ) : new CSharpType ( typeof ( Response < > ) , Type ) ;
317
+ return isAsync ? new CSharpType ( typeof ( Task < > ) , new CSharpType ( typeof ( Response < > ) , ResourceClientCharpType ) ) : new CSharpType ( typeof ( Response < > ) , ResourceClientCharpType ) ;
289
318
}
290
319
291
- private TryStatement BuildOperationMethodTryStatement ( MethodProvider convenienceMethod , bool isAsync , InputServiceMethod method , bool isGeneric )
320
+ private TryStatement BuildOperationMethodTryStatement ( InputServiceMethod method , MethodProvider convenienceMethod , MethodSignature signature , bool isAsync , bool isGeneric )
292
321
{
293
322
var operation = method . Operation ;
294
323
var cancellationToken = convenienceMethod . Signature . Parameters . Single ( p => p . Type . Equals ( typeof ( CancellationToken ) ) ) ;
324
+
295
325
var tryStatement = new TryStatement ( ) ;
296
326
var contextDeclaration = Declare ( "context" , typeof ( RequestContext ) , New . Instance ( typeof ( RequestContext ) , new Dictionary < ValueExpression , ValueExpression > { { Identifier ( nameof ( RequestContext . CancellationToken ) ) , cancellationToken } } ) , out var contextVariable ) ;
297
327
tryStatement . Add ( contextDeclaration ) ;
@@ -325,7 +355,7 @@ private TryStatement BuildOperationMethodTryStatement(MethodProvider convenience
325
355
finalStateVia = ( OperationFinalStateVia ) lroPagingMethod . LongRunningServiceMetadata . FinalStateVia ;
326
356
}
327
357
328
- var armOperationType = ! isGeneric ? ManagementClientGenerator . Instance . OutputLibrary . ArmOperation . Type : ManagementClientGenerator . Instance . OutputLibrary . GenericArmOperation . Type . MakeGenericType ( [ Type ] ) ;
358
+ var armOperationType = ! isGeneric ? ManagementClientGenerator . Instance . OutputLibrary . ArmOperation . Type : ManagementClientGenerator . Instance . OutputLibrary . GenericArmOperation . Type . MakeGenericType ( [ ResourceClientCharpType ] ) ;
329
359
ValueExpression [ ] armOperationArguments = [ _clientDiagonosticsField , This . Property ( "Pipeline" ) , messageVariable . Property ( "Request" ) , isGeneric ? responseVariable . Invoke ( "GetRawResponse" ) : responseVariable , Static ( typeof ( OperationFinalStateVia ) ) . Property ( finalStateVia . ToString ( ) ) ] ;
330
360
var operationDeclaration = Declare ( "operation" , armOperationType , New . Instance ( armOperationType , isGeneric ? [ New . Instance ( Source . Type , This . Property ( "Client" ) ) , .. armOperationArguments ] : armOperationArguments ) , out var operationVariable ) ;
331
361
@@ -340,15 +370,27 @@ private TryStatement BuildOperationMethodTryStatement(MethodProvider convenience
340
370
}
341
371
else
342
372
{
343
- tryStatement . Add ( new IfStatement ( responseVariable . Property ( "Value" ) . Equal ( Null ) )
344
- {
345
- ( ( KeywordExpression ) ThrowExpression ( New . Instance ( typeof ( RequestFailedException ) , responseVariable . Invoke ( "GetRawResponse" ) ) ) ) . Terminate ( )
346
- } ) ;
347
- tryStatement . Add ( Return ( Static ( typeof ( Response ) ) . Invoke ( nameof ( Response . FromValue ) , New . Instance ( Type , This . Property ( "Client" ) , responseVariable . Property ( "Value" ) ) , responseVariable . Invoke ( "GetRawResponse" ) ) ) ) ;
373
+ tryStatement . Add ( BuildReturnStatements ( responseVariable , signature ) ) ;
348
374
}
375
+
349
376
return tryStatement ;
350
377
}
351
378
379
+ protected virtual MethodBodyStatement BuildReturnStatements ( ValueExpression responseVariable , MethodSignature signature )
380
+ {
381
+ List < MethodBodyStatement > statements =
382
+ [
383
+ new IfStatement ( responseVariable . Property ( "Value" ) . Equal ( Null ) )
384
+ {
385
+ ( ( KeywordExpression ) ThrowExpression ( New . Instance ( typeof ( RequestFailedException ) , responseVariable . Invoke ( "GetRawResponse" ) ) ) ) . Terminate ( )
386
+ } ,
387
+ ] ;
388
+ var returnValueExpression = New . Instance ( ResourceClientCharpType , This . Property ( "Client" ) , responseVariable . Property ( "Value" ) ) ;
389
+ statements . Add ( Return ( Static ( typeof ( Response ) ) . Invoke ( nameof ( Response . FromValue ) , returnValueExpression , responseVariable . Invoke ( "GetRawResponse" ) ) ) ) ;
390
+
391
+ return statements ;
392
+ }
393
+
352
394
private static CSharpType GetResponseType ( MethodProvider convenienceMethod , bool isAsync ) => isAsync ? convenienceMethod . Signature . ReturnType ? . Arguments [ 0 ] ! : convenienceMethod . Signature . ReturnType ! ;
353
395
354
396
private ValueExpression [ ] PopulateArguments ( IReadOnlyList < ParameterProvider > parameters , MethodProvider convenienceMethod , VariableExpression contextVariable )
@@ -365,7 +407,7 @@ private ValueExpression[] PopulateArguments(IReadOnlyList<ParameterProvider> par
365
407
arguments . Add ( This . Property ( nameof ( ArmResource . Id ) ) . Property ( nameof ( ResourceIdentifier . ResourceGroupName ) ) ) ;
366
408
}
367
409
// TODO: handle parents
368
- else if ( parameter . Name . Equals ( _contextualParameters . Last ( ) , StringComparison . InvariantCultureIgnoreCase ) )
410
+ else if ( parameter . Name . Equals ( ContextualParameters . Last ( ) , StringComparison . InvariantCultureIgnoreCase ) )
369
411
{
370
412
arguments . Add ( This . Property ( nameof ( ArmResource . Id ) ) . Property ( nameof ( ResourceIdentifier . Name ) ) ) ;
371
413
}
0 commit comments