Skip to content

Commit

Permalink
Fix diff
Browse files Browse the repository at this point in the history
  • Loading branch information
rkodev committed Sep 19, 2023
2 parents 792defc + 2b907bf commit 3dd3120
Show file tree
Hide file tree
Showing 19 changed files with 317 additions and 112 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added auto-generated comment for TypeScript generation. [#3244](https://github.com/microsoft/kiota/issues/3244)

### Changed

- Localhost based descriptions are not cached anymore to facilitate development workflows. [#3316](https://github.com/microsoft/kiota/issues/3316)
- Changed parameter order in with_url method body to match the signature of RequestBuilder constructor in Python. [#3328](https://github.com/microsoft/kiota/issues/3328
- Removed redundant undefined qualifier in TypeScript for properties. [#3244](https://github.com/microsoft/kiota/issues/3244)
- The default status code response is now used as 4XX and 5XX when those class responses are not provided in the description. [#3245](https://github.com/microsoft/kiota/issues/3245)
- Adds codes files in typescript to reduce number of generated files. [#2116](https://github.com/microsoft/kiota/issues/2116)


## [1.6.1] - 2023-09-11

### Changed
Expand Down
5 changes: 5 additions & 0 deletions src/Kiota.Builder/CodeDOM/CodeMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ public IOrderedEnumerable<KeyValuePair<string, CodeTypeBase>> ErrorMappings
return errorMappings.OrderBy(static x => x.Key);
}
}
public bool HasErrorMappingCode(string code)
{
ArgumentException.ThrowIfNullOrEmpty(code);
return errorMappings.ContainsKey(code);
}

public DeprecationInformation? Deprecation
{
Expand Down
53 changes: 33 additions & 20 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,31 +1224,44 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten
private const string RequestBodyPlainTextContentType = "text/plain";
private static readonly HashSet<string> noContentStatusCodes = new() { "201", "202", "204", "205" };
private static readonly HashSet<string> errorStatusCodes = new(Enumerable.Range(400, 599).Select(static x => x.ToString(CultureInfo.InvariantCulture))
.Concat(new[] { "4XX", "5XX" }), StringComparer.OrdinalIgnoreCase);

.Concat(new[] { FourXXError, FiveXXError }), StringComparer.OrdinalIgnoreCase);
private const string FourXXError = "4XX";
private const string FiveXXError = "5XX";
private void AddErrorMappingsForExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod)
{
foreach (var response in operation.Responses.Where(x => errorStatusCodes.Contains(x.Key)))
{
var errorCode = response.Key.ToUpperInvariant();
var errorSchema = response.Value.GetResponseSchema(config.StructuredMimeTypes);
if (errorSchema != null && modelsNamespace != null)
{
var parentElement = string.IsNullOrEmpty(response.Value.Reference?.Id) && string.IsNullOrEmpty(errorSchema.Reference?.Id)
? (CodeElement)executorMethod
: modelsNamespace;
var errorType = CreateModelDeclarations(currentNode, errorSchema, operation, parentElement, $"{errorCode}Error", response: response.Value);
if (errorType is CodeType codeType &&
codeType.TypeDefinition is CodeClass codeClass &&
!codeClass.IsErrorDefinition)
{
codeClass.IsErrorDefinition = true;
}
if (errorType is null)
logger.LogWarning("Could not create error type for {Error} in {Operation}", errorCode, operation.OperationId);
else
executorMethod.AddErrorMapping(errorCode, errorType);
if (response.Value.GetResponseSchema(config.StructuredMimeTypes) is { } schema)
{
AddErrorMappingToExecutorMethod(currentNode, operation, executorMethod, schema, response.Value, response.Key.ToUpperInvariant());
}
}
if (operation.Responses.TryGetValue("default", out var defaultResponse) && defaultResponse.GetResponseSchema(config.StructuredMimeTypes) is { } errorSchema)
{
if (!executorMethod.HasErrorMappingCode(FourXXError))
AddErrorMappingToExecutorMethod(currentNode, operation, executorMethod, errorSchema, defaultResponse, FourXXError);
if (!executorMethod.HasErrorMappingCode(FiveXXError))
AddErrorMappingToExecutorMethod(currentNode, operation, executorMethod, errorSchema, defaultResponse, FiveXXError);
}
}
private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod, OpenApiSchema errorSchema, OpenApiResponse response, string errorCode)
{
if (modelsNamespace != null)
{
var parentElement = string.IsNullOrEmpty(response.Reference?.Id) && string.IsNullOrEmpty(errorSchema.Reference?.Id)
? (CodeElement)executorMethod
: modelsNamespace;
var errorType = CreateModelDeclarations(currentNode, errorSchema, operation, parentElement, $"{errorCode}Error", response: response);
if (errorType is CodeType codeType &&
codeType.TypeDefinition is CodeClass codeClass &&
!codeClass.IsErrorDefinition)
{
codeClass.IsErrorDefinition = true;
}
if (errorType is null)
logger.LogWarning("Could not create error type for {Error} in {Operation}", errorCode, operation.OperationId);
else
executorMethod.AddErrorMapping(errorCode, errorType);
}
}
private CodeTypeBase? GetExecutorMethodReturnType(OpenApiUrlTreeNode currentNode, OpenApiSchema? schema, OpenApiOperation operation, CodeClass parentClass)
Expand Down
17 changes: 12 additions & 5 deletions src/Kiota.Builder/Writers/ProprietableBlockExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Kiota.Builder.CodeDOM;

Expand All @@ -12,8 +13,14 @@ internal static class ProprietableBlockExtensions
internal static string GetPrimaryMessageCodePath<TBlockKind, TBlockDeclaration>(this ProprietableBlock<TBlockKind, TBlockDeclaration> block,
Func<CodeProperty, string> propertyNameNormalization,
Func<CodeMethod, string> methodNameNormalization,
string pathSegment = ".") where TBlockKind : Enum where TBlockDeclaration : ProprietableBlockDeclaration, new()
string pathSegment = ".",
HashSet<CodeElement>? visitedElements = default) where TBlockKind : Enum where TBlockDeclaration : ProprietableBlockDeclaration, new()
{
visitedElements ??= new();
if (visitedElements.Contains(block))
return string.Empty;
else
visitedElements.Add(block);
if (block is CodeInterface currentInterface)
{
if (currentInterface.Methods.FirstOrDefault(static x => isGetterMethod(x) && x.AccessedProperty is not null && isPrimaryErrorMessage(x.AccessedProperty)) is CodeMethod primaryErrorMessageMethod)
Expand All @@ -22,10 +29,10 @@ internal static string GetPrimaryMessageCodePath<TBlockKind, TBlockDeclaration>(
return propertyNameNormalization(primaryErrorMessageProperty);
else if (currentInterface.Methods
.Where(isGetterMethod)
.Select(x => new { Value = x.ReturnType is CodeType codeType && codeType.TypeDefinition is CodeInterface codeInterface && codeInterface.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment) is string segment && !string.IsNullOrEmpty(segment) ? $"{methodNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = true })
.Select(x => new { Value = x.ReturnType is CodeType codeType && codeType.TypeDefinition is CodeInterface codeInterface && codeInterface.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment, visitedElements) is string segment && !string.IsNullOrEmpty(segment) ? $"{methodNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = true })
.Union(currentInterface.Properties
.Where(isCustomProperty)
.Select(x => new { Value = x.Type is CodeType codeType && codeType.TypeDefinition is CodeInterface codeInterface && codeInterface.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment) is string segment && !string.IsNullOrEmpty(segment) ? $"{propertyNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = false }))
.Select(x => new { Value = x.Type is CodeType codeType && codeType.TypeDefinition is CodeInterface codeInterface && codeInterface.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment, visitedElements) is string segment && !string.IsNullOrEmpty(segment) ? $"{propertyNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = false }))
.OrderBy(static x => x.IsMethod)
.ThenBy(static x => x.Value, StringComparer.OrdinalIgnoreCase)
.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Value)) is { } primaryMessageCodePath)
Expand All @@ -40,10 +47,10 @@ internal static string GetPrimaryMessageCodePath<TBlockKind, TBlockDeclaration>(
return propertyNameNormalization(primaryErrorMessageProperty);
else if (currentClass.Methods
.Where(isGetterMethod)
.Select(x => new { Value = x.ReturnType is CodeType codeType && codeType.TypeDefinition is CodeClass codeClass && codeClass.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment) is string segment && !string.IsNullOrEmpty(segment) ? $"{methodNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = true })
.Select(x => new { Value = x.ReturnType is CodeType codeType && codeType.TypeDefinition is CodeClass codeClass && codeClass.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment, visitedElements) is string segment && !string.IsNullOrEmpty(segment) ? $"{methodNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = true })
.Union(currentClass.Properties
.Where(isCustomProperty)
.Select(x => new { Value = x.Type is CodeType codeType && codeType.TypeDefinition is CodeClass codeClass && codeClass.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment) is string segment && !string.IsNullOrEmpty(segment) ? $"{propertyNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = false }))
.Select(x => new { Value = x.Type is CodeType codeType && codeType.TypeDefinition is CodeClass codeClass && codeClass.GetPrimaryMessageCodePath(propertyNameNormalization, methodNameNormalization, pathSegment, visitedElements) is string segment && !string.IsNullOrEmpty(segment) ? $"{propertyNameNormalization(x)}{pathSegment}{segment}" : string.Empty, IsMethod = false }))
.OrderBy(static x => x.IsMethod)
.ThenBy(static x => x.Value, StringComparer.OrdinalIgnoreCase)
.FirstOrDefault(static x => !string.IsNullOrEmpty(x.Value)) is { } primaryMessageCodePath)
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void WriteRawUrlBuilderBody(CodeClass parentClass, CodeMethod codeElemen
{
var rawUrlParameter = codeElement.Parameters.OfKind(CodeParameterKind.RawUrl) ?? throw new InvalidOperationException("RawUrlBuilder method should have a RawUrl parameter");
var requestAdapterProperty = parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter) ?? throw new InvalidOperationException("RawUrlBuilder method should have a RequestAdapter property");
writer.WriteLine($"return {parentClass.Name.ToFirstCharacterUpperCase()}({rawUrlParameter.Name.ToSnakeCase()}, self.{requestAdapterProperty.Name.ToSnakeCase()})");
writer.WriteLine($"return {parentClass.Name.ToFirstCharacterUpperCase()}(self.{requestAdapterProperty.Name.ToSnakeCase()}, {rawUrlParameter.Name.ToSnakeCase()})");
}
private const string DiscriminatorMappingVarName = "mapping_value";

Expand Down
9 changes: 7 additions & 2 deletions src/Kiota.Builder/Writers/TypeScript/CodeBlockEndWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
using Kiota.Builder.CodeDOM;

namespace Kiota.Builder.Writers.TypeScript;
public class CodeBlockEndWriter : ICodeElementWriter<BlockEnd>
public class CodeBlockEndWriter : BaseElementWriter<BlockEnd, TypeScriptConventionService>
{
public void WriteCodeElement(BlockEnd codeElement, LanguageWriter writer)
public CodeBlockEndWriter(TypeScriptConventionService conventionService) : base(conventionService)
{
}
public override void WriteCodeElement(BlockEnd codeElement, LanguageWriter writer)
{
ArgumentNullException.ThrowIfNull(codeElement);
ArgumentNullException.ThrowIfNull(writer);
if (codeElement.Parent is CodeNamespace) return;
writer.CloseBlock();
if (codeElement.Parent?.Parent is CodeNamespace)
conventions.WriteAutoGeneratedEnd(writer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWrit
{
ArgumentNullException.ThrowIfNull(codeElement);
ArgumentNullException.ThrowIfNull(writer);
if (codeElement.Parent?.Parent is CodeNamespace)
conventions.WriteAutoGeneratedStart(writer);
var parentNamespace = codeElement.GetImmediateParentOfType<CodeNamespace>();

if (codeElement.Parent?.Parent is not CodeFile)
Expand Down
6 changes: 5 additions & 1 deletion src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ public override void WriteCodeElement(CodeFunction codeElement, LanguageWriter w
ArgumentNullException.ThrowIfNull(codeElement);
if (codeElement.OriginalLocalMethod == null) throw new InvalidOperationException($"{nameof(codeElement.OriginalLocalMethod)} should not be null");
ArgumentNullException.ThrowIfNull(writer);

if (codeElement.Parent is not CodeNamespace && codeElement.Parent is not CodeFile) throw new InvalidOperationException("the parent of a function should be a namespace or file");

if (codeElement.Parent is CodeNamespace)
{
conventions.WriteAutoGeneratedStart(writer);
_codeUsingWriter.WriteCodeElement(codeElement.StartBlock.Usings, codeElement.GetImmediateParentOfType<CodeNamespace>(), writer);

}

var codeMethod = codeElement.OriginalLocalMethod;

var returnType = codeMethod.Kind != CodeMethodKind.Factory ? conventions.GetTypeString(codeMethod.ReturnType, codeElement) : string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@
using Kiota.Builder.CodeDOM;
using Kiota.Builder.Extensions;

namespace Kiota.Builder.Writers.TypeScript
namespace Kiota.Builder.Writers.TypeScript;
public class CodeInterfaceDeclarationWriter : BaseElementWriter<InterfaceDeclaration, TypeScriptConventionService>
{
public class CodeInterfaceDeclarationWriter : BaseElementWriter<InterfaceDeclaration, TypeScriptConventionService>
private readonly CodeUsingWriter _codeUsingWriter;
public CodeInterfaceDeclarationWriter(TypeScriptConventionService conventionService, string clientNamespaceName) : base(conventionService)
{
private readonly CodeUsingWriter _codeUsingWriter;
public CodeInterfaceDeclarationWriter(TypeScriptConventionService conventionService, string clientNamespaceName) : base(conventionService)
{
_codeUsingWriter = new(clientNamespaceName);
}
_codeUsingWriter = new(clientNamespaceName);
}

public override void WriteCodeElement(InterfaceDeclaration codeElement, LanguageWriter writer)
public override void WriteCodeElement(InterfaceDeclaration codeElement, LanguageWriter writer)
{
ArgumentNullException.ThrowIfNull(codeElement);
ArgumentNullException.ThrowIfNull(writer);

var parentNamespace = codeElement.GetImmediateParentOfType<CodeNamespace>();
if (codeElement.Parent?.Parent is CodeNamespace)
{
ArgumentNullException.ThrowIfNull(codeElement);
ArgumentNullException.ThrowIfNull(writer);

var parentNamespace = codeElement.GetImmediateParentOfType<CodeNamespace>();

if (codeElement.Parent?.Parent is not CodeFile)
_codeUsingWriter.WriteCodeElement(codeElement.Usings, parentNamespace, writer);

var derivation = codeElement.Implements.Any() ? $" extends {codeElement.Implements.Select(static x => x.Name).Aggregate(static (x, y) => x + ", " + y)}" : string.Empty;
writer.StartBlock($"export interface {codeElement.Name.ToFirstCharacterUpperCase()}{derivation} {{");
conventions.WriteAutoGeneratedStart(writer);
_codeUsingWriter.WriteCodeElement(codeElement.Usings, parentNamespace, writer);
}

var derivation = codeElement.Implements.Any() ? $" extends {codeElement.Implements.Select(static x => x.Name).Aggregate(static (x, y) => x + ", " + y)}" : string.Empty;
writer.StartBlock($"export interface {codeElement.Name.ToFirstCharacterUpperCase()}{derivation} {{");
}
}
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Writers/TypeScript/CodePropertyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public override void WriteCodeElement(CodeProperty codeElement, LanguageWriter w

private static void WriteCodePropertyForInterface(CodeProperty codeElement, LanguageWriter writer, string returnType, bool isFlagEnum)
{
writer.WriteLine($"{codeElement.Name.ToFirstCharacterLowerCase()}?: {returnType}{(isFlagEnum ? "[]" : string.Empty)}{(codeElement.Type.IsNullable ? " | undefined" : string.Empty)};");
writer.WriteLine($"{codeElement.Name.ToFirstCharacterLowerCase()}?: {returnType}{(isFlagEnum ? "[]" : string.Empty)};");
}

private void WriteCodePropertyForClass(CodeProperty codeElement, CodeClass parentClass, LanguageWriter writer, string returnType, bool isFlagEnum)
Expand All @@ -45,7 +45,7 @@ private void WriteCodePropertyForClass(CodeProperty codeElement, CodeClass paren
writer.CloseBlock();
break;
default:
writer.WriteLine($"{conventions.GetAccessModifier(codeElement.Access)} {codeElement.NamePrefix}{codeElement.Name.ToFirstCharacterLowerCase()}{(codeElement.Type.IsNullable ? "?" : string.Empty)}: {returnType}{(isFlagEnum ? "[]" : string.Empty)}{(codeElement.Type.IsNullable ? " | undefined" : string.Empty)};");
writer.WriteLine($"{conventions.GetAccessModifier(codeElement.Access)} {codeElement.NamePrefix}{codeElement.Name.ToFirstCharacterLowerCase()}{(codeElement.Type.IsNullable ? "?" : string.Empty)}: {returnType}{(isFlagEnum ? "[]" : string.Empty)};");
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ public TypeScriptConventionService(LanguageWriter languageWriter)
{
writer = languageWriter;
}
internal void WriteAutoGeneratedStart(LanguageWriter writer)
{
writer.WriteLine("// tslint:disable");
writer.WriteLine("// eslint-disable");
writer.WriteLine("// Generated by Microsoft Kiota");
}
internal void WriteAutoGeneratedEnd(LanguageWriter writer)
{
writer.WriteLine("// tslint:enable");
writer.WriteLine("// eslint-enable");
}
private readonly LanguageWriter writer;
public override string StreamTypeName => "ArrayBuffer";
public override string VoidTypeName => "void";
Expand Down
Loading

0 comments on commit 3dd3120

Please sign in to comment.