From 144c68e95d96be92787934960bbbafa1f8786951 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 10 Mar 2023 14:52:32 -0500 Subject: [PATCH 01/19] - removes properties from request builders in Go --- src/Kiota.Builder/CodeDOM/CodeProperty.cs | 4 ++ .../CodePropertiesEnumerableExtensions.cs | 16 ++++++ .../Refiners/CommonLanguageRefiner.cs | 26 +++++++++- src/Kiota.Builder/Refiners/GoRefiner.cs | 15 +++++- .../Writers/Go/CodeMethodWriter.cs | 49 ++++++++++--------- .../Writers/Go/CodePropertyWriter.cs | 2 + .../Writers/Go/GoConventionService.cs | 12 +++-- .../Writers/Go/GoNamespaceExtensions.cs | 2 +- 8 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 src/Kiota.Builder/Extensions/CodePropertiesEnumerableExtensions.cs diff --git a/src/Kiota.Builder/CodeDOM/CodeProperty.cs b/src/Kiota.Builder/CodeDOM/CodeProperty.cs index 63700135b0..364d263892 100644 --- a/src/Kiota.Builder/CodeDOM/CodeProperty.cs +++ b/src/Kiota.Builder/CodeDOM/CodeProperty.cs @@ -45,6 +45,10 @@ public class CodeProperty : CodeTerminalWithKind, IDocumentedE public bool ReadOnly { get; set; } = false; public AccessModifier Access { get; set; } = AccessModifier.Public; public bool ExistsInBaseType => OriginalPropertyFromBaseType != null; + public bool ExistsInExternalBaseType + { + get; set; + } public CodeMethod? Getter { get; set; diff --git a/src/Kiota.Builder/Extensions/CodePropertiesEnumerableExtensions.cs b/src/Kiota.Builder/Extensions/CodePropertiesEnumerableExtensions.cs new file mode 100644 index 0000000000..6cc21e72af --- /dev/null +++ b/src/Kiota.Builder/Extensions/CodePropertiesEnumerableExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Kiota.Builder.CodeDOM; + +namespace Kiota.Builder.Extensions; + +public static class CodePropertiesEnumerableExtensions +{ + public static CodeProperty? OfKind(this IEnumerable properties, CodePropertyKind kind) + { + ArgumentNullException.ThrowIfNull(properties); + return properties.FirstOrDefault(x => x != null && x.IsOfKind(kind)); + } +} diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index 866507e2a5..cda995335c 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -468,7 +468,7 @@ private static IEnumerable usingSelector(AdditionalUsingEvaluator x) protected static void AddDefaultImports(CodeElement current, IEnumerable evaluators) { var usingsToAdd = evaluators.Where(x => x.CodeElementEvaluator.Invoke(current)) - .SelectMany(x => usingSelector(x)) + .SelectMany(usingSelector) .ToArray(); if (usingsToAdd.Any()) { @@ -1407,4 +1407,28 @@ protected void RemoveHandlerFromRequestBuilder(CodeElement currentElement) CrawlTree(currentElement, RemoveHandlerFromRequestBuilder); } + protected static void MoveRequestBuilderPropertiesToBaseType(CodeElement currentElement, CodeUsing baseTypeUsing, AccessModifier? accessModifier = null) + { + if (currentElement is CodeClass currentClass && currentClass.IsOfKind(CodeClassKind.RequestBuilder)) + { + if (currentClass.StartBlock.Inherits == null) + { + currentClass.StartBlock.Inherits = new CodeType + { + Name = baseTypeUsing.Name + }; + currentClass.AddUsing(baseTypeUsing); + } + + var properties = currentClass.Properties.Where(static x => x.IsOfKind(CodePropertyKind.PathParameters, CodePropertyKind.UrlTemplate, CodePropertyKind.RequestAdapter)); + foreach (var property in properties) + { + property.ExistsInExternalBaseType = true; + if (accessModifier.HasValue) + property.Access = accessModifier.Value; + } + } + + CrawlTree(currentElement, x => MoveRequestBuilderPropertiesToBaseType(x, baseTypeUsing, accessModifier)); + } } diff --git a/src/Kiota.Builder/Refiners/GoRefiner.cs b/src/Kiota.Builder/Refiners/GoRefiner.cs index 096f390538..3e32b01ed7 100644 --- a/src/Kiota.Builder/Refiners/GoRefiner.cs +++ b/src/Kiota.Builder/Refiners/GoRefiner.cs @@ -18,6 +18,17 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance return Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "BaseRequestBuilder", + Declaration = new CodeType + { + Name = "github.com/microsoft/kiota-abstractions-go", + IsExternal = true + } + }, + accessModifier: AccessModifier.Public); ReplaceIndexersByMethodsWithParameter( generatedCode, false, @@ -29,8 +40,8 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance generatedCode, true, string.Empty, - false, - MergeOverLappedStrings); + false, + MergeOverLappedStrings); RenameCancellationParameter(generatedCode); RemoveDiscriminatorMappingsTargetingSubNamespaces(generatedCode); cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index 41f4721bd2..d485acd44f 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -447,7 +447,7 @@ private void WriteGetterBody(CodeMethod codeElement, LanguageWriter writer, Code private void WriteApiConstructorBody(CodeClass parentClass, CodeMethod method, LanguageWriter writer) { if (parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) is not CodeProperty requestAdapterProperty) return; - var requestAdapterPropertyName = requestAdapterProperty.Name.ToFirstCharacterLowerCase(); + var requestAdapterPropertyName = BaseRequestBuilderVarName + "." + requestAdapterProperty.Name.ToFirstCharacterUpperCase(); var backingStoreParameter = method.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.BackingStore)); WriteSerializationRegistration(method.SerializerModules, writer, parentClass, "RegisterDefaultSerializer", "SerializationWriterFactory"); WriteSerializationRegistration(method.DeserializerModules, writer, parentClass, "RegisterDefaultDeserializer", "ParseNodeFactory"); @@ -457,7 +457,7 @@ private void WriteApiConstructorBody(CodeClass parentClass, CodeMethod method, L writer.WriteLine($"m.{requestAdapterPropertyName}.SetBaseUrl(\"{method.BaseUrl}\")"); writer.CloseBlock(); if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) - writer.WriteLine($"m.{pathParametersProperty.Name.ToFirstCharacterLowerCase()}[\"baseurl\"] = m.{requestAdapterPropertyName}.GetBaseUrl()"); + writer.WriteLine($"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}[\"baseurl\"] = m.{requestAdapterPropertyName}.GetBaseUrl()"); } if (backingStoreParameter != null) writer.WriteLine($"m.{requestAdapterPropertyName}.EnableBackingStore({backingStoreParameter.Name});"); @@ -481,14 +481,18 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho { writer.IncreaseIndent(); var parentClassName = parentClass.StartBlock.Inherits!.Name.ToFirstCharacterUpperCase(); - writer.WriteLine($"{parentClassName}: *{conventions.GetImportedStaticMethodName(parentClass.StartBlock.Inherits, parentClass)}(),"); + var newMethodName = conventions.GetImportedStaticMethodName(parentClass.StartBlock.Inherits, parentClass); + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && + parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty) + writer.WriteLine($"{parentClassName}: *{newMethodName}({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}),"); + else + writer.WriteLine($"{parentClassName}: *{newMethodName}(),"); writer.DecreaseIndent(); } writer.CloseBlock(decreaseIndent: false); foreach (var propWithDefault in parentClass.GetPropertiesOfKind(CodePropertyKind.BackingStore, - CodePropertyKind.RequestBuilder, - CodePropertyKind.UrlTemplate, - CodePropertyKind.PathParameters) + CodePropertyKind.RequestBuilder) .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) .OrderBy(static x => x.Name)) { @@ -519,27 +523,17 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho { if (currentMethod.IsOfKind(CodeMethodKind.Constructor)) { - if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam && + parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) conventions.AddParametersAssignment(writer, pathParametersParam.Type.AllTypes.OfType().FirstOrDefault(), pathParametersParam.Name.ToFirstCharacterLowerCase(), + $"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", currentMethod.Parameters .Where(static x => x.IsOfKind(CodeParameterKind.Path)) .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) .ToArray()); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); } - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.RequestAdapter, CodePropertyKind.RequestAdapter, writer); - } - } - private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? variableName = default) - { - if (parentClass.GetPropertyOfKind(propertyKind) is CodeProperty property) - { - if (!string.IsNullOrEmpty(variableName)) - writer.WriteLine($"m.{property.Name.ToFirstCharacterLowerCase()} = {variableName}"); - else if (currentMethod.Parameters.OfKind(parameterKind) is CodeParameter parameter) - writer.WriteLine($"m.{property.Name.ToFirstCharacterLowerCase()} = {parameter.Name}"); } } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer, CodeClass parentClass) @@ -557,7 +551,7 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, Lan { var pathParameters = codeElement.Parameters.Where(static x => x.IsOfKind(CodeMethod.ParameterKindForConvertedIndexers)); if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) - conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.{pathParametersProperty.Name.ToFirstCharacterLowerCase()}", pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); + conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", parameters: pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName, codeElement.Parameters.Except(pathParameters).ToArray()); } private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer, bool inherits) @@ -725,7 +719,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, RequestParams requ var assignmentPrefix = isVoid ? "err =" : "res, err :="; - writer.WriteLine($"{assignmentPrefix} m.requestAdapter.{sendMethodName}({contextVarName}, {RequestInfoVarName}, {constructorFunction}{errorMappingVarName})"); + writer.WriteLine($"{assignmentPrefix} m.{BaseRequestBuilderVarName}.RequestAdapter.{sendMethodName}({contextVarName}, {RequestInfoVarName}, {constructorFunction}{errorMappingVarName})"); WriteReturnError(writer, returnType); var valueVarName = string.Empty; if (codeElement.ReturnType.CollectionKind != CodeTypeBase.CodeTypeCollectionKind.None) @@ -783,7 +777,7 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req { if (codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null"); - var requestAdapterPropertyName = parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter)?.Name.ToFirstCharacterLowerCase(); + var requestAdapterPropertyName = BaseRequestBuilderVarName + "." + parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter)?.Name.ToFirstCharacterUpperCase(); var contextParameterName = codeElement.Parameters.OfKind(CodeParameterKind.Cancellation)?.Name.ToFirstCharacterLowerCase(); writer.WriteLine($"{RequestInfoVarName} := {conventions.AbstractionsHash}.NewRequestInformation()"); if (parentClass.GetPropertyOfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && @@ -843,7 +837,16 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req } writer.WriteLine($"return {RequestInfoVarName}, nil"); } - private static string GetPropertyCall(CodeProperty property, string defaultValue) => property == null ? defaultValue : $"m.{property.Name.ToFirstCharacterLowerCase()}"; + private const string BaseRequestBuilderVarName = "BaseRequestBuilder"; + private static string GetPropertyCall(CodeProperty property, string defaultValue) + { + return property switch + { + null => defaultValue, + _ when property.ExistsInExternalBaseType => $"m.{BaseRequestBuilderVarName}.{property.Name.ToFirstCharacterUpperCase()}", + _ => $"m.{property.Name.ToFirstCharacterLowerCase()}" + }; + } private static void WriteReturnError(LanguageWriter writer, params string[] returnTypes) { diff --git a/src/Kiota.Builder/Writers/Go/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/Go/CodePropertyWriter.cs index 1185ed5e76..f860b575e6 100644 --- a/src/Kiota.Builder/Writers/Go/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodePropertyWriter.cs @@ -9,6 +9,8 @@ public class CodePropertyWriter : BaseElementWriter 1 ? $"{splatImport.First().TrimStart('*')}." : string.Empty; pathParameters ??= Enumerable.Empty(); var pathParametersSuffix = pathParameters.Any() ? $", {string.Join(", ", pathParameters.Select(x => $"{x.Name.ToFirstCharacterLowerCase()}"))}" : string.Empty; - writer.WriteLines($"return {moduleName}New{constructorName}Internal({urlTemplateParams}, m.{requestAdapterProp.Name}{pathParametersSuffix})"); + writer.WriteLines($"return {moduleName}New{constructorName}Internal({urlTemplateParams}, m.BaseRequestBuilder.{requestAdapterProp.Name.ToFirstCharacterUpperCase()}{pathParametersSuffix})"); } public override string TempDictionaryVarName => "urlTplParams"; - internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase? pathParametersType, string pathParametersReference, params (CodeTypeBase, string, string)[] parameters) + internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase? pathParametersType, string pathParametersReference, string pathParametersTarget = "", params (CodeTypeBase, string, string)[] parameters) { if (pathParametersType == null) return; var mapTypeName = pathParametersType.Name; - writer.WriteLine($"{TempDictionaryVarName} := make({mapTypeName})"); + var isTempTarget = string.IsNullOrEmpty(pathParametersTarget); + if (isTempTarget) + writer.WriteLine($"{TempDictionaryVarName} := make({mapTypeName})"); writer.StartBlock($"for idx, item := range {pathParametersReference} {{"); - writer.WriteLine($"{TempDictionaryVarName}[idx] = item"); + writer.WriteLine($"{(isTempTarget ? TempDictionaryVarName : pathParametersTarget)}[idx] = item"); writer.CloseBlock(); foreach (var p in parameters) { diff --git a/src/Kiota.Builder/Writers/Go/GoNamespaceExtensions.cs b/src/Kiota.Builder/Writers/Go/GoNamespaceExtensions.cs index 633b14bf33..1a06c08602 100644 --- a/src/Kiota.Builder/Writers/Go/GoNamespaceExtensions.cs +++ b/src/Kiota.Builder/Writers/Go/GoNamespaceExtensions.cs @@ -19,7 +19,7 @@ public static string GetInternalNamespaceImport(this CodeElement ns) { if (ns == null) return string.Empty; var urlPrefixIndex = ns.Name.LastIndexOf('/') + 1; - return (ns.Name[..urlPrefixIndex] + ns.Name[urlPrefixIndex..].Split('.', StringSplitOptions.RemoveEmptyEntries).Aggregate((x, y) => $"{x}/{y}")).ToLowerInvariant(); + return (ns.Name[..urlPrefixIndex] + string.Join("/", ns.Name[urlPrefixIndex..].Split('.', StringSplitOptions.RemoveEmptyEntries))).ToLowerInvariant(); } public static string GetNamespaceImportSymbol(this CodeElement ns) { From ecd7cc4d8fec5ff6cd1a0249895d188d04837188 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 13 Mar 2023 10:58:57 -0400 Subject: [PATCH 02/19] - adds a method to remove request configuration class when possible Signed-off-by: Vincent Biret --- src/Kiota.Builder/CodeDOM/CodeType.cs | 5 +++- .../Refiners/CommonLanguageRefiner.cs | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/CodeDOM/CodeType.cs b/src/Kiota.Builder/CodeDOM/CodeType.cs index 6f22d573dc..940d7c37d0 100644 --- a/src/Kiota.Builder/CodeDOM/CodeType.cs +++ b/src/Kiota.Builder/CodeDOM/CodeType.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Kiota.Builder.CodeDOM; public class CodeType : CodeTypeBase, ICloneable @@ -18,7 +19,9 @@ public override object Clone() return new CodeType { TypeDefinition = TypeDefinition, // not cloning the type definition as it's a code element that lives in the tree and we don't want to fork the tree - IsExternal = IsExternal + IsExternal = IsExternal, + GenericTypeParameterValues = new(GenericTypeParameterValues), }.BaseClone(this); } + public List GenericTypeParameterValues { get; set; } = new(); } diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index cda995335c..ffa25800cc 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -1431,4 +1431,33 @@ protected static void MoveRequestBuilderPropertiesToBaseType(CodeElement current CrawlTree(currentElement, x => MoveRequestBuilderPropertiesToBaseType(x, baseTypeUsing, accessModifier)); } + protected static void RemoveRequestConfigurationClasses(CodeElement currentElement, CodeUsing configurationParameterTypeUsing, CodeType defaultValueForGenericTypeParam) + { + if (currentElement is CodeClass currentClass && currentClass.IsOfKind(CodeClassKind.RequestConfiguration) && + currentClass.Parent is CodeClass parentClass) + { + parentClass.RemoveChildElement(currentClass); + var configurationParameters = parentClass.Methods + .SelectMany(static x => x.Parameters) + .Where(x => x.IsOfKind(CodeParameterKind.RequestConfiguration) && x.Type is CodeType type && type.TypeDefinition == currentClass) + .ToArray(); + if (configurationParameters.Any()) + { + parentClass.AddUsing(configurationParameterTypeUsing); + var genericTypeParamValue = currentClass.Properties.OfKind(CodePropertyKind.QueryParameters)?.Type as CodeType ?? defaultValueForGenericTypeParam; + var configurationParameterType = new CodeType + { + Name = configurationParameterTypeUsing.Name, + }; + foreach (var configurationParameter in configurationParameters) + { + var newType = (CodeType)configurationParameterType.Clone(); + newType.GenericTypeParameterValues.Add(genericTypeParamValue); + configurationParameter.Type = newType; + } + } + } + + CrawlTree(currentElement, x => RemoveRequestConfigurationClasses(x, configurationParameterTypeUsing, defaultValueForGenericTypeParam)); + } } From a22cace4f657bf9e60d643495cbd774676c0cb02 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 13 Mar 2023 11:10:55 -0400 Subject: [PATCH 03/19] - code linting Signed-off-by: Vincent Biret --- .../Writers/Go/CodeMethodWriter.cs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index d485acd44f..4ce1050cf7 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -519,22 +519,17 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho var setterName = propWithDefault.SetterFromCurrentOrBaseType?.Name.ToFirstCharacterUpperCase() is string sName && !string.IsNullOrEmpty(sName) ? sName : $"Set{propWithDefault.SymbolName.ToFirstCharacterUpperCase()}"; writer.WriteLine($"m.{setterName}({defaultValueReference})"); } - if (parentClass.IsOfKind(CodeClassKind.RequestBuilder)) - { - if (currentMethod.IsOfKind(CodeMethodKind.Constructor)) - { - if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam && - parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) - conventions.AddParametersAssignment(writer, - pathParametersParam.Type.AllTypes.OfType().FirstOrDefault(), - pathParametersParam.Name.ToFirstCharacterLowerCase(), - $"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", - currentMethod.Parameters - .Where(static x => x.IsOfKind(CodeParameterKind.Path)) - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) - .ToArray()); - } - } + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && currentMethod.IsOfKind(CodeMethodKind.Constructor) && + currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam && + parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) + conventions.AddParametersAssignment(writer, + pathParametersParam.Type.AllTypes.OfType().FirstOrDefault(), + pathParametersParam.Name.ToFirstCharacterLowerCase(), + $"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", + currentMethod.Parameters + .Where(static x => x.IsOfKind(CodeParameterKind.Path)) + .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .ToArray()); } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer, CodeClass parentClass) { From fa8838ccb44a083c00e47f529748981c89693d9e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 13 Mar 2023 13:41:39 -0400 Subject: [PATCH 04/19] - moves request builder properties to base in java --- src/Kiota.Builder/Refiners/JavaRefiner.cs | 10 ++++ .../Writers/Java/CodeMethodWriter.cs | 55 ++++++++----------- .../Writers/Java/CodePropertyWriter.cs | 2 + .../Writers/Java/JavaConventionService.cs | 10 +++- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/Kiota.Builder/Refiners/JavaRefiner.cs b/src/Kiota.Builder/Refiners/JavaRefiner.cs index 124afd6201..9344460050 100644 --- a/src/Kiota.Builder/Refiners/JavaRefiner.cs +++ b/src/Kiota.Builder/Refiners/JavaRefiner.cs @@ -18,6 +18,16 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance { cancellationToken.ThrowIfCancellationRequested(); LowerCaseNamespaceNames(generatedCode); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "BaseRequestBuilder", + Declaration = new CodeType + { + Name = "com.microsoft.kiota", + IsExternal = true + } + }); var reservedNamesProvider = new JavaReservedNamesProvider(); CorrectNames(generatedCode, s => { diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs index f2363e44d0..9d95ff2430 100644 --- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs @@ -254,7 +254,7 @@ private void WriteRequestBuilderBody(CodeClass parentClass, CodeMethod codeEleme private static void AddNullChecks(CodeMethod codeElement, LanguageWriter writer) { if (!codeElement.IsOverload) - foreach (var parameter in codeElement.Parameters.Where(static x => !x.Optional).OrderBy(static x => x.Name)) + foreach (var parameter in codeElement.Parameters.Where(static x => !x.Optional && !x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.PathParameters)).OrderBy(static x => x.Name)) writer.WriteLine($"Objects.requireNonNull({parameter.Name.ToFirstCharacterLowerCase()});"); } private static void WriteRequestBuilderConstructorCall(CodeMethod codeElement, LanguageWriter writer) @@ -293,10 +293,18 @@ private static void WriteSerializationRegistration(HashSet serialization private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMethod, LanguageWriter writer, bool inherits) { if (inherits) - writer.WriteLine("super();"); + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && + parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && + !string.IsNullOrEmpty(urlTemplateProperty.DefaultValue)) + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) + writer.WriteLine($"super({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}, {pathParametersParameter.Name.ToFirstCharacterLowerCase()});"); + else + writer.WriteLine($"super({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue});"); + else + writer.WriteLine("super();"); foreach (var propWithDefault in parentClass.GetPropertiesOfKind(CodePropertyKind.BackingStore, CodePropertyKind.RequestBuilder, - CodePropertyKind.UrlTemplate, CodePropertyKind.PathParameters) .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) .OrderBy(static x => x.Name)) @@ -317,42 +325,27 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho } writer.WriteLine($"this.{setterName}({defaultValue});"); } - if (parentClass.IsOfKind(CodeClassKind.RequestBuilder)) + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp) { if (currentMethod.IsOfKind(CodeMethodKind.Constructor) && currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) { - conventions.AddParametersAssignment(writer, - pathParametersParam.Type, - pathParametersParam.Name.ToFirstCharacterLowerCase(), - currentMethod.Parameters - .Where(x => x.IsOfKind(CodeParameterKind.Path)) - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) - .ToArray()); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); + var pathParameters = currentMethod.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path)); + if (pathParameters.Any()) + conventions.AddParametersAssignment(writer, + pathParametersParam.Type, + pathParametersParam.Name.ToFirstCharacterLowerCase(), + $"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.", + pathParameters + .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .ToArray()); } else if (currentMethod.IsOfKind(CodeMethodKind.RawUrlConstructor) && - parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp && currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl) is CodeParameter rawUrlParam) { - conventions.AddParametersAssignment(writer, - pathParametersProp.Type, - string.Empty, - (rawUrlParam.Type, Constants.RawUrlParameterName, rawUrlParam.Name.ToFirstCharacterLowerCase())); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); + writer.WriteLine($"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.put(\"{Constants.RawUrlParameterName}\", Objects.requireNonNull({rawUrlParam.Name.ToFirstCharacterLowerCase()}));"); } - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.RequestAdapter, CodePropertyKind.RequestAdapter, writer); - } - } - private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? variableName = default) - { - if (parentClass.GetPropertyOfKind(propertyKind) is CodeProperty property) - { - var parameter = currentMethod.Parameters.FirstOrDefault(x => x.IsOfKind(parameterKind)); - if (!string.IsNullOrEmpty(variableName)) - writer.WriteLine($"this.{property.Name.ToFirstCharacterLowerCase()} = {variableName};"); - else if (parameter != null) - writer.WriteLine($"this.{property.Name.ToFirstCharacterLowerCase()} = {parameter.Name};"); } } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer, CodeClass parentClass) @@ -387,7 +380,7 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, Lan { if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty && codeElement.OriginalIndexer != null) conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"this.{pathParametersProperty.Name}", - (codeElement.OriginalIndexer.IndexType, codeElement.OriginalIndexer.SerializationName, "id")); + parameters: (codeElement.OriginalIndexer.IndexType, codeElement.OriginalIndexer.SerializationName, "id")); conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName); } private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer, bool inherits) diff --git a/src/Kiota.Builder/Writers/Java/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/Java/CodePropertyWriter.cs index 69ce645106..f763c5841d 100644 --- a/src/Kiota.Builder/Writers/Java/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/Java/CodePropertyWriter.cs @@ -8,6 +8,8 @@ public class CodePropertyWriter : BaseElementWriter "urlTplParams"; - internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, params (CodeTypeBase, string, string)[] parameters) + internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, string varName = "", params (CodeTypeBase, string, string)[] parameters) { if (pathParametersType == null) return; var mapTypeName = pathParametersType.Name; - writer.WriteLine($"final {mapTypeName} {TempDictionaryVarName} = new {mapTypeName}({pathParametersReference});"); + if (string.IsNullOrEmpty(varName)) + { + varName = TempDictionaryVarName; + writer.WriteLine($"final {mapTypeName} {varName} = new {mapTypeName}({pathParametersReference});"); + } if (parameters.Any()) writer.WriteLines(parameters.Select(p => - $"{TempDictionaryVarName}.put(\"{p.Item2}\", {p.Item3});" + $"{varName}.put(\"{p.Item2}\", {p.Item3});" ).ToArray()); } #pragma warning restore CA1822 // Method should be static From 0d2e012424b6dfab0c252db891eec07d5863edb0 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 13 Mar 2023 14:17:27 -0400 Subject: [PATCH 05/19] - moves redundant java request configuration properties Signed-off-by: Vincent Biret --- .../CodeDOM/ProprietableBlock.cs | 8 +++++++ .../Refiners/CommonLanguageRefiner.cs | 17 ++++++++++++++ src/Kiota.Builder/Refiners/JavaRefiner.cs | 23 ++++++++----------- .../Writers/Java/CodeMethodWriter.cs | 14 ++--------- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/Kiota.Builder/CodeDOM/ProprietableBlock.cs b/src/Kiota.Builder/CodeDOM/ProprietableBlock.cs index 852b03e5da..35ad10a28a 100644 --- a/src/Kiota.Builder/CodeDOM/ProprietableBlock.cs +++ b/src/Kiota.Builder/CodeDOM/ProprietableBlock.cs @@ -39,6 +39,14 @@ public virtual IEnumerable AddProperty(params CodeProperty[] prope throw new ArgumentOutOfRangeException(nameof(properties)); return AddRange(properties); } + public void RemovePropertiesOfKind(params CodePropertyKind[] kind) + { + if (kind == null || !kind.Any()) + throw new ArgumentNullException(nameof(kind)); + var propertiesToRemove = Properties.Where(x => x.IsOfKind(kind)).ToList(); + foreach (var property in propertiesToRemove) + RemoveChildElement(property); + } #nullable disable public T Kind { diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index ffa25800cc..0d9e6c6d44 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -1431,6 +1431,23 @@ protected static void MoveRequestBuilderPropertiesToBaseType(CodeElement current CrawlTree(currentElement, x => MoveRequestBuilderPropertiesToBaseType(x, baseTypeUsing, accessModifier)); } + protected static void RemoveRequestConfigurationClassesCommonProperties(CodeElement currentElement, CodeUsing baseTypeUsing) + { + if (currentElement is CodeClass currentClass && currentClass.IsOfKind(CodeClassKind.RequestConfiguration)) + { + if (currentClass.StartBlock.Inherits == null) + { + currentClass.StartBlock.Inherits = new CodeType + { + Name = baseTypeUsing.Name + }; + currentClass.AddUsing(baseTypeUsing); + } + currentClass.RemovePropertiesOfKind(CodePropertyKind.Headers, CodePropertyKind.Options); + } + + CrawlTree(currentElement, x => RemoveRequestConfigurationClassesCommonProperties(x, baseTypeUsing)); + } protected static void RemoveRequestConfigurationClasses(CodeElement currentElement, CodeUsing configurationParameterTypeUsing, CodeType defaultValueForGenericTypeParam) { if (currentElement is CodeClass currentClass && currentClass.IsOfKind(CodeClassKind.RequestConfiguration) && diff --git a/src/Kiota.Builder/Refiners/JavaRefiner.cs b/src/Kiota.Builder/Refiners/JavaRefiner.cs index 9344460050..f62aa10dfc 100644 --- a/src/Kiota.Builder/Refiners/JavaRefiner.cs +++ b/src/Kiota.Builder/Refiners/JavaRefiner.cs @@ -28,6 +28,16 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance IsExternal = true } }); + RemoveRequestConfigurationClassesCommonProperties(generatedCode, + new CodeUsing + { + Name = "BaseRequestConfiguration", + Declaration = new CodeType + { + Name = "com.microsoft.kiota", + IsExternal = true + } + }); var reservedNamesProvider = new JavaReservedNamesProvider(); CorrectNames(generatedCode, s => { @@ -216,16 +226,12 @@ private static void AddEnumSetImport(CodeElement currentElement) "com.microsoft.kiota.store", "BackingStoreFactory", "BackingStoreFactorySingleton"), new (static x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.BackingStore), "com.microsoft.kiota.store", "BackingStore", "BackedModel", "BackingStoreFactorySingleton"), - new (static x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Options), - "java.util", "Collections"), new (static x => x is CodeProperty prop && "decimal".Equals(prop.Type.Name, StringComparison.OrdinalIgnoreCase) || x is CodeMethod method && "decimal".Equals(method.ReturnType.Name, StringComparison.OrdinalIgnoreCase) || x is CodeParameter para && "decimal".Equals(para.Type.Name, StringComparison.OrdinalIgnoreCase), "java.math", "BigDecimal"), new (static x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.QueryParameter) && !string.IsNullOrEmpty(prop.SerializationName), "com.microsoft.kiota", "QueryParameter"), - new (static x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Headers), - "com.microsoft.kiota", "RequestHeaders"), new (static x => x is CodeClass @class && @class.OriginalComposedType is CodeIntersectionType intersectionType && intersectionType.Types.Any(static y => !y.IsExternal), "com.microsoft.kiota.serialization", "ParseNodeHelper"), }; @@ -238,15 +244,6 @@ private static void CorrectPropertyType(CodeProperty currentProperty) } else if (currentProperty.IsOfKind(CodePropertyKind.BackingStore)) currentProperty.Type.Name = currentProperty.Type.Name[1..]; // removing the "I" - else if (currentProperty.IsOfKind(CodePropertyKind.Options)) - { - currentProperty.Type.Name = "java.util.List"; //fully qualified name to avoid conflict with generated types - currentProperty.DefaultValue = "Collections.emptyList()"; - } - else if (currentProperty.IsOfKind(CodePropertyKind.Headers)) - { - currentProperty.DefaultValue = $"new {currentProperty.Type.Name.ToFirstCharacterUpperCase()}()"; - } else if (currentProperty.IsOfKind(CodePropertyKind.QueryParameter)) currentProperty.DefaultValue = $"new {currentProperty.Type.Name.ToFirstCharacterUpperCase()}()"; else if (currentProperty.IsOfKind(CodePropertyKind.AdditionalData)) diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs index 9d95ff2430..02af0e7a90 100644 --- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs @@ -553,23 +553,13 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req writer.WriteLines($"final {requestConfigTypeName} {RequestConfigVarName} = new {requestConfigTypeName}();", $"{requestParams.requestConfiguration.Name}.accept({RequestConfigVarName});"); var queryString = requestParams.QueryParameters; - var headers = requestParams.Headers; - var options = requestParams.Options; if (queryString != null) { var queryStringName = $"{RequestConfigVarName}.{queryString.Name.ToFirstCharacterLowerCase()}"; writer.WriteLine($"{RequestInfoVarName}.addQueryParameters({queryStringName});"); } - if (headers != null) - { - var headersName = $"{RequestConfigVarName}.{headers.Name.ToFirstCharacterLowerCase()}"; - writer.WriteLine($"{RequestInfoVarName}.headers.putAll({headersName});"); - } - if (options != null) - { - var optionsName = $"{RequestConfigVarName}.{options.Name.ToFirstCharacterLowerCase()}"; - writer.WriteLine($"{RequestInfoVarName}.addRequestOptions({optionsName});"); - } + writer.WriteLines($"{RequestInfoVarName}.headers.putAll({RequestConfigVarName}.headers);", + $"{RequestInfoVarName}.addRequestOptions({RequestConfigVarName}.options);"); writer.CloseBlock(); } From 700d8aff3fb6cda8fb9273d04f1ec3fcc35e35b4 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 14 Mar 2023 14:59:41 -0400 Subject: [PATCH 06/19] - removes request builder properties for ruby Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/RubyRefiner.cs | 10 +++++ .../Writers/Ruby/CodeMethodWriter.cs | 39 +++++++------------ .../Writers/Ruby/CodePropertyWriter.cs | 1 + 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Kiota.Builder/Refiners/RubyRefiner.cs b/src/Kiota.Builder/Refiners/RubyRefiner.cs index 25550fc65f..047b294d54 100644 --- a/src/Kiota.Builder/Refiners/RubyRefiner.cs +++ b/src/Kiota.Builder/Refiners/RubyRefiner.cs @@ -18,6 +18,16 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance { cancellationToken.ThrowIfCancellationRequested(); ReplaceIndexersByMethodsWithParameter(generatedCode, false, "_by_id"); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "MicrosoftKiotaAbstractions::BaseRequestBuilder", + Declaration = new CodeType + { + Name = "MicrosoftKiotaAbstractions", + IsExternal = true + } + }); var classesToDisambiguate = new HashSet(); var suffix = "Model"; DisambiguateClassesWithNamespaceNames(generatedCode, classesToDisambiguate, suffix); diff --git a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs index 955611396f..e1dbb9c0da 100644 --- a/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs @@ -98,7 +98,7 @@ private static void AddNullChecks(CodeMethod codeElement, LanguageWriter writer) { if (!codeElement.IsOverload) foreach (var parameter in codeElement.Parameters - .Where(static x => !x.Optional) + .Where(static x => !x.Optional && !x.IsOfKind(CodeParameterKind.PathParameters, CodeParameterKind.RequestAdapter)) .Select(static x => x.Name.ToSnakeCase()) .OrderBy(static x => x)) writer.WriteLine($"raise StandardError, '{parameter} cannot be null' if {parameter}.nil?"); @@ -133,8 +133,6 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me var requestAdapterPropertyName = $"{requestAdapterProperty?.NamePrefix}{requestAdapterProperty?.Name.ToSnakeCase()}"; WriteSerializationRegistration(parentClass, method.SerializerModules, writer, "register_default_serializer"); WriteSerializationRegistration(parentClass, method.DeserializerModules, writer, "register_default_deserializer"); - if (method.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.RequestAdapter)) is CodeParameter requestAdapterParameter) - writer.WriteLine($"@{requestAdapterPropertyName} = {requestAdapterParameter.Name.ToSnakeCase()}"); if (!string.IsNullOrEmpty(method.BaseUrl)) { writer.StartBlock($"if @{requestAdapterPropertyName}.get_base_url.nil? || @{requestAdapterPropertyName}.get_base_url.empty?"); @@ -158,11 +156,18 @@ private static void WriteSerializationRegistration(CodeClass parentClass, HashSe private static void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMethod, LanguageWriter writer, bool inherits) { if (inherits) - writer.WriteLine("super"); + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && + parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && + !string.IsNullOrEmpty(urlTemplateProperty.DefaultValue)) + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) + writer.WriteLine($"super({pathParametersParameter.Name.ToSnakeCase()}, {requestAdapterParameter.Name.ToSnakeCase()}, {urlTemplateProperty.DefaultValue})"); + else + writer.WriteLine($"super(Hash.new, {requestAdapterParameter.Name.ToSnakeCase()}, {urlTemplateProperty.DefaultValue})"); + else + writer.WriteLine("super"); foreach (var propWithDefault in parentClass.GetPropertiesOfKind(CodePropertyKind.BackingStore, - CodePropertyKind.RequestBuilder, - CodePropertyKind.UrlTemplate, - CodePropertyKind.PathParameters) + CodePropertyKind.RequestBuilder) .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) .OrderBy(static x => x.Name)) { @@ -177,22 +182,6 @@ private static void WriteConstructorBody(CodeClass parentClass, CodeMethod curre { writer.WriteLine($"@{propWithDefault.NamePrefix}{propWithDefault.Name.ToSnakeCase()} = {propWithDefault.DefaultValue}"); } - if (currentMethod.IsOfKind(CodeMethodKind.Constructor)) - { - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.RequestAdapter, CodePropertyKind.RequestAdapter, writer); - var pathParametersParamName = currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters)?.Name.ToSnakeCase(); - if (parentClass.IsOfKind(CodeClassKind.RequestBuilder)) - writer.WriteLine($"{pathParametersParamName} = {{ \"request-raw-url\" => {pathParametersParamName} }} if {pathParametersParamName}.is_a? String"); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, $" if {pathParametersParamName}.is_a? Hash"); - } - } - private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? controlSuffix = default) - { - if (parentClass.GetPropertyOfKind(propertyKind) is CodeProperty property && - currentMethod.Parameters.FirstOrDefault(x => x.IsOfKind(parameterKind)) is CodeParameter parameter) - { - writer.WriteLine($"@{property.NamePrefix}{property.Name.ToSnakeCase()} = {parameter.Name.ToSnakeCase()}{controlSuffix}"); - } } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer) { @@ -356,8 +345,8 @@ private void WriteMethodDocumentation(CodeMethod code, LanguageWriter writer) writer.WriteLine(conventions.DocCommentStart); if (isDescriptionPresent) writer.WriteLine($"{conventions.DocCommentPrefix}{RubyConventionService.RemoveInvalidDescriptionCharacters(code.Documentation.Description)}"); - foreach (var paramWithDescription in parametersWithDescription.OrderBy(static x => x.Name)) - writer.WriteLine($"{conventions.DocCommentPrefix}@param {paramWithDescription.Name} {RubyConventionService.RemoveInvalidDescriptionCharacters(paramWithDescription.Documentation.Description)}"); + foreach (var paramWithDescription in parametersWithDescription.OrderBy(static x => x.Name, StringComparer.OrdinalIgnoreCase)) + writer.WriteLine($"{conventions.DocCommentPrefix}@param {paramWithDescription.Name.ToSnakeCase()} {RubyConventionService.RemoveInvalidDescriptionCharacters(paramWithDescription.Documentation.Description)}"); if (code.IsAsync) writer.WriteLine($"{conventions.DocCommentPrefix}@return a Fiber of {code.ReturnType.Name.ToSnakeCase()}"); diff --git a/src/Kiota.Builder/Writers/Ruby/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/Ruby/CodePropertyWriter.cs index a054664a8f..703c66132c 100644 --- a/src/Kiota.Builder/Writers/Ruby/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/Ruby/CodePropertyWriter.cs @@ -8,6 +8,7 @@ public class CodePropertyWriter : BaseElementWriter Date: Tue, 14 Mar 2023 15:55:10 -0400 Subject: [PATCH 07/19] - removes request configuration for ruby --- src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs | 6 +++--- src/Kiota.Builder/Refiners/RubyRefiner.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index 0d9e6c6d44..0c889274c2 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -1448,7 +1448,7 @@ protected static void RemoveRequestConfigurationClassesCommonProperties(CodeElem CrawlTree(currentElement, x => RemoveRequestConfigurationClassesCommonProperties(x, baseTypeUsing)); } - protected static void RemoveRequestConfigurationClasses(CodeElement currentElement, CodeUsing configurationParameterTypeUsing, CodeType defaultValueForGenericTypeParam) + protected static void RemoveRequestConfigurationClasses(CodeElement currentElement, CodeUsing? configurationParameterTypeUsing = null, CodeType? defaultValueForGenericTypeParam = null) { if (currentElement is CodeClass currentClass && currentClass.IsOfKind(CodeClassKind.RequestConfiguration) && currentClass.Parent is CodeClass parentClass) @@ -1458,10 +1458,10 @@ protected static void RemoveRequestConfigurationClasses(CodeElement currentEleme .SelectMany(static x => x.Parameters) .Where(x => x.IsOfKind(CodeParameterKind.RequestConfiguration) && x.Type is CodeType type && type.TypeDefinition == currentClass) .ToArray(); - if (configurationParameters.Any()) + var genericTypeParamValue = currentClass.Properties.OfKind(CodePropertyKind.QueryParameters)?.Type as CodeType ?? defaultValueForGenericTypeParam; + if (configurationParameterTypeUsing != null && genericTypeParamValue != null && configurationParameters.Any()) { parentClass.AddUsing(configurationParameterTypeUsing); - var genericTypeParamValue = currentClass.Properties.OfKind(CodePropertyKind.QueryParameters)?.Type as CodeType ?? defaultValueForGenericTypeParam; var configurationParameterType = new CodeType { Name = configurationParameterTypeUsing.Name, diff --git a/src/Kiota.Builder/Refiners/RubyRefiner.cs b/src/Kiota.Builder/Refiners/RubyRefiner.cs index 047b294d54..c431e1e19b 100644 --- a/src/Kiota.Builder/Refiners/RubyRefiner.cs +++ b/src/Kiota.Builder/Refiners/RubyRefiner.cs @@ -28,6 +28,7 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance IsExternal = true } }); + RemoveRequestConfigurationClasses(generatedCode); var classesToDisambiguate = new HashSet(); var suffix = "Model"; DisambiguateClassesWithNamespaceNames(generatedCode, classesToDisambiguate, suffix); From 3dfe841bb743351cb091086e1916aa80c9cbaf03 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 15 Mar 2023 15:13:31 -0400 Subject: [PATCH 08/19] - removes java raw url instruction Signed-off-by: Vincent Biret --- .../Writers/Java/CodeMethodWriter.cs | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs index 02af0e7a90..502e02fd7c 100644 --- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs @@ -297,10 +297,14 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && !string.IsNullOrEmpty(urlTemplateProperty.DefaultValue)) + { + var thirdParameterName = string.Empty; if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) - writer.WriteLine($"super({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}, {pathParametersParameter.Name.ToFirstCharacterLowerCase()});"); - else - writer.WriteLine($"super({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue});"); + thirdParameterName = $", {pathParametersParameter.Name}"; + else if (currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl) is CodeParameter rawUrlParameter) + thirdParameterName = $", {rawUrlParameter.Name}"; + writer.WriteLine($"super({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}{thirdParameterName});"); + } else writer.WriteLine("super();"); foreach (var propWithDefault in parentClass.GetPropertiesOfKind(CodePropertyKind.BackingStore, @@ -326,26 +330,19 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho writer.WriteLine($"this.{setterName}({defaultValue});"); } if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && - parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp) - { - if (currentMethod.IsOfKind(CodeMethodKind.Constructor) && + parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp && + currentMethod.IsOfKind(CodeMethodKind.Constructor) && currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) - { - var pathParameters = currentMethod.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path)); - if (pathParameters.Any()) - conventions.AddParametersAssignment(writer, - pathParametersParam.Type, - pathParametersParam.Name.ToFirstCharacterLowerCase(), - $"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.", - pathParameters - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) - .ToArray()); - } - else if (currentMethod.IsOfKind(CodeMethodKind.RawUrlConstructor) && - currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl) is CodeParameter rawUrlParam) - { - writer.WriteLine($"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.put(\"{Constants.RawUrlParameterName}\", Objects.requireNonNull({rawUrlParam.Name.ToFirstCharacterLowerCase()}));"); - } + { + var pathParameters = currentMethod.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path)); + if (pathParameters.Any()) + conventions.AddParametersAssignment(writer, + pathParametersParam.Type, + pathParametersParam.Name.ToFirstCharacterLowerCase(), + $"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.", + pathParameters + .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .ToArray()); } } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer, CodeClass parentClass) From 28cb3adc30ed3f74a920e10535039578806a9888 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 15 Mar 2023 15:53:30 -0400 Subject: [PATCH 09/19] - go moves path parameters copy to abstractions Signed-off-by: Vincent Biret --- src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs | 10 ++++++++-- src/Kiota.Builder/Writers/Go/GoConventionService.cs | 11 +++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index 4ce1050cf7..35fe40900c 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -485,7 +485,12 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty) - writer.WriteLine($"{parentClassName}: *{newMethodName}({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}),"); + { + var pathParametersValue = ", map[string]string{}"; + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) + pathParametersValue = $", {pathParametersParameter.Name.ToFirstCharacterLowerCase()}"; + writer.WriteLine($"{parentClassName}: *{newMethodName}({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}{pathParametersValue}),"); + } else writer.WriteLine($"{parentClassName}: *{newMethodName}(),"); writer.DecreaseIndent(); @@ -526,6 +531,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho pathParametersParam.Type.AllTypes.OfType().FirstOrDefault(), pathParametersParam.Name.ToFirstCharacterLowerCase(), $"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", + false, currentMethod.Parameters .Where(static x => x.IsOfKind(CodeParameterKind.Path)) .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) @@ -546,7 +552,7 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, Lan { var pathParameters = codeElement.Parameters.Where(static x => x.IsOfKind(CodeMethod.ParameterKindForConvertedIndexers)); if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) - conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", parameters: pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); + conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", string.Empty, true, pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName, codeElement.Parameters.Except(pathParameters).ToArray()); } private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer, bool inherits) diff --git a/src/Kiota.Builder/Writers/Go/GoConventionService.cs b/src/Kiota.Builder/Writers/Go/GoConventionService.cs index d1ca429316..2c4e556122 100644 --- a/src/Kiota.Builder/Writers/Go/GoConventionService.cs +++ b/src/Kiota.Builder/Writers/Go/GoConventionService.cs @@ -189,16 +189,19 @@ internal void AddRequestBuilderBody(CodeClass parentClass, string returnType, La writer.WriteLines($"return {moduleName}New{constructorName}Internal({urlTemplateParams}, m.BaseRequestBuilder.{requestAdapterProp.Name.ToFirstCharacterUpperCase()}{pathParametersSuffix})"); } public override string TempDictionaryVarName => "urlTplParams"; - internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase? pathParametersType, string pathParametersReference, string pathParametersTarget = "", params (CodeTypeBase, string, string)[] parameters) + internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase? pathParametersType, string pathParametersReference, string pathParametersTarget, bool copyMap, params (CodeTypeBase, string, string)[] parameters) { if (pathParametersType == null) return; var mapTypeName = pathParametersType.Name; var isTempTarget = string.IsNullOrEmpty(pathParametersTarget); if (isTempTarget) writer.WriteLine($"{TempDictionaryVarName} := make({mapTypeName})"); - writer.StartBlock($"for idx, item := range {pathParametersReference} {{"); - writer.WriteLine($"{(isTempTarget ? TempDictionaryVarName : pathParametersTarget)}[idx] = item"); - writer.CloseBlock(); + if (copyMap) + { + writer.StartBlock($"for idx, item := range {pathParametersReference} {{"); + writer.WriteLine($"{(isTempTarget ? TempDictionaryVarName : pathParametersTarget)}[idx] = item"); + writer.CloseBlock(); + } foreach (var p in parameters) { var isStringStruct = !p.Item1.IsNullable && p.Item1.Name.Equals("string", StringComparison.OrdinalIgnoreCase); From 8082cc5eb12d0c57631504367114939880659cdc Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 17 Mar 2023 15:57:33 -0400 Subject: [PATCH 10/19] - removes unnecessary properties from typescript request builders Signed-off-by: Vincent Biret --- .../Refiners/TypeScriptRefiner.cs | 14 ++++- .../Writers/TypeScript/CodeMethodWriter.cs | 61 +++++++++---------- .../Writers/TypeScript/CodePropertyWriter.cs | 2 + .../TypeScript/TypeScriptConventionService.cs | 10 ++- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs b/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs index 2b0be2efd1..8675fef80e 100644 --- a/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs +++ b/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs @@ -16,6 +16,16 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance return Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "BaseRequestBuilder", + Declaration = new CodeType + { + Name = "@microsoft/kiota-abstractions", + IsExternal = true + } + }); ReplaceIndexersByMethodsWithParameter(generatedCode, false, "ById"); RemoveCancellationParameter(generatedCode); CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType, CorrectImplements); @@ -184,7 +194,7 @@ currentInterface.StartBlock is InterfaceDeclaration interfaceDeclaration && AbstractionsPackageName, "SerializationWriter"), new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Deserializer, CodeMethodKind.Factory), AbstractionsPackageName, "ParseNode"), - new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Constructor, CodeMethodKind.ClientConstructor, CodeMethodKind.IndexerBackwardCompatibility), + new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.IndexerBackwardCompatibility), AbstractionsPackageName, "getPathParameters"), new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.RequestExecutor), AbstractionsPackageName, "Parsable", "ParsableFactory"), @@ -222,7 +232,7 @@ private static void CorrectPropertyType(CodeProperty currentProperty) currentProperty.Type.IsNullable = false; currentProperty.Type.Name = "Record"; if (!string.IsNullOrEmpty(currentProperty.DefaultValue)) - currentProperty.DefaultValue = "{}"; + currentProperty.DefaultValue = string.Empty; } CorrectCoreTypes(currentProperty.Parent as CodeClass, DateTypesReplacements, currentProperty.Type); } diff --git a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs index d2e6b369bb..8b9a3a4815 100644 --- a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs @@ -104,7 +104,9 @@ internal static void WriteDefensiveStatements(CodeMethod codeElement, LanguageWr { if (codeElement.IsOfKind(CodeMethodKind.Setter)) return; - foreach (var parameter in codeElement.Parameters.Where(x => !x.Optional).OrderBy(x => x.Name)) + foreach (var parameter in codeElement.Parameters + .Where(static x => !x.Optional && !x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.PathParameters)) + .OrderBy(static x => x.Name)) { var parameterName = parameter.Name.ToFirstCharacterLowerCase(); writer.WriteLine($"if(!{parameterName}) throw new Error(\"{parameterName} cannot be undefined\");"); @@ -117,7 +119,7 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, str codeElement.OriginalIndexer != null) { localConventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"this.{pathParametersProperty.Name}", - (codeElement.OriginalIndexer.IndexType, codeElement.OriginalIndexer.SerializationName, "id")); + parameters: (codeElement.OriginalIndexer.IndexType, codeElement.OriginalIndexer.SerializationName, "id")); } conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName); } @@ -189,10 +191,21 @@ private CodePropertyKind[] SetterAccessProperties private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMethod, LanguageWriter writer, bool inherits) { if (inherits || parentClass.IsErrorDefinition) - writer.WriteLine("super();"); + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && + parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && + !string.IsNullOrEmpty(urlTemplateProperty.DefaultValue)) + { + var pathParametersValue = "{}"; + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) + pathParametersValue = pathParametersParameter.Name.ToFirstCharacterLowerCase(); + writer.WriteLine($"super({pathParametersValue}, {requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue});"); + } + else + writer.WriteLine("super();"); foreach (var propWithDefault in parentClass.GetPropertiesOfKind(DirectAccessProperties) - .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) + .Where(static x => !string.IsNullOrEmpty(x.DefaultValue) && !x.IsOfKind(CodePropertyKind.UrlTemplate)) .OrderByDescending(static x => x.Kind) .ThenBy(static x => x.Name)) { @@ -200,7 +213,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho } foreach (var propWithDefault in parentClass.GetPropertiesOfKind(SetterAccessProperties) - .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) + .Where(static x => !string.IsNullOrEmpty(x.DefaultValue) && !x.IsOfKind(CodePropertyKind.UrlTemplate)) // do not apply the default value if the type is composed as the default value may not necessarily which type to use .Where(static x => x.Type is not CodeType propType || propType.TypeDefinition is not CodeClass propertyClass || propertyClass.OriginalComposedType is null) .OrderByDescending(static x => x.Kind) @@ -208,33 +221,19 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho { writer.WriteLine($"this.{propWithDefault.Name.ToFirstCharacterLowerCase()} = {propWithDefault.DefaultValue};"); } - if (parentClass.IsOfKind(CodeClassKind.RequestBuilder)) - { - if (currentMethod.IsOfKind(CodeMethodKind.Constructor) && - currentMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.PathParameters)) is CodeParameter pathParametersParam) - { - localConventions?.AddParametersAssignment(writer, - pathParametersParam.Type.AllTypes.OfType().First(), - pathParametersParam.Name.ToFirstCharacterLowerCase(), - currentMethod.Parameters - .Where(x => x.IsOfKind(CodeParameterKind.Path)) - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) - .ToArray()); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); - } - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.RequestAdapter, CodePropertyKind.RequestAdapter, writer); - } - } - private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? variableName = default) - { - var property = parentClass.GetPropertyOfKind(propertyKind); - if (property != null) + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.IsOfKind(CodeMethodKind.Constructor) && + currentMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.PathParameters)) is CodeParameter pathParametersParam && + parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) { - var parameter = currentMethod.Parameters.FirstOrDefault(x => x.IsOfKind(parameterKind)); - if (!string.IsNullOrEmpty(variableName)) - writer.WriteLine($"this.{property.Name.ToFirstCharacterLowerCase()} = {variableName};"); - else if (parameter != null) - writer.WriteLine($"this.{property.Name.ToFirstCharacterLowerCase()} = {parameter.Name};"); + localConventions?.AddParametersAssignment(writer, + pathParametersParam.Type.AllTypes.OfType().First(), + pathParametersParam.Name.ToFirstCharacterLowerCase(), + $"this.{pathParametersProperty.Name.ToFirstCharacterLowerCase()}", + currentMethod.Parameters + .Where(static x => x.IsOfKind(CodeParameterKind.Path)) + .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .ToArray()); } } private static void WriteSetterBody(CodeMethod codeElement, LanguageWriter writer, CodeClass parentClass) diff --git a/src/Kiota.Builder/Writers/TypeScript/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodePropertyWriter.cs index 1374b496c8..78905d0f9d 100644 --- a/src/Kiota.Builder/Writers/TypeScript/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/TypeScript/CodePropertyWriter.cs @@ -7,6 +7,8 @@ public class CodePropertyWriter : BaseElementWriter "urlTplParams"; - internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, params (CodeTypeBase, string, string)[] parameters) + internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, string varName = "", params (CodeTypeBase, string, string)[] parameters) { if (pathParametersType == null) return; - writer.WriteLine($"const {TempDictionaryVarName} = getPathParameters({pathParametersReference});"); + if (string.IsNullOrEmpty(varName)) + { + varName = TempDictionaryVarName; + writer.WriteLine($"const {varName} = getPathParameters({pathParametersReference});"); + } if (parameters.Any()) writer.WriteLines(parameters.Select(p => - $"{TempDictionaryVarName}[\"{p.Item2}\"] = {p.Item3}" + $"{varName}[\"{p.Item2}\"] = {p.Item3}" ).ToArray()); } #pragma warning restore CA1822 // Method should be static From 0ccced1c2cfd5b68d9b5269e455aa63ccf04950e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 17 Mar 2023 16:18:51 -0400 Subject: [PATCH 11/19] - adds support policy amend for additions in request builder Signed-off-by: Vincent Biret --- docs/support.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/support.md b/docs/support.md index 4bb58b8351..8c314beae5 100644 --- a/docs/support.md +++ b/docs/support.md @@ -17,7 +17,7 @@ Major releases include new features, new public API surface area, and bug fixes. ### Minor releases -Minor releases also include new features, public API surface area, and bug fixes. The difference between these and major releases is that minor releases will not contain breaking changes to the tooling experience or the generated API surface area of GA maturity languages. Minor releases can install side by side with previous minor releases. Minor releases are targeted to publish on the first Tuesday of every month. +Minor releases also include new features, public API surface area, and bug fixes. The difference between these and major releases is that minor releases will not contain breaking changes to the tooling experience or the generated API surface area of stable maturity languages. Minor releases can install side by side with previous minor releases. Minor releases are targeted to publish on the first Tuesday of every month. ### Patches @@ -33,7 +33,7 @@ The following criteria is used to determine the maturity levels. - **Preview**: Kiota is at or near the level of table but hasn't been used to generate production API clients. - **Experimental**: Kiota provides some functionality for the language but is still in early stages. Some features may not work correctly or at all. -Breaking changes to languages that are stable will result in major version change for Kiota tooling. +Breaking changes to languages that are stable will result in major version change for Kiota tooling. Code generation changes to a stable maturity language are not considered breaking when they rely on additions in the corresponding abstractions library as these changes will only require to update the abstractions library the the latest minor/patch version under the same major version. The current status of language support can be queried by using the following command. From 635c890192b55b33d10cfad18dc5052fab1279a9 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Mar 2023 15:11:52 -0400 Subject: [PATCH 12/19] - CSharp request builder properties deduplication Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/CSharpRefiner.cs | 10 +++ .../Writers/CSharp/CSharpConventionService.cs | 10 ++- .../Writers/CSharp/CodeIndexerWriter.cs | 2 +- .../Writers/CSharp/CodeMethodWriter.cs | 61 +++++++++++-------- .../Writers/CSharp/CodePropertyWriter.cs | 1 + .../Writers/Java/CodeMethodWriter.cs | 6 +- 6 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/Kiota.Builder/Refiners/CSharpRefiner.cs b/src/Kiota.Builder/Refiners/CSharpRefiner.cs index b976384b77..de39136551 100644 --- a/src/Kiota.Builder/Refiners/CSharpRefiner.cs +++ b/src/Kiota.Builder/Refiners/CSharpRefiner.cs @@ -16,6 +16,16 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance return Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "BaseRequestBuilder", + Declaration = new CodeType + { + Name = "Microsoft.Kiota.Abstractions", + IsExternal = true + } + }); AddDefaultImports(generatedCode, defaultUsingEvaluators); CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType); MoveClassesWithNamespaceNamesUnderNamespace(generatedCode); diff --git a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs index 56f8a17ce0..8e7190096e 100644 --- a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs +++ b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs @@ -71,10 +71,14 @@ internal void AddRequestBuilderBody(CodeClass parentClass, string returnType, La } } public override string TempDictionaryVarName => "urlTplParams"; - internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, params (CodeTypeBase, string, string)[] parameters) + internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathParametersType, string pathParametersReference, string varName = "", params (CodeTypeBase, string, string)[] parameters) { if (pathParametersType == null) return; - writer.WriteLine($"var {TempDictionaryVarName} = new {pathParametersType.Name}({pathParametersReference});"); + if (string.IsNullOrEmpty(varName)) + { + varName = TempDictionaryVarName; + writer.WriteLine($"var {varName} = new {pathParametersType.Name}({pathParametersReference});"); + } if (parameters.Any()) { writer.WriteLines(parameters.Select(p => @@ -88,7 +92,7 @@ internal void AddParametersAssignment(LanguageWriter writer, CodeTypeBase pathPa else nullCheck = $"if ({identName} is not null) "; } - return $"{nullCheck}{TempDictionaryVarName}.Add(\"{name}\", {identName});"; + return $"{nullCheck}{varName}.Add(\"{name}\", {identName});"; }).ToArray()); } } diff --git a/src/Kiota.Builder/Writers/CSharp/CodeIndexerWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeIndexerWriter.cs index a450425b29..6c5fe5863f 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodeIndexerWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodeIndexerWriter.cs @@ -13,7 +13,7 @@ public override void WriteCodeElement(CodeIndexer codeElement, LanguageWriter wr conventions.WriteShortDescription(codeElement.Documentation.Description, writer); writer.StartBlock($"public {returnType} this[{conventions.GetTypeString(codeElement.IndexType, codeElement)} position] {{ get {{"); if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp) - conventions.AddParametersAssignment(writer, pathParametersProp.Type, pathParametersProp.Name.ToFirstCharacterUpperCase(), (codeElement.IndexType, codeElement.SerializationName, "position")); + conventions.AddParametersAssignment(writer, pathParametersProp.Type, pathParametersProp.Name.ToFirstCharacterUpperCase(), string.Empty, (codeElement.IndexType, codeElement.SerializationName, "position")); conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName, "return "); writer.CloseBlock("} }"); } diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs index 18e518c5f0..5367b5f384 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs @@ -22,7 +22,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri WriteMethodDocumentation(codeElement, writer); WriteMethodPrototype(codeElement, parentClass, writer, returnType, inherits, isVoid); writer.IncreaseIndent(); - foreach (var parameter in codeElement.Parameters.Where(x => !x.Optional).OrderBy(x => x.Name)) + foreach (var parameter in codeElement.Parameters.Where(static x => !x.Optional && !x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.PathParameters, CodeParameterKind.RawUrl)).OrderBy(static x => x.Name, StringComparer.OrdinalIgnoreCase)) { var parameterName = parameter.Name.ToFirstCharacterLowerCase(); if (nameof(String).Equals(parameter.Type.Name, StringComparison.OrdinalIgnoreCase) && parameter.Type.CollectionKind == CodeTypeBase.CodeTypeCollectionKind.None) @@ -189,7 +189,7 @@ private void WriteFactoryMethodBody(CodeMethod codeElement, CodeClass parentClas private void WriteRequestBuilderBody(CodeClass parentClass, CodeMethod codeElement, LanguageWriter writer) { var importSymbol = conventions.GetTypeString(codeElement.ReturnType, parentClass); - conventions.AddRequestBuilderBody(parentClass, importSymbol, writer, prefix: "return ", pathParameters: codeElement.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Path))); + conventions.AddRequestBuilderBody(parentClass, importSymbol, writer, prefix: "return ", pathParameters: codeElement.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path))); } private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod method, LanguageWriter writer) { @@ -220,7 +220,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho { foreach (var propWithDefault in parentClass .Properties - .Where(static x => !string.IsNullOrEmpty(x.DefaultValue)) + .Where(static x => !string.IsNullOrEmpty(x.DefaultValue) && !x.IsOfKind(CodePropertyKind.UrlTemplate, CodePropertyKind.PathParameters)) // do not apply the default value if the type is composed as the default value may not necessarily which type to use .Where(static x => x.Type is not CodeType propType || propType.TypeDefinition is not CodeClass propertyClass || propertyClass.OriginalComposedType is null) .OrderByDescending(static x => x.Kind) @@ -233,31 +233,21 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho } writer.WriteLine($"{propWithDefault.Name.ToFirstCharacterUpperCase()} = {defaultValue};"); } - if (parentClass.IsOfKind(CodeClassKind.RequestBuilder)) + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp && + currentMethod.IsOfKind(CodeMethodKind.Constructor) && + currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) { - if (currentMethod.IsOfKind(CodeMethodKind.Constructor) && - currentMethod.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.PathParameters)) is CodeParameter pathParametersParam) - { + var pathParameters = currentMethod.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path)); + if (pathParameters.Any()) conventions.AddParametersAssignment(writer, pathParametersParam.Type, pathParametersParam.Name.ToFirstCharacterLowerCase(), + pathParametersProp.Name.ToFirstCharacterUpperCase(), currentMethod.Parameters - .Where(x => x.IsOfKind(CodeParameterKind.Path)) - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .Where(static x => x.IsOfKind(CodeParameterKind.Path)) + .Select(static x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) .ToArray()); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); - } - else if (currentMethod.IsOfKind(CodeMethodKind.RawUrlConstructor) && - currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl) is CodeParameter rawUrlParam) - { - if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp) - conventions.AddParametersAssignment(writer, - pathParametersProp.Type, - string.Empty, - (rawUrlParam.Type, Constants.RawUrlParameterName, rawUrlParam.Name.ToFirstCharacterLowerCase())); - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.PathParameters, CodePropertyKind.PathParameters, writer, conventions.TempDictionaryVarName); - } - AssignPropertyFromParameter(parentClass, currentMethod, CodeParameterKind.RequestAdapter, CodePropertyKind.RequestAdapter, writer); } } private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? variableName = default) @@ -555,6 +545,29 @@ private void WriteMethodDocumentation(CodeMethod code, LanguageWriter writer) writer.WriteLine($"{conventions.DocCommentPrefix}{paramWithDescription.Documentation.Description.CleanupXMLString()}"); } private static readonly BaseCodeParameterOrderComparer parameterOrderComparer = new(); + private static string GetBaseSuffix(bool isConstructor, bool inherits, CodeClass parentClass, CodeMethod currentMethod) + { + if (isConstructor && inherits) + { + if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && + currentMethod.Parameters.OfKind(CodeParameterKind.RequestAdapter) is CodeParameter requestAdapterParameter && + parentClass.Properties.OfKind(CodePropertyKind.UrlTemplate) is CodeProperty urlTemplateProperty && + !string.IsNullOrEmpty(urlTemplateProperty.DefaultValue)) + { + var thirdParameterName = string.Empty; + if (currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParameter) + thirdParameterName = $", {pathParametersParameter.Name}"; + else if (currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl) is CodeParameter rawUrlParameter) + thirdParameterName = $", {rawUrlParameter.Name}"; + else if (parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty && !string.IsNullOrEmpty(pathParametersProperty.DefaultValue)) + thirdParameterName = $", {pathParametersProperty.DefaultValue}"; + return $" : base({requestAdapterParameter.Name.ToFirstCharacterLowerCase()}, {urlTemplateProperty.DefaultValue}{thirdParameterName})"; + } + return " : base()"; + } + + return string.Empty; + } private void WriteMethodPrototype(CodeMethod code, CodeClass parentClass, LanguageWriter writer, string returnType, bool inherits, bool isVoid) { var staticModifier = code.IsStatic ? "static " : string.Empty; @@ -570,9 +583,7 @@ private void WriteMethodPrototype(CodeMethod code, CodeClass parentClass, Langua var completeReturnType = isConstructor ? string.Empty : $"{asyncPrefix}{voidCorrectedTaskReturnType}{genericTypeSuffix} "; - var baseSuffix = string.Empty; - if (isConstructor && inherits) - baseSuffix = " : base()"; + var baseSuffix = GetBaseSuffix(isConstructor, inherits, parentClass, code); var parameters = string.Join(", ", code.Parameters.OrderBy(x => x, parameterOrderComparer).Select(p => conventions.GetParameterSignature(p, code)).ToList()); var methodName = isConstructor ? parentClass.Name.ToFirstCharacterUpperCase() : code.Name.ToFirstCharacterUpperCase(); var includeNullableReferenceType = code.IsOfKind(CodeMethodKind.RequestExecutor, CodeMethodKind.RequestGenerator); diff --git a/src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs index ba2aedc6a1..f4ec3a21dd 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs @@ -8,6 +8,7 @@ public class CodePropertyWriter : BaseElementWriter !x.Optional && !x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.PathParameters)).OrderBy(static x => x.Name)) + foreach (var parameter in codeElement.Parameters.Where(static x => !x.Optional && !x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.PathParameters)).OrderBy(static x => x.Name, StringComparer.OrdinalIgnoreCase)) writer.WriteLine($"Objects.requireNonNull({parameter.Name.ToFirstCharacterLowerCase()});"); } private static void WriteRequestBuilderConstructorCall(CodeMethod codeElement, LanguageWriter writer) @@ -332,7 +332,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho if (parentClass.IsOfKind(CodeClassKind.RequestBuilder) && parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProp && currentMethod.IsOfKind(CodeMethodKind.Constructor) && - currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) + currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam) { var pathParameters = currentMethod.Parameters.Where(static x => x.IsOfKind(CodeParameterKind.Path)); if (pathParameters.Any()) @@ -341,7 +341,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho pathParametersParam.Name.ToFirstCharacterLowerCase(), $"this.{pathParametersProp.Name.ToFirstCharacterLowerCase()}.", pathParameters - .Select(x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) + .Select(static x => (x.Type, string.IsNullOrEmpty(x.SerializationName) ? x.Name : x.SerializationName, x.Name.ToFirstCharacterLowerCase())) .ToArray()); } } From 14b1b227adf7e622fdcb595957c8ad01c5fe45f6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Mar 2023 15:50:00 -0400 Subject: [PATCH 13/19] - makes request configuration generic for shell Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/CSharpRefiner.cs | 16 ++++++++++++ .../Refiners/CommonLanguageRefiner.cs | 1 + src/Kiota.Builder/Refiners/ShellRefiner.cs | 25 +++++++++++++++++++ .../Writers/CSharp/CSharpConventionService.cs | 11 +++++--- .../Writers/CSharp/CodeMethodWriter.cs | 24 ++++++++++-------- .../Writers/Shell/ShellCodeMethodWriter.cs | 2 +- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/Kiota.Builder/Refiners/CSharpRefiner.cs b/src/Kiota.Builder/Refiners/CSharpRefiner.cs index de39136551..669b1f6a27 100644 --- a/src/Kiota.Builder/Refiners/CSharpRefiner.cs +++ b/src/Kiota.Builder/Refiners/CSharpRefiner.cs @@ -26,6 +26,22 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance IsExternal = true } }); + //TODO uncomment on the next major version + // RemoveRequestConfigurationClasses(generatedCode, + // new CodeUsing + // { + // Name = "RequestConfiguration", + // Declaration = new CodeType + // { + // Name = "Microsoft.Kiota.Abstractions", + // IsExternal = true + // } + // }, + // new CodeType + // { + // Name = "DefaultQueryParameters", + // IsExternal = true, + // }); AddDefaultImports(generatedCode, defaultUsingEvaluators); CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType); MoveClassesWithNamespaceNamesUnderNamespace(generatedCode); diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index 0c889274c2..dc261fb05d 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -1469,6 +1469,7 @@ protected static void RemoveRequestConfigurationClasses(CodeElement currentEleme foreach (var configurationParameter in configurationParameters) { var newType = (CodeType)configurationParameterType.Clone(); + newType.ActionOf = configurationParameter.Type.ActionOf; newType.GenericTypeParameterValues.Add(genericTypeParamValue); configurationParameter.Type = newType; } diff --git a/src/Kiota.Builder/Refiners/ShellRefiner.cs b/src/Kiota.Builder/Refiners/ShellRefiner.cs index eaa0996903..75e907e58e 100644 --- a/src/Kiota.Builder/Refiners/ShellRefiner.cs +++ b/src/Kiota.Builder/Refiners/ShellRefiner.cs @@ -20,6 +20,31 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance return Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); + MoveRequestBuilderPropertiesToBaseType(generatedCode, + new CodeUsing + { + Name = "BaseRequestBuilder", + Declaration = new CodeType + { + Name = "Microsoft.Kiota.Abstractions", + IsExternal = true + } + }); + RemoveRequestConfigurationClasses(generatedCode, + new CodeUsing + { + Name = "RequestConfiguration", + Declaration = new CodeType + { + Name = "Microsoft.Kiota.Abstractions", + IsExternal = true + } + }, + new CodeType + { + Name = "DefaultQueryParameters", + IsExternal = true, + }); AddDefaultImports(generatedCode, defaultUsingEvaluators); AddDefaultImports(generatedCode, additionalUsingEvaluators); CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType); diff --git a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs index 8e7190096e..c223156f5b 100644 --- a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs +++ b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs @@ -133,7 +133,7 @@ public override string GetTypeString(CodeTypeBase code, CodeElement targetElemen { return GetTypeString(code, targetElement, includeCollectionInformation, true); } - public string GetTypeString(CodeTypeBase code, CodeElement targetElement, bool includeCollectionInformation, bool includeNullableInformation) + public string GetTypeString(CodeTypeBase code, CodeElement targetElement, bool includeCollectionInformation, bool includeNullableInformation, bool includeActionInformation = true) { if (code is CodeComposedTypeBase) throw new InvalidOperationException($"CSharp does not support union types, the union type {code.Name} should have been filtered out by the refiner"); @@ -148,9 +148,12 @@ public string GetTypeString(CodeTypeBase code, CodeElement targetElement, bool i CodeTypeCollectionKind.Array when includeCollectionInformation => "[]", _ => string.Empty, }; - if (currentType.ActionOf) - return $"Action<{collectionPrefix}{typeName}{nullableSuffix}{collectionSuffix}>"; - return $"{collectionPrefix}{typeName}{nullableSuffix}{collectionSuffix}"; + var genericParameters = currentType.GenericTypeParameterValues.Any() ? + $"<{string.Join(", ", currentType.GenericTypeParameterValues.Select(x => GetTypeString(x, targetElement, includeCollectionInformation)))}>" : + string.Empty; + if (currentType.ActionOf && includeActionInformation) + return $"Action<{collectionPrefix}{typeName}{genericParameters}{nullableSuffix}{collectionSuffix}>"; + return $"{collectionPrefix}{typeName}{genericParameters}{nullableSuffix}{collectionSuffix}"; } throw new InvalidOperationException($"type of type {code.GetType()} is unknown"); diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs index 5367b5f384..f81ff0307c 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs @@ -8,7 +8,14 @@ namespace Kiota.Builder.Writers.CSharp; public class CodeMethodWriter : BaseElementWriter { - public CodeMethodWriter(CSharpConventionService conventionService) : base(conventionService) { } + /// + /// Flag to avoid pushing a breaking change, remove it and remove the condition that depends on it with V2 + /// + private readonly bool IsRequestConfigurationGeneric; + public CodeMethodWriter(CSharpConventionService conventionService, bool isRequestConfigurationGeneric = false) : base(conventionService) + { + IsRequestConfigurationGeneric = isRequestConfigurationGeneric; + } public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter writer) { ArgumentNullException.ThrowIfNull(codeElement); @@ -420,17 +427,14 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req if (requestParams.requestConfiguration != null) { writer.StartBlock($"if ({requestParams.requestConfiguration.Name} != null) {{"); - writer.WriteLines($"var {RequestConfigVarName} = new {requestParams.requestConfiguration.Type.Name.ToFirstCharacterUpperCase()}();", + var requestConfigType = conventions.GetTypeString(requestParams.requestConfiguration.Type, codeElement, false, true, false).ToFirstCharacterUpperCase(); + writer.WriteLines($"var {RequestConfigVarName} = new {requestConfigType}();", $"{requestParams.requestConfiguration.Name}.Invoke({RequestConfigVarName});"); var queryString = requestParams.QueryParameters; - var headers = requestParams.Headers; - var options = requestParams.Options; - if (queryString != null) - writer.WriteLine($"{RequestInfoVarName}.AddQueryParameters({RequestConfigVarName}.{queryString.Name.ToFirstCharacterUpperCase()});"); - if (options != null) - writer.WriteLine($"{RequestInfoVarName}.AddRequestOptions({RequestConfigVarName}.{options.Name.ToFirstCharacterUpperCase()});"); - if (headers != null) - writer.WriteLine($"{RequestInfoVarName}.AddHeaders({RequestConfigVarName}.{headers.Name.ToFirstCharacterUpperCase()});"); + if (queryString != null || IsRequestConfigurationGeneric) + writer.WriteLine($"{RequestInfoVarName}.AddQueryParameters({RequestConfigVarName}.QueryParameters);"); + writer.WriteLines($"{RequestInfoVarName}.AddRequestOptions({RequestConfigVarName}.Options);", + $"{RequestInfoVarName}.AddHeaders({RequestConfigVarName}.Headers);"); writer.CloseBlock(); } writer.WriteLine($"return {RequestInfoVarName};"); diff --git a/src/Kiota.Builder/Writers/Shell/ShellCodeMethodWriter.cs b/src/Kiota.Builder/Writers/Shell/ShellCodeMethodWriter.cs index 15be306222..872c350604 100644 --- a/src/Kiota.Builder/Writers/Shell/ShellCodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Shell/ShellCodeMethodWriter.cs @@ -37,7 +37,7 @@ partial class ShellCodeMethodWriter : CodeMethodWriter private const string JsonNoIndentParamName = "jsonNoIndent"; private const string InvocationContextParamName = "invocationContext"; - public ShellCodeMethodWriter(CSharpConventionService conventionService) : base(conventionService) + public ShellCodeMethodWriter(CSharpConventionService conventionService) : base(conventionService, true) { } From 6dad5fff876cf9a30a26f4c8c5d152bae7278a37 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Mar 2023 16:46:53 -0400 Subject: [PATCH 14/19] - fixes unit tests Signed-off-by: Vincent Biret --- .../Writers/Go/CodeMethodWriter.cs | 2 +- .../Writers/CSharp/CodeMethodWriterTests.cs | 24 +++++------ .../Writers/Go/CodeMethodWriterTests.cs | 43 ++++++++++--------- .../Writers/Java/CodeMethodWriterTests.cs | 20 +++++---- .../Writers/Ruby/CodeMethodWriterTests.cs | 2 +- .../TypeScript/CodeMethodWriterTests.cs | 3 +- 6 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index 35fe40900c..f2dba1e515 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -552,7 +552,7 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, Lan { var pathParameters = codeElement.Parameters.Where(static x => x.IsOfKind(CodeMethod.ParameterKindForConvertedIndexers)); if (parentClass.GetPropertyOfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) - conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", string.Empty, true, pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); + conventions.AddParametersAssignment(writer, pathParametersProperty.Type, $"m.BaseRequestBuilder.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", string.Empty, true, pathParameters.Select(static x => (x.Type, x.SerializationName, x.Name.ToFirstCharacterLowerCase())).ToArray()); conventions.AddRequestBuilderBody(parentClass, returnType, writer, conventions.TempDictionaryVarName, codeElement.Parameters.Except(pathParameters).ToArray()); } private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer, bool inherits) diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs index 4e93c441d6..e90b715401 100644 --- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs @@ -798,9 +798,9 @@ public void WritesRequestGeneratorBodyForNullableScalar() Assert.Contains("var requestConfig = new RequestConfig()", result); Assert.Contains("config.Invoke(requestConfig)", result); Assert.Contains("requestInfo.Headers.Add(\"Accept\", \"application/json\")", result); - Assert.Contains("requestInfo.AddHeaders(requestConfig.H)", result); - Assert.Contains("requestInfo.AddQueryParameters(requestConfig.Q)", result); - Assert.Contains("requestInfo.AddRequestOptions(requestConfig.O)", result); + Assert.Contains("requestInfo.AddHeaders(requestConfig.Headers)", result); + Assert.Contains("requestInfo.AddQueryParameters(requestConfig.QueryParameters)", result); + Assert.Contains("requestInfo.AddRequestOptions(requestConfig.Options)", result); Assert.Contains("SetContentFromScalar", result); Assert.Contains("return requestInfo;", result); AssertExtensions.CurlyBracesAreClosed(result, 1); @@ -824,9 +824,9 @@ public void WritesRequestGeneratorBodyForScalar() Assert.Contains("var requestConfig = new RequestConfig()", result); Assert.Contains("config.Invoke(requestConfig)", result); Assert.Contains("requestInfo.Headers.Add(\"Accept\", \"application/json\")", result); - Assert.Contains("requestInfo.AddHeaders(requestConfig.H)", result); - Assert.Contains("requestInfo.AddQueryParameters(requestConfig.Q)", result); - Assert.Contains("requestInfo.AddRequestOptions(requestConfig.O)", result); + Assert.Contains("requestInfo.AddHeaders(requestConfig.Headers)", result); + Assert.Contains("requestInfo.AddQueryParameters(requestConfig.QueryParameters)", result); + Assert.Contains("requestInfo.AddRequestOptions(requestConfig.Options)", result); Assert.Contains("SetContentFromScalar", result); Assert.Contains("return requestInfo;", result); Assert.Contains("async Task", result);//verify we only have one nullable marker @@ -851,9 +851,9 @@ public void WritesRequestGeneratorBodyForParsable() Assert.Contains("var requestConfig = new RequestConfig()", result); Assert.Contains("config.Invoke(requestConfig)", result); Assert.Contains("requestInfo.Headers.Add(\"Accept\", \"application/json\")", result); - Assert.Contains("requestInfo.AddHeaders(requestConfig.H)", result); - Assert.Contains("requestInfo.AddQueryParameters(requestConfig.Q)", result); - Assert.Contains("requestInfo.AddRequestOptions(requestConfig.O)", result); + Assert.Contains("requestInfo.AddHeaders(requestConfig.Headers)", result); + Assert.Contains("requestInfo.AddQueryParameters(requestConfig.QueryParameters)", result); + Assert.Contains("requestInfo.AddRequestOptions(requestConfig.Options)", result); Assert.Contains("SetContentFromParsable", result); Assert.Contains("return requestInfo;", result); AssertExtensions.CurlyBracesAreClosed(result, 1); @@ -1229,7 +1229,7 @@ public void WritesConstructor() { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string" @@ -1427,7 +1427,7 @@ public void WritesNullableMethodPrototypeForValueType() method.AddParameter(new CodeParameter { Name = "ra", - Kind = CodeParameterKind.RequestAdapter, + Kind = CodeParameterKind.Custom, Type = new CodeType { Name = "RequestAdapter", @@ -1472,7 +1472,7 @@ public void WritesMethodWithEmptyStringAsDefaultValueIfNotNullableAndOptional() method.AddParameter(new CodeParameter { Name = "ra", - Kind = CodeParameterKind.RequestAdapter, + Kind = CodeParameterKind.Custom, Type = new CodeType { Name = "RequestAdapter", diff --git a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs index 07d38f7458..b586e24e5d 100644 --- a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs @@ -54,6 +54,10 @@ public void Dispose() } private void AddRequestProperties() { + parentClass.StartBlock.Inherits = new CodeType + { + Name = "BaseRequestBuilder" + }; parentClass.AddProperty(new CodeProperty { Name = "requestAdapter", @@ -625,8 +629,8 @@ public void WritesRequestBuilder() method.Kind = CodeMethodKind.RequestBuilderBackwardCompatibility; writer.Write(method); var result = tw.ToString(); - Assert.Contains("m.pathParameters", result); - Assert.Contains("m.requestAdapter", result); + Assert.Contains("m.BaseRequestBuilder.PathParameters", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter", result); Assert.Contains("return", result); Assert.Contains("func (m", result); Assert.Contains("New", result); @@ -684,7 +688,7 @@ public void WritesRequestExecutorBody() Assert.Contains("\"5XX\": CreateError5XXFromDiscriminatorValue", result); Assert.Contains("\"403\": CreateError403FromDiscriminatorValue", result); Assert.Contains("ctx context.Context,", result); - Assert.Contains("m.requestAdapter.Send(ctx,", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter.Send(ctx,", result); Assert.Contains("return res.(", result); Assert.Contains("err != nil", result); Assert.Contains("return nil, err", result); @@ -708,8 +712,8 @@ public void WritesRequestExecutorBodyForEnum() }; writer.Write(method); var result = tw.ToString(); - Assert.DoesNotContain("m.requestAdapter.Send(", result); - Assert.Contains("m.requestAdapter.SendEnum", result); + Assert.DoesNotContain("m.BaseRequestBuilder.RequestAdapter.Send(", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter.SendEnum", result); Assert.Contains("ParseSomeEnum", result); Assert.Contains("return nil, err", result); Assert.Contains("if res == nil", result); @@ -736,7 +740,7 @@ public void WritesRequestExecutorBodyForEnumCollection() var result = tw.ToString(); Assert.DoesNotContain("m.requestAdapter.Send(", result); Assert.DoesNotContain("m.requestAdapter.SendEnum(", result); - Assert.Contains("m.requestAdapter.SendEnumCollection", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter.SendEnumCollection", result); Assert.Contains("ParseSomeEnum", result); Assert.DoesNotContain("val[i] = *(v.(*SomeEnum))", result); Assert.Contains("val[i] = v.(SomeEnum)", result); @@ -1095,7 +1099,7 @@ public async Task WritesRequestGeneratorBodyForScalar() Assert.Contains("if c.Q != nil", result); Assert.Contains("requestInfo.AddQueryParameters(", result); Assert.Contains("requestInfo.AddRequestOptions(", result); - Assert.Contains("requestInfo.SetContentFromScalar(ctx, m.requestAdapter", result); + Assert.Contains("requestInfo.SetContentFromScalar(ctx, m.BaseRequestBuilder.RequestAdapter", result); Assert.Contains("return requestInfo, nil", result); AssertExtensions.CurlyBracesAreClosed(result); } @@ -1134,7 +1138,7 @@ public async Task WritesRequestGeneratorBodyForScalarCollection() Assert.Contains("if c.Q != nil", result); Assert.Contains("requestInfo.AddQueryParameters(", result); Assert.Contains("requestInfo.AddRequestOptions(", result); - Assert.Contains("requestInfo.SetContentFromScalarCollection(ctx, m.requestAdapter", result); + Assert.Contains("requestInfo.SetContentFromScalarCollection(ctx, m.BaseRequestBuilder.RequestAdapter", result); Assert.Contains("return requestInfo, nil", result); AssertExtensions.CurlyBracesAreClosed(result); } @@ -1171,7 +1175,7 @@ public async Task WritesRequestGeneratorBodyForParsable() Assert.Contains("if c.Q != nil", result); Assert.Contains("requestInfo.AddQueryParameters(", result); Assert.Contains("requestInfo.AddRequestOptions(", result); - Assert.Contains("requestInfo.SetContentFromParsable(ctx, m.requestAdapter", result); + Assert.Contains("requestInfo.SetContentFromParsable(ctx, m.BaseRequestBuilder.RequestAdapter", result); Assert.Contains("return requestInfo, nil", result); AssertExtensions.CurlyBracesAreClosed(result); } @@ -1210,7 +1214,7 @@ public async Task WritesRequestGeneratorBodyForParsableCollection() Assert.Contains("if c.Q != nil", result); Assert.Contains("requestInfo.AddQueryParameters(", result); Assert.Contains("requestInfo.AddRequestOptions(", result); - Assert.Contains("requestInfo.SetContentFromParsableCollection(ctx, m.requestAdapter", result); + Assert.Contains("requestInfo.SetContentFromParsableCollection(ctx, m.BaseRequestBuilder.RequestAdapter", result); Assert.Contains("return requestInfo, nil", result); AssertExtensions.CurlyBracesAreClosed(result); } @@ -1530,11 +1534,11 @@ public void WritesIndexer() var methodForTest = parentClass.AddMethod(CodeMethod.FromIndexer(parentClass.Indexer, string.Empty, false)).First(); writer.Write(methodForTest); var result = tw.ToString(); - Assert.Contains("m.requestAdapter", result); - Assert.Contains("m.pathParameters", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter", result); + Assert.Contains("m.BaseRequestBuilder.PathParameters", result); Assert.Contains("[\"id\"] = id", result); Assert.Contains("return", result); - Assert.Contains("NewSomecustomtypeInternal(urlTplParams, m.requestAdapter)", result); // checking the parameter is passed to the constructor + Assert.Contains("NewSomecustomtypeInternal(urlTplParams, m.BaseRequestBuilder.RequestAdapter)", result); // checking the parameter is passed to the constructor } [Fact] public void WritesPathParameterRequestBuilder() @@ -1552,8 +1556,8 @@ public void WritesPathParameterRequestBuilder() }); writer.Write(method); var result = tw.ToString(); - Assert.Contains("m.requestAdapter", result); - Assert.Contains("m.pathParameters", result); + Assert.Contains("m.BaseRequestBuilder.RequestAdapter", result); + Assert.Contains("m.BaseRequestBuilder.PathParameters", result); Assert.Contains("pathParam", result); Assert.Contains("return New", result); } @@ -1645,7 +1649,7 @@ public void WritesConstructor() { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string", @@ -1664,9 +1668,8 @@ public void WritesConstructor() writer.Write(method); var result = tw.ToString(); Assert.Contains(parentClass.Name.ToFirstCharacterUpperCase(), result); - Assert.Contains($"m.{propName} = {defaultValue}", result); - Assert.Contains("m.pathParameters = urlTplParams", result); - Assert.Contains("make(map[string]string)", result); + Assert.Contains($"m.Set{propName.ToFirstCharacterUpperCase()}({defaultValue})", result); + Assert.Contains("NewBaseRequestBuilder", result); } [Fact] public void DoesNotWriteConstructorWithDefaultFromComposedType() @@ -1807,7 +1810,7 @@ public void WritesApiConstructor() Assert.Contains(parentClass.Name.ToFirstCharacterUpperCase(), result); Assert.Contains("RegisterDefaultSerializer", result); Assert.Contains("RegisterDefaultDeserializer", result); - Assert.Contains($"[\"baseurl\"] = m.core.GetBaseUrl", result); + Assert.Contains($"[\"baseurl\"] = m.BaseRequestBuilder.Core.GetBaseUrl", result); Assert.Contains($"SetBaseUrl(\"{method.BaseUrl}\")", result); } [Fact] diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs index 81a0a0f325..a1ecb210e1 100644 --- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs @@ -55,6 +55,10 @@ public void Dispose() } private void AddRequestProperties() { + parentClass.StartBlock.Inherits = new CodeType + { + Name = "BaseRequestBuilder" + }; parentClass.AddProperty(new CodeProperty { Name = "requestAdapter", @@ -1641,14 +1645,14 @@ public void WritesSetterToField() public void WritesConstructor() { method.Kind = CodeMethodKind.Constructor; - var defaultValue = "someVal"; + var defaultValue = "\"someVal\""; var propName = "propWithDefaultValue"; parentClass.Kind = CodeClassKind.RequestBuilder; parentClass.AddProperty(new CodeProperty { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string" @@ -1667,8 +1671,8 @@ public void WritesConstructor() writer.Write(method); var result = tw.ToString(); Assert.Contains(parentClass.Name.ToFirstCharacterUpperCase(), result); - Assert.Contains($"this.{propName} = {defaultValue}", result); - Assert.Contains("new Map(pathParameters)", result); + Assert.Contains($"this.set{propName.ToFirstCharacterUpperCase()}({defaultValue})", result); + Assert.Contains("super", result); } [Fact] public void DoesNotWriteConstructorWithDefaultFromComposedType() @@ -1716,14 +1720,14 @@ public void DoesNotWriteConstructorWithDefaultFromComposedType() public void WritesRawUrlConstructor() { method.Kind = CodeMethodKind.RawUrlConstructor; - var defaultValue = "someVal"; + var defaultValue = "\"someVal\""; var propName = "propWithDefaultValue"; parentClass.Kind = CodeClassKind.RequestBuilder; parentClass.AddProperty(new CodeProperty { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string" @@ -1742,8 +1746,8 @@ public void WritesRawUrlConstructor() writer.Write(method); var result = tw.ToString(); Assert.Contains(parentClass.Name.ToFirstCharacterUpperCase(), result); - Assert.Contains($"this.{propName} = {defaultValue}", result); - Assert.Contains("urlTplParams.put(\"request-raw-url\", rawUrl);", result); + Assert.Contains($"this.set{propName.ToFirstCharacterUpperCase()}({defaultValue})", result); + Assert.Contains("super", result); } [Fact] public void WritesApiConstructor() diff --git a/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs index e7c1fc87c1..cf89ce9d6d 100644 --- a/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Ruby/CodeMethodWriterTests.cs @@ -745,7 +745,7 @@ public void WritesConstructor() { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string" diff --git a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs index b76e7b28c0..86111f056b 100644 --- a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs @@ -707,7 +707,7 @@ public void WritesConstructor() { Name = propName, DefaultValue = defaultValue, - Kind = CodePropertyKind.UrlTemplate, + Kind = CodePropertyKind.Custom, Type = new CodeType { Name = "string", @@ -726,7 +726,6 @@ public void WritesConstructor() writer.Write(method); var result = tw.ToString(); Assert.Contains($"this.{propName} = {defaultValue}", result); - Assert.Contains("getPathParameters", result); } [Fact] public void DoesNotWriteConstructorWithDefaultFromComposedType() From 74919397399ff68140a407d8e74442a7ab5543d1 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Mar 2023 14:18:25 -0400 Subject: [PATCH 15/19] - fixes a bug where class names could conflict Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/CSharpRefiner.cs | 5 +++++ .../Refiners/CSharpReservedClassNamesProvider.cs | 13 +++++++++++++ .../Refiners/CSharpReservedNamesProvider.cs | 2 +- src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs | 9 ++++++--- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs diff --git a/src/Kiota.Builder/Refiners/CSharpRefiner.cs b/src/Kiota.Builder/Refiners/CSharpRefiner.cs index 669b1f6a27..7af05fa489 100644 --- a/src/Kiota.Builder/Refiners/CSharpRefiner.cs +++ b/src/Kiota.Builder/Refiners/CSharpRefiner.cs @@ -66,6 +66,11 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance new CSharpReservedNamesProvider(), x => $"@{x.ToFirstCharacterUpperCase()}", new HashSet { typeof(CodeClass), typeof(ClassDeclaration), typeof(CodeProperty), typeof(CodeUsing), typeof(CodeNamespace), typeof(CodeMethod), typeof(CodeEnum) } ); + ReplaceReservedNames( + generatedCode, + new CSharpReservedClassNamesProvider(), + x => $"{x.ToFirstCharacterUpperCase()}Escaped" + ); ReplaceReservedExceptionPropertyNames( generatedCode, new CSharpExceptionsReservedNamesProvider(), diff --git a/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs b/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs new file mode 100644 index 0000000000..232df15787 --- /dev/null +++ b/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Kiota.Builder.Refiners; + +public class CSharpReservedClassNamesProvider : IReservedNamesProvider +{ + private readonly Lazy> _reservedNames = new(static () => new(StringComparer.OrdinalIgnoreCase) + { + "BaseRequestBuilder", + }); + public HashSet ReservedNames => _reservedNames.Value; +} diff --git a/src/Kiota.Builder/Refiners/CSharpReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/CSharpReservedNamesProvider.cs index b42c6bdd41..7c0c1e0b08 100644 --- a/src/Kiota.Builder/Refiners/CSharpReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/CSharpReservedNamesProvider.cs @@ -109,7 +109,7 @@ public class CSharpReservedNamesProvider : IReservedNamesProvider "when", "while", "with", - "yield" + "yield", }); public HashSet ReservedNames => _reservedNames.Value; } diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs index dc261fb05d..95ad38fc49 100644 --- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs +++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs @@ -336,7 +336,7 @@ protected static void ReplaceReservedNames(CodeElement current, IReservedNamesPr // in the CodeNamespace if-block so we also need to update the using references if (!codeElementExceptions?.Contains(typeof(CodeNamespace)) ?? true) ReplaceReservedCodeUsingNamespaceSegmentNames(currentDeclaration, provider, replacement); - if (currentDeclaration.Inherits?.Name is string inheritName && provider.ReservedNames.Contains(inheritName)) + if (currentDeclaration.Inherits?.Name is string inheritName && provider.ReservedNames.Contains(inheritName) && (currentDeclaration.Inherits is not CodeType inheritType || !inheritType.IsExternal)) currentDeclaration.Inherits.Name = replacement(currentDeclaration.Inherits.Name); if (currentClass.DiscriminatorInformation.DiscriminatorMappings.Select(static x => x.Value.Name).Any(provider.ReservedNames.Contains)) ReplaceMappingNames(currentClass.DiscriminatorInformation.DiscriminatorMappings, provider, replacement); @@ -1415,7 +1415,8 @@ protected static void MoveRequestBuilderPropertiesToBaseType(CodeElement current { currentClass.StartBlock.Inherits = new CodeType { - Name = baseTypeUsing.Name + Name = baseTypeUsing.Name, + IsExternal = true, }; currentClass.AddUsing(baseTypeUsing); } @@ -1439,7 +1440,8 @@ protected static void RemoveRequestConfigurationClassesCommonProperties(CodeElem { currentClass.StartBlock.Inherits = new CodeType { - Name = baseTypeUsing.Name + Name = baseTypeUsing.Name, + IsExternal = true, }; currentClass.AddUsing(baseTypeUsing); } @@ -1465,6 +1467,7 @@ protected static void RemoveRequestConfigurationClasses(CodeElement currentEleme var configurationParameterType = new CodeType { Name = configurationParameterTypeUsing.Name, + IsExternal = true, }; foreach (var configurationParameter in configurationParameters) { From a1fbde11b8f360f7a829ef75503b1be4deb05de6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Mar 2023 14:30:30 -0400 Subject: [PATCH 16/19] - adds the reserved name to other languages Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/GoReservedNamesProvider.cs | 3 ++- src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs | 1 + src/Kiota.Builder/Refiners/RubyReservedNamesProvider.cs | 1 + src/Kiota.Builder/Refiners/ShellRefiner.cs | 5 +++++ .../Refiners/TypeScriptReservedNamesProvider.cs | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Refiners/GoReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/GoReservedNamesProvider.cs index f87225f1b5..15202158df 100644 --- a/src/Kiota.Builder/Refiners/GoReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/GoReservedNamesProvider.cs @@ -30,7 +30,8 @@ public class GoReservedNamesProvider : IReservedNamesProvider "switch", "type", "var", - "vendor" // cannot be used as a package name + "vendor", // cannot be used as a package name + "BaseRequestBuilder" }); public HashSet ReservedNames => _reservedNames.Value; } diff --git a/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs index 12c39e379d..96d7c45688 100644 --- a/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/JavaReservedNamesProvider.cs @@ -62,6 +62,7 @@ public class JavaReservedNamesProvider : IReservedNamesProvider "volatile", "wait", "while", + "BaseRequestBuilder", }); public HashSet ReservedNames => _reservedNames.Value; } diff --git a/src/Kiota.Builder/Refiners/RubyReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/RubyReservedNamesProvider.cs index d928f81c69..fca27d11cb 100644 --- a/src/Kiota.Builder/Refiners/RubyReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/RubyReservedNamesProvider.cs @@ -41,6 +41,7 @@ public class RubyReservedNamesProvider : IReservedNamesProvider "while", "defined?", "self", + "BaseRequestBuilder", }); public HashSet ReservedNames => _reservedNames.Value; } diff --git a/src/Kiota.Builder/Refiners/ShellRefiner.cs b/src/Kiota.Builder/Refiners/ShellRefiner.cs index 75e907e58e..c8aecbc58b 100644 --- a/src/Kiota.Builder/Refiners/ShellRefiner.cs +++ b/src/Kiota.Builder/Refiners/ShellRefiner.cs @@ -69,6 +69,11 @@ public override Task Refine(CodeNamespace generatedCode, CancellationToken cance new CSharpReservedNamesProvider(), x => $"@{x.ToFirstCharacterUpperCase()}", new HashSet { typeof(CodeClass), typeof(ClassDeclaration), typeof(CodeProperty), typeof(CodeUsing), typeof(CodeNamespace), typeof(CodeMethod), typeof(CodeEnum) } ); + ReplaceReservedNames( + generatedCode, + new CSharpReservedClassNamesProvider(), + x => $"{x.ToFirstCharacterUpperCase()}Escaped" + ); // Replace the reserved types ReplaceReservedModelTypes(generatedCode, new CSharpReservedTypesProvider(), x => $"{x}Object"); cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Kiota.Builder/Refiners/TypeScriptReservedNamesProvider.cs b/src/Kiota.Builder/Refiners/TypeScriptReservedNamesProvider.cs index 3d04e6a1b2..cd256bce8f 100644 --- a/src/Kiota.Builder/Refiners/TypeScriptReservedNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/TypeScriptReservedNamesProvider.cs @@ -41,6 +41,7 @@ public class TypeScriptReservedNamesProvider : IReservedNamesProvider "void", "while", "with", + "BaseRequestBuilder", }); public HashSet ReservedNames => _reservedNames.Value; } From 8ba81686b6cdfba5fa1e7d5630137eabbffa9dc3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Mar 2023 14:47:58 -0400 Subject: [PATCH 17/19] - code linting Signed-off-by: Vincent Biret --- src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs index f81ff0307c..80d9dab77f 100644 --- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs @@ -257,18 +257,6 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho .ToArray()); } } - private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMethod currentMethod, CodeParameterKind parameterKind, CodePropertyKind propertyKind, LanguageWriter writer, string? variableName = default) - { - var property = parentClass.GetPropertyOfKind(propertyKind); - if (property != null) - { - var parameter = currentMethod.Parameters.FirstOrDefault(x => x.IsOfKind(parameterKind)); - if (!string.IsNullOrEmpty(variableName)) - writer.WriteLine($"{property.Name.ToFirstCharacterUpperCase()} = {variableName};"); - else if (parameter != null) - writer.WriteLine($"{property.Name.ToFirstCharacterUpperCase()} = {parameter.Name};"); - } - } private string DefaultDeserializerValue => $"new Dictionary>"; private void WriteDeserializerBody(bool shouldHide, CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer) { From d528c91baf5435c7871f5fa479f327fe107cff95 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Mar 2023 14:48:58 -0400 Subject: [PATCH 18/19] - fixes encoding Signed-off-by: Vincent Biret --- src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs b/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs index 232df15787..8acb6b60e3 100644 --- a/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs +++ b/src/Kiota.Builder/Refiners/CSharpReservedClassNamesProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Kiota.Builder.Refiners; From 925f3338adac6ffab92f783ff43cfd0fb9d468f9 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 23 Mar 2023 08:14:02 -0400 Subject: [PATCH 19/19] Update src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs Co-authored-by: Eastman --- src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs index f2dba1e515..73d6a95dd2 100644 --- a/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs @@ -528,7 +528,7 @@ private void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMetho currentMethod.Parameters.OfKind(CodeParameterKind.PathParameters) is CodeParameter pathParametersParam && parentClass.Properties.OfKind(CodePropertyKind.PathParameters) is CodeProperty pathParametersProperty) conventions.AddParametersAssignment(writer, - pathParametersParam.Type.AllTypes.OfType().FirstOrDefault(), + pathParametersParam.Type.AllTypes.FirstOrDefault(), pathParametersParam.Name.ToFirstCharacterLowerCase(), $"m.{BaseRequestBuilderVarName}.{pathParametersProperty.Name.ToFirstCharacterUpperCase()}", false,