From 31c3c532ff3a63f27a642020b5c3f8a93728d29c Mon Sep 17 00:00:00 2001 From: koros Date: Fri, 15 Nov 2024 17:11:32 +0300 Subject: [PATCH] Remove unused code and enhance JSON request body output --- src/Kiota.Builder/Refiners/HttpRefiner.cs | 45 ++++++------------- .../HTTP/CodeClassDeclarationWriter.cs | 44 +++++++++++++----- 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/Kiota.Builder/Refiners/HttpRefiner.cs b/src/Kiota.Builder/Refiners/HttpRefiner.cs index 165c4cb354..9f2e621337 100644 --- a/src/Kiota.Builder/Refiners/HttpRefiner.cs +++ b/src/Kiota.Builder/Refiners/HttpRefiner.cs @@ -35,15 +35,6 @@ public override Task RefineAsync(CodeNamespace generatedCode, CancellationToken static s => s ); cancellationToken.ThrowIfCancellationRequested(); - AddPropertiesAndMethodTypesImports( - generatedCode, - true, - false, - true); - AddDefaultImports( - generatedCode, - defaultUsingEvaluators); - cancellationToken.ThrowIfCancellationRequested(); SetBaseUrlForRequestBuilderMethods(generatedCode, GetBaseUrl(generatedCode)); // Remove unused code from the DOM e.g Models, BarrelInitializers, e.t.c RemoveUnusedCodeElements(generatedCode); @@ -54,24 +45,6 @@ public override Task RefineAsync(CodeNamespace generatedCode, CancellationToken CorrectImplements); }, cancellationToken); } - private static readonly AdditionalUsingEvaluator[] defaultUsingEvaluators = { - new (x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.RequestAdapter), - "MicrosoftKiotaAbstractions", "RequestAdapter"), - new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.RequestGenerator), - "MicrosoftKiotaAbstractions", "RequestInformation", "HttpMethod", "RequestOption"), - new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.RequestExecutor), - "MicrosoftKiotaAbstractions", "ResponseHandler"), - new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Serializer), - "MicrosoftKiotaAbstractions", "SerializationWriter"), - new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Deserializer, CodeMethodKind.Factory), - "MicrosoftKiotaAbstractions", "ParseNode", "Parsable"), - new (x => x is CodeClass codeClass && codeClass.IsOfKind(CodeClassKind.Model), - "MicrosoftKiotaAbstractions", "Parsable"), - new (x => x is CodeClass @class && @class.IsOfKind(CodeClassKind.Model) && - (@class.Properties.Any(x => x.IsOfKind(CodePropertyKind.AdditionalData)) || - @class.StartBlock.Implements.Any(x => KiotaBuilder.AdditionalHolderInterface.Equals(x.Name, StringComparison.OrdinalIgnoreCase))), - "MicrosoftKiotaAbstractions", "AdditionalDataHolder"), - }; private static void CorrectImplements(ProprietableBlockDeclaration block) { block.ReplaceImplementByName(KiotaBuilder.AdditionalHolderInterface, "AdditionalDataHolder"); @@ -228,18 +201,28 @@ private static void SetBaseUrlForRequestBuilderMethods(CodeElement current, stri private static void RemoveUnusedCodeElements(CodeElement element) { - if (element is CodeClass code && (code.IsOfKind(CodeClassKind.Model) || code.IsOfKind(CodeClassKind.BarrelInitializer) || IsBaseRequestBuilder(code))) + if (!IsRequestBuilderClass(element) || IsBaseRequestBuilder(element) || IsRequestBuilderClassWithoutAnyHttpOperations(element)) { var parentNameSpace = element.GetImmediateParentOfType(); parentNameSpace?.RemoveChildElement(element); } - CrawlTree(element, RemoveUnusedCodeElements); } - private static bool IsBaseRequestBuilder(CodeClass codeClass) + private static bool IsRequestBuilderClass(CodeElement element) { - return codeClass.IsOfKind(CodeClassKind.RequestBuilder) && + return element is CodeClass code && code.IsOfKind(CodeClassKind.RequestBuilder); + } + + private static bool IsBaseRequestBuilder(CodeElement element) + { + return element is CodeClass codeClass && codeClass.IsOfKind(CodeClassKind.RequestBuilder) && codeClass.Properties.Any(property => property.IsOfKind(CodePropertyKind.UrlTemplate) && string.Equals(property.DefaultValue, "\"{+baseurl}\"", StringComparison.Ordinal)); } + + private static bool IsRequestBuilderClassWithoutAnyHttpOperations(CodeElement element) + { + return element is CodeClass codeClass && codeClass.IsOfKind(CodeClassKind.RequestBuilder) && + !codeClass.Methods.Any(method => method.IsOfKind(CodeMethodKind.RequestExecutor)); + } } diff --git a/src/Kiota.Builder/Writers/HTTP/CodeClassDeclarationWriter.cs b/src/Kiota.Builder/Writers/HTTP/CodeClassDeclarationWriter.cs index 1aee645f9f..1579ee840b 100644 --- a/src/Kiota.Builder/Writers/HTTP/CodeClassDeclarationWriter.cs +++ b/src/Kiota.Builder/Writers/HTTP/CodeClassDeclarationWriter.cs @@ -69,8 +69,7 @@ private static void WriteQueryParameters(CodeElement codeElement, LanguageWriter queryParams.ForEach(prop => { - var documentation = prop.Documentation.DescriptionTemplate; - writer.WriteLine($"# {documentation}"); + writer.WriteLine($"# {prop.Documentation.DescriptionTemplate}"); writer.WriteLine($"@{prop.Name} = "); writer.WriteLine(); }); @@ -87,8 +86,7 @@ private static void WriteHttpMethods(CodeElement codeElement, LanguageWriter wri httpMethods?.ForEach(method => { - var documentation = method.Documentation.DescriptionTemplate; - writer.WriteLine($"# {documentation}"); + writer.WriteLine($"# {method.Documentation.DescriptionTemplate}"); writer.WriteLine($"{method.Name.ToUpperInvariant()} {GetUrlTemplate(codeElement)}"); WriteRequestBody(method, writer); @@ -115,10 +113,9 @@ private static void WriteRequestBody(CodeMethod method, LanguageWriter writer) var requestBody = method.Parameters.FirstOrDefault(param => param.IsOfKind(CodeParameterKind.RequestBody)); if (requestBody is null) return; - var contentType = method.RequestBodyContentType; // Empty line before content type writer.WriteLine(); - writer.WriteLine($"Content-Type: {contentType}"); + writer.WriteLine($"Content-Type: {method.RequestBodyContentType}"); // loop through the properties of the request body and write a JSON object if (requestBody.Type is CodeType ct && ct.TypeDefinition is CodeClass requestBodyClass) @@ -130,13 +127,37 @@ private static void WriteRequestBody(CodeMethod method, LanguageWriter writer) writer.WriteLine("}"); } } - private static void WriteProperties(CodeClass codeClass, LanguageWriter writer) { - // Write properties of the current class - foreach (var prop in codeClass.Properties.Where(prop => prop.IsOfKind(CodePropertyKind.Custom))) + var properties = codeClass.Properties.Where(prop => prop.IsOfKind(CodePropertyKind.Custom)).ToList(); + for (int i = 0; i < properties.Count; i++) { - writer.WriteLine($"{prop.Name}: {GetDefaultValueForProperty(prop)}"); + var prop = properties[i]; + var propName = $"\"{prop.Name}\""; + writer.Write($"{propName}: "); + if (prop.Type is CodeType propType && propType.TypeDefinition is CodeClass propClass) + { + // If the property is an object, write a JSON representation recursively + writer.WriteLine("{", includeIndent: false); + writer.IncreaseIndent(); + WriteProperties(propClass, writer); + writer.DecreaseIndent(); + writer.Write("}"); + } + else + { + writer.Write(GetDefaultValueForProperty(prop), includeIndent: false); + } + + // Add a trailing comma if there are more properties to be written + if (i < properties.Count - 1) + { + writer.WriteLine(",", includeIndent: false); + } + else + { + writer.WriteLine(); + } } // If the class extends another class, write properties of the base class @@ -154,8 +175,9 @@ private static string GetDefaultValueForProperty(CodeProperty prop) "string" => "\"string\"", "bool" or "boolean" => "false", _ when prop.Type is CodeType enumType && enumType.TypeDefinition is CodeEnum enumDefinition => - enumDefinition.Options.FirstOrDefault()?.Name ?? "null", + enumDefinition.Options.FirstOrDefault()?.Name is string enumName ? $"\"{enumName}\"" : "null", _ => "null" }; } + }