@@ -32,7 +32,6 @@ namespace Azure.Generator.Management.Providers
3232    internal  class  ResourceClientProvider  :  TypeProvider 
3333    { 
3434        private  IReadOnlyCollection < InputServiceMethod >  _resourceServiceMethods ; 
35-         private  readonly  IReadOnlyList < string >  _contextualParameters ; 
3635
3736        private  FieldProvider  _dataField ; 
3837        private  FieldProvider  _resourcetypeField ; 
@@ -56,11 +55,11 @@ public ResourceClientProvider(InputClient inputClient)
5655            ResourceData  =  ManagementClientGenerator . Instance . TypeFactory . CreateModel ( resourceModel ) ! ; 
5756            _clientProvider  =  ManagementClientGenerator . Instance . TypeFactory . CreateClient ( inputClient ) ! ; 
5857
59-             _contextualParameters  =  GetContextualParameters ( requestPath ) ; 
58+             ContextualParameters  =  GetContextualParameters ( requestPath ) ; 
6059
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 ) ; 
6463        } 
6564
6665        private  IReadOnlyList < string >  GetContextualParameters ( string  contextualRequestPath ) 
@@ -77,6 +76,8 @@ private IReadOnlyList<string> GetContextualParameters(string contextualRequestPa
7776            return  contextualParameters ; 
7877        } 
7978
79+         protected  IReadOnlyList < string >  ContextualParameters  {  get ;  } 
80+ 
8081        protected  override  string  BuildName ( )  =>  $ "{ SpecName } Resource"; 
8182
8283        private  OperationSourceProvider ?  _source ; 
@@ -89,7 +90,7 @@ private IReadOnlyList<string> GetContextualParameters(string contextualRequestPa
8990
9091        protected  override  string  BuildRelativeFilePath ( )  =>  Path . Combine ( "src" ,  "Generated" ,  $ "{ Name } .cs") ; 
9192
92-         protected  override  FieldProvider [ ]  BuildFields ( )  =>  [ _dataField ,   _clientDiagonosticsField ,  _restClientField ,  _resourcetypeField ] ; 
93+         protected  override  FieldProvider [ ]  BuildFields ( )  =>  [ _clientDiagonosticsField ,  _restClientField ,   _dataField ,  _resourcetypeField ] ; 
9394
9495        protected  override  PropertyProvider [ ]  BuildProperties ( ) 
9596        { 
@@ -199,6 +200,8 @@ protected MethodProvider BuildValidateResourceIdMethod()
199200
200201        protected  virtual  ValueExpression  ExpectedResourceTypeForValidation  =>  _resourcetypeField ; 
201202
203+         protected  virtual  CSharpType  ResourceClientCharpType  =>  this . Type ; 
204+ 
202205        protected  override  CSharpType [ ]  BuildImplements ( )  =>  [ typeof ( ArmResource ) ] ; 
203206
204207        protected  override  MethodProvider [ ]  BuildMethods ( ) 
@@ -224,14 +227,14 @@ protected override MethodProvider[] BuildMethods()
224227            return  [ BuildValidateResourceIdMethod ( ) ,  .. operationMethods ] ; 
225228        } 
226229
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 ) 
228232        { 
229-             var  operation  =  method . Operation ; 
230233            var  signature  =  new  MethodSignature ( 
231234                isUpdateOnly  ?  ( isAsync  ?  "UpdateAsync"  :  "Update" )  :  convenienceMethod . Signature . Name , 
232235                isUpdateOnly  ?  $ "Update a { SpecName } ":  convenienceMethod . Signature . Description , 
233236                convenienceMethod . Signature . Modifiers , 
234-                 GetOperationMethodReturnType ( isAsync ,   method   is   InputLongRunningServiceMethod   ||   method   is   InputLongRunningPagingServiceMethod ,   operation . Responses ,  out  var  isGeneric ) , 
237+                 GetOperationMethodReturnType ( method ,   isAsync ,  out  var  isGeneric ) , 
235238                convenienceMethod . Signature . ReturnDescription , 
236239                GetOperationMethodParameters ( convenienceMethod ,  method  is  InputLongRunningServiceMethod ) , 
237240                convenienceMethod . Signature . Attributes , 
@@ -240,58 +243,85 @@ private MethodProvider BuildOperationMethod(InputServiceMethod method, MethodPro
240243                convenienceMethod . Signature . ExplicitInterface , 
241244                convenienceMethod . Signature . NonDocumentComment ) ; 
242245
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+         { 
243251            var  bodyStatements  =  new  MethodBodyStatement [ ] 
244252                { 
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 ) , 
246254                    scopeVariable . Invoke ( nameof ( DiagnosticScope . Start ) ) . Terminate ( ) , 
247255                    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 ( ) ] ) ) 
249259                } ; 
250260
251261            return  new  MethodProvider ( signature ,  bodyStatements ,  this ) ; 
252262        } 
253263
264+         protected  virtual  bool  SkipMethodParameter ( ParameterProvider  parameter ) 
265+         { 
266+             return  ContextualParameters . Contains ( parameter . Name ) ; 
267+         } 
268+ 
254269        protected  IReadOnlyList < ParameterProvider >  GetOperationMethodParameters ( MethodProvider  convenienceMethod ,  bool  isLongRunning ) 
255270        { 
256271            var  result  =  new  List < ParameterProvider > ( ) ; 
257272            if  ( isLongRunning ) 
258273            { 
259274                result . Add ( KnownAzureParameters . WaitUntil ) ; 
260275            } 
276+ 
261277            foreach  ( var  parameter  in  convenienceMethod . Signature . Parameters ) 
262278            { 
263-                 if  ( ! _contextualParameters . Contains ( parameter . Name ) ) 
279+                 if  ( ! SkipMethodParameter ( parameter ) ) 
264280                { 
265281                    result . Add ( parameter ) ; 
266282                } 
267283            } 
284+ 
268285            return  result ; 
269286        } 
270287
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 ) 
272302        { 
273-             isGeneric  =  false ; 
303+             bool  isLongRunningOperation  =  IsLongRunningOperation ( method ) ; 
304+             isGeneric  =  IsReturnTypeGeneric ( method ) ; 
305+ 
274306            if  ( isLongRunningOperation ) 
275307            { 
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 ) 
279309                { 
280310                    return  isAsync  ?  new  CSharpType ( typeof ( Task < > ) ,  typeof ( ArmOperation ) )  :  typeof ( ArmOperation ) ; 
281311                } 
282312                else 
283313                { 
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 ) ; 
286315                } 
287316            } 
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 ) ; 
289318        } 
290319
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 ) 
292321        { 
293322            var  operation  =  method . Operation ; 
294323            var  cancellationToken  =  convenienceMethod . Signature . Parameters . Single ( p =>  p . Type . Equals ( typeof ( CancellationToken ) ) ) ; 
324+ 
295325            var  tryStatement  =  new  TryStatement ( ) ; 
296326            var  contextDeclaration  =  Declare ( "context" ,  typeof ( RequestContext ) ,  New . Instance ( typeof ( RequestContext ) ,  new  Dictionary < ValueExpression ,  ValueExpression >  {  {  Identifier ( nameof ( RequestContext . CancellationToken ) ) ,  cancellationToken  }  } ) ,  out  var  contextVariable ) ; 
297327            tryStatement . Add ( contextDeclaration ) ; 
@@ -325,7 +355,7 @@ private TryStatement BuildOperationMethodTryStatement(MethodProvider convenience
325355                    finalStateVia  =  ( OperationFinalStateVia ) lroPagingMethod . LongRunningServiceMetadata . FinalStateVia ; 
326356                } 
327357
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 ] ) ; 
329359                ValueExpression [ ]  armOperationArguments  =  [ _clientDiagonosticsField ,  This . Property ( "Pipeline" ) ,  messageVariable . Property ( "Request" ) ,  isGeneric  ?  responseVariable . Invoke ( "GetRawResponse" )  :  responseVariable ,  Static ( typeof ( OperationFinalStateVia ) ) . Property ( finalStateVia . ToString ( ) ) ] ; 
330360                var  operationDeclaration  =  Declare ( "operation" ,  armOperationType ,  New . Instance ( armOperationType ,  isGeneric  ?  [ New . Instance ( Source . Type ,  This . Property ( "Client" ) ) ,  .. armOperationArguments ]  :  armOperationArguments ) ,  out  var  operationVariable ) ; 
331361
@@ -340,15 +370,27 @@ private TryStatement BuildOperationMethodTryStatement(MethodProvider convenience
340370            } 
341371            else 
342372            { 
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 ) ) ; 
348374            } 
375+ 
349376            return  tryStatement ; 
350377        } 
351378
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+ 
352394        private  static CSharpType  GetResponseType ( MethodProvider  convenienceMethod ,  bool  isAsync )  =>  isAsync  ?  convenienceMethod . Signature . ReturnType ? . Arguments [ 0 ] !  :  convenienceMethod . Signature . ReturnType ! ; 
353395
354396        private  ValueExpression [ ]  PopulateArguments ( IReadOnlyList < ParameterProvider >  parameters ,  MethodProvider  convenienceMethod ,  VariableExpression  contextVariable ) 
@@ -365,7 +407,7 @@ private ValueExpression[] PopulateArguments(IReadOnlyList<ParameterProvider> par
365407                    arguments . Add ( This . Property ( nameof ( ArmResource . Id ) ) . Property ( nameof ( ResourceIdentifier . ResourceGroupName ) ) ) ; 
366408                } 
367409                // TODO: handle parents 
368-                 else  if  ( parameter . Name . Equals ( _contextualParameters . Last ( ) ,  StringComparison . InvariantCultureIgnoreCase ) ) 
410+                 else  if  ( parameter . Name . Equals ( ContextualParameters . Last ( ) ,  StringComparison . InvariantCultureIgnoreCase ) ) 
369411                { 
370412                    arguments . Add ( This . Property ( nameof ( ArmResource . Id ) ) . Property ( nameof ( ResourceIdentifier . Name ) ) ) ; 
371413                } 
0 commit comments