RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.67k stars 1.23k forks source link

When first tag contains dot, C# client generated using MultipleClientsFromFirstTagAndOperationNameGenerator is invalid #4719

Open romfir opened 7 months ago

romfir commented 7 months ago

sample swagger.json code:

async Task Main()
{
    var document = await OpenApiDocument.FromFileAsync("swagger.json");

    var settings = new CSharpClientGeneratorSettings
    {
        GenerateClientClasses = true,
        GenerateOptionalParameters = true,
        OperationNameGenerator = new MultipleClientsFromFirstTagAndOperationNameGenerator(),
        CSharpGeneratorSettings =
    {
        Namespace = "CustomNameSpace",
        JsonLibrary = CSharpJsonLibrary.SystemTextJson,
        ClassStyle = CSharpClassStyle.Poco,
    },
        UseHttpClientCreationMethod = false,
        DisposeHttpClient = true,
        GenerateSyncMethods = false,
        GeneratePrepareRequestAndProcessResponseAsAsyncMethods = false,
    };

    var generator = new CSharpClientGenerator(document, settings);

    var codeGeneratedByNSwag = generator.GenerateFile();

    Console.WriteLine(codeGeneratedByNSwag);
}

generated code looks like this which is not a valid C# code

 public partial class Categories.CategoryClient 
    {
    #pragma warning disable 8618 // Set by constructor via BaseUrl property
        private string _baseUrl;
    #pragma warning restore 8618 // Set by constructor via BaseUrl property
        private System.Net.Http.HttpClient _httpClient;
        private static System.Lazy<System.Text.Json.JsonSerializerOptions> _settings = new System.Lazy<System.Text.Json.JsonSerializerOptions>(CreateSerializerSettings, true);

        public Categories.CategoryClient(System.Net.Http.HttpClient httpClient)
        {
            BaseUrl = "https://localhost:56908";
            _httpClient = httpClient;
        }

Error is probably located in GenerateControllerName method, it should somehow handle special characters, probably the best solution to this would be to use Roslyn apis, something like this using Microsoft.CodeAnalysis.CSharp:

public static string CsEscapedIdentifier(string text)
{
    if (!SyntaxFacts.IsValidIdentifier(text))
    {
        text = new string(text.Where(SyntaxFacts.IsIdentifierPartCharacter).ToArray());
        if (!SyntaxFacts.IsIdentifierStartCharacter(text[0]))
            text = "a" + text;
    }

    if (SyntaxFacts.GetKeywordKind(text) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(text) != SyntaxKind.None)
        text = "@" + text;

    return text;
}

code inspired by this

libraries used: NJsonSchema.CodeGeneration.CSharp: 11.0.0 NSwag.CodeGeneration.CSharp: 14.0.1 NSwag.Core: 14.0.1