33// Copyright (C) Leszek Pomianowski and OpenAPI Client Contributors.
44// All Rights Reserved.
55
6- using System . Net . Http ;
7- using Microsoft . CodeAnalysis . CSharp ;
8- using Microsoft . CodeAnalysis . CSharp . Syntax ;
96using Microsoft . OpenApi ;
107using Microsoft . OpenApi . Reader ;
118using OpenApi . Client . SourceGenerators . Converters ;
@@ -23,9 +20,9 @@ public sealed class ClientGenerator(GeneratorData metadata)
2320
2421 private OpenApiDocument document = null ! ;
2522
26- private static readonly string GeneratorVersion = AssemblyVersionProvider . GetInformationalVersion ( ) ;
23+ private static readonly string GeneratorVersion = AssemblyVersionProvider . Get ( ) ;
2724
28- private const string GeneratorName = "OpenApiClient" ;
25+ private const string GeneratorName = OpenApiClientGeneration . GeneratorName ;
2926
3027 /// <summary>
3128 /// Generates the client source code.
@@ -206,8 +203,7 @@ private MemberDeclarationSyntax ComputeException()
206203 SyntaxFactory . ParseName ( "global::System.CodeDom.Compiler.GeneratedCode" ) ,
207204 SyntaxFactory . AttributeArgumentList (
208205 SyntaxFactory . SeparatedList (
209- new [ ]
210- {
206+ [
211207 SyntaxFactory . AttributeArgument (
212208 SyntaxFactory . LiteralExpression (
213209 SyntaxKind . StringLiteralExpression ,
@@ -220,7 +216,7 @@ private MemberDeclarationSyntax ComputeException()
220216 SyntaxFactory . Literal ( GeneratorVersion )
221217 )
222218 ) ,
223- }
219+ ]
224220 )
225221 )
226222 )
@@ -236,38 +232,43 @@ private MemberDeclarationSyntax ComputeException()
236232
237233 private MemberDeclarationSyntax ComputeInterface ( )
238234 {
239- // Add a meaningful description to the interface, including information about its purpose and details from the OpenAPI document
240235 SyntaxTriviaList interfaceSummaryTrivia = SyntaxFactory . TriviaList (
241236 SyntaxFactory . Comment ( "/// <summary>" ) ,
242237 SyntaxFactory . CarriageReturnLineFeed ,
243238 SyntaxFactory . Comment (
244239 $ "/// { metadata . ClassName } is an abstraction for a client to an API generated based on the OpenAPI specification."
245240 ) ,
246241 SyntaxFactory . CarriageReturnLineFeed ,
247- SyntaxFactory . Comment ( "/// It uses an injected HttpClient to make HTTP requests." ) ,
242+ SyntaxFactory . Comment (
243+ "/// Uses an injected <see cref=\" global::System.Net.Http.HttpClient\" > to make HTTP requests."
244+ ) ,
248245 SyntaxFactory . CarriageReturnLineFeed
249246 ) ;
250247
251- if ( ! string . IsNullOrEmpty ( document . Info . Summary ) )
248+ if ( ! string . IsNullOrWhiteSpace ( document . Info . Summary ) )
252249 {
253250 interfaceSummaryTrivia = interfaceSummaryTrivia . AddRange (
254251 [
255252 SyntaxFactory . Comment ( "/// <para>" ) ,
256253 SyntaxFactory . CarriageReturnLineFeed ,
257- SyntaxFactory . Comment ( $ "/// { document . Info . Summary } ") ,
254+ SyntaxFactory . Comment (
255+ $ "/// { document . Info . Summary ! . Replace ( "\r \n " , " " ) . Replace ( "\n " , " " ) } "
256+ ) ,
258257 SyntaxFactory . CarriageReturnLineFeed ,
259258 SyntaxFactory . Comment ( "/// </para>" ) ,
260259 ]
261260 ) ;
262261 }
263262
264- if ( ! string . IsNullOrEmpty ( document . Info . Description ) )
263+ if ( ! string . IsNullOrWhiteSpace ( document . Info . Description ) )
265264 {
266265 interfaceSummaryTrivia = interfaceSummaryTrivia . AddRange (
267266 [
268267 SyntaxFactory . Comment ( "/// <para>" ) ,
269268 SyntaxFactory . CarriageReturnLineFeed ,
270- SyntaxFactory . Comment ( $ "/// { document . Info . Description } ") ,
269+ SyntaxFactory . Comment (
270+ $ "/// { document . Info . Description ! . Replace ( "\r \n " , " " ) . Replace ( "\n " , " " ) } "
271+ ) ,
271272 SyntaxFactory . CarriageReturnLineFeed ,
272273 SyntaxFactory . Comment ( "/// </para>" ) ,
273274 ]
@@ -290,8 +291,7 @@ private MemberDeclarationSyntax ComputeInterface()
290291 SyntaxFactory . ParseName ( "global::System.CodeDom.Compiler.GeneratedCode" ) ,
291292 SyntaxFactory . AttributeArgumentList (
292293 SyntaxFactory . SeparatedList (
293- new [ ]
294- {
294+ [
295295 SyntaxFactory . AttributeArgument (
296296 SyntaxFactory . LiteralExpression (
297297 SyntaxKind . StringLiteralExpression ,
@@ -303,8 +303,8 @@ private MemberDeclarationSyntax ComputeInterface()
303303 SyntaxKind . StringLiteralExpression ,
304304 SyntaxFactory . Literal ( GeneratorVersion )
305305 )
306- ) ,
307- }
306+ )
307+ ]
308308 )
309309 )
310310 )
@@ -373,6 +373,43 @@ private MemberDeclarationSyntax ComputeClass()
373373 {
374374 IEnumerable < MemberDeclarationSyntax > classMembers = ComputeClassMembers ( ) ;
375375
376+ classMembers = classMembers . Append (
377+ SyntaxFactory
378+ . ConstructorDeclaration ( metadata . ClassName )
379+ . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PublicKeyword ) )
380+ . AddParameterListParameters (
381+ SyntaxFactory
382+ . Parameter ( SyntaxFactory . Identifier ( "httpClient" ) )
383+ . WithType ( SyntaxFactory . ParseTypeName ( "global::System.Net.Http.HttpClient" ) )
384+ )
385+ . WithBody (
386+ SyntaxFactory . Block (
387+ SyntaxFactory . ExpressionStatement (
388+ SyntaxFactory . AssignmentExpression (
389+ SyntaxKind . SimpleAssignmentExpression ,
390+ SyntaxFactory . IdentifierName ( "_httpClient" ) ,
391+ SyntaxFactory . IdentifierName ( "httpClient" )
392+ )
393+ )
394+ )
395+ )
396+ ) ;
397+
398+ classMembers = classMembers . Prepend (
399+ SyntaxFactory
400+ . FieldDeclaration (
401+ SyntaxFactory
402+ . VariableDeclaration (
403+ SyntaxFactory . ParseTypeName ( "global::System.Net.Http.HttpClient" )
404+ )
405+ . AddVariables ( SyntaxFactory . VariableDeclarator ( "_httpClient" ) )
406+ )
407+ . AddModifiers (
408+ SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) ,
409+ SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword )
410+ )
411+ ) ;
412+
376413 // Add GeneratedCodeAttribute to the class
377414 return SyntaxFactory
378415 . ClassDeclaration ( metadata . ClassName )
@@ -387,8 +424,7 @@ private MemberDeclarationSyntax ComputeClass()
387424 SyntaxFactory . ParseName ( "global::System.CodeDom.Compiler.GeneratedCode" ) ,
388425 SyntaxFactory . AttributeArgumentList (
389426 SyntaxFactory . SeparatedList (
390- new [ ]
391- {
427+ [
392428 SyntaxFactory . AttributeArgument (
393429 SyntaxFactory . LiteralExpression (
394430 SyntaxKind . StringLiteralExpression ,
@@ -401,7 +437,7 @@ private MemberDeclarationSyntax ComputeClass()
401437 SyntaxFactory . Literal ( GeneratorVersion )
402438 )
403439 ) ,
404- }
440+ ]
405441 )
406442 )
407443 )
@@ -429,6 +465,50 @@ KeyValuePair<HttpMethod, OpenApiOperation> openApiOperation in openApiPath.Value
429465 "global::System.Threading.Tasks.Task"
430466 ) ;
431467
468+ FieldDeclarationSyntax httpClientField = SyntaxFactory
469+ . FieldDeclaration (
470+ SyntaxFactory
471+ . VariableDeclaration (
472+ SyntaxFactory . ParseTypeName ( "global::System.Net.Http.HttpClient" )
473+ )
474+ . AddVariables ( SyntaxFactory . VariableDeclarator ( "_httpClient" ) )
475+ )
476+ . AddModifiers (
477+ SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) ,
478+ SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword )
479+ ) ;
480+
481+ PropertyDeclarationSyntax httpClientProperty = SyntaxFactory
482+ . PropertyDeclaration (
483+ SyntaxFactory . ParseTypeName ( "global::System.Net.Http.HttpClient" ) ,
484+ "HttpClient"
485+ )
486+ . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PublicKeyword ) )
487+ . WithExpressionBody (
488+ SyntaxFactory . ArrowExpressionClause ( SyntaxFactory . IdentifierName ( "_httpClient" ) )
489+ )
490+ . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
491+
492+ ConstructorDeclarationSyntax constructor = SyntaxFactory
493+ . ConstructorDeclaration ( metadata . ClassName )
494+ . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PublicKeyword ) )
495+ . AddParameterListParameters (
496+ SyntaxFactory
497+ . Parameter ( SyntaxFactory . Identifier ( "httpClient" ) )
498+ . WithType ( SyntaxFactory . ParseTypeName ( "global::System.Net.Http.HttpClient" ) )
499+ )
500+ . WithBody (
501+ SyntaxFactory . Block (
502+ SyntaxFactory . ExpressionStatement (
503+ SyntaxFactory . AssignmentExpression (
504+ SyntaxKind . SimpleAssignmentExpression ,
505+ SyntaxFactory . IdentifierName ( "_httpClient" ) ,
506+ SyntaxFactory . IdentifierName ( "httpClient" )
507+ )
508+ )
509+ )
510+ ) ;
511+
432512 yield return SyntaxFactory
433513 . MethodDeclaration (
434514 taskType ,
@@ -468,20 +548,20 @@ private static string ComputeOperationName(HttpMethod httpMethod, OpenApiOperati
468548 {
469549 StringBuilder nameBuilder = new ( ) ;
470550
471- nameBuilder . Append (
472- httpMethod . Method switch
473- {
474- "GET" => nameof ( HttpMethod . Get ) ,
475- "POST" => nameof ( HttpMethod . Post ) ,
476- "DELETE" => nameof ( HttpMethod . Delete ) ,
477- "PUT" => nameof ( HttpMethod . Put ) ,
478- "HEAD" => nameof ( HttpMethod . Head ) ,
479- "OPTIONS" => nameof ( HttpMethod . Options ) ,
480- "TRACE" => nameof ( HttpMethod . Trace ) ,
481- "PATCH" => "Patch" ,
482- _ => httpMethod . Method . ToPascalCase ( ) ,
483- }
484- ) ;
551+ // nameBuilder.Append(
552+ // httpMethod.Method switch
553+ // {
554+ // "GET" => nameof(HttpMethod.Get),
555+ // "POST" => nameof(HttpMethod.Post),
556+ // "DELETE" => nameof(HttpMethod.Delete),
557+ // "PUT" => nameof(HttpMethod.Put),
558+ // "HEAD" => nameof(HttpMethod.Head),
559+ // "OPTIONS" => nameof(HttpMethod.Options),
560+ // "TRACE" => nameof(HttpMethod.Trace),
561+ // "PATCH" => "Patch",
562+ // _ => httpMethod.Method.ToPascalCase(),
563+ // }
564+ // );
485565
486566 return nameBuilder . Append ( operation . OperationId ? . ToPascalCase ( ) ) . ToString ( ) ;
487567 }
0 commit comments