Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/commands enhancements #1901

Merged
merged 7 commits into from
Oct 18, 2022
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added compatibility all the way down to android API level 26 for Java.
- Added support for enum and collection of enum return types for Java.
- Added support for types with more than 500 discriminator entries in Java.
- Added a confirmation message once the generation is successful. [#1898](https://github.com/microsoft/kiota/issues/1898)

### Changed

- Removed response handler parameter from Java executor methods.
- Changed the generated PHP deserializer code to use `fn` instead of `function`. [#1880](https://github.com/microsoft/kiota/pull/1880)
- Fixes compile errors due to type ambiguity in generated models in dotnet. [#1881](https://github.com/microsoft/kiota/issues/1881)
- Changes the ResponeHandler parameter in IRequestAdapter to be a RequestOption in dotnet [#1858](https://github.com/microsoft/kiota/issues/1858)
- File extensions are now stripped from property/namespace/class names. [#1892](https://github.com/microsoft/kiota/issues/1892)
- Missing host/server is now considered a warning instead of a critical error. [#1896](https://github.com/microsoft/kiota/issues/1896)
- Fixed a bug where info and show commands would crash in case of invalid description URL. [#1894](https://github.com/microsoft/kiota/issues/1894)
- Show command now reads descriptions directly from APIs.guru instead of their origin. [#1897](https://github.com/microsoft/kiota/issues/1897)

## [0.6.0] - 2022-10-06

Expand Down
38 changes: 30 additions & 8 deletions src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ public static string GetNamespaceFromPath(this string currentPath, string prefix
+ currentPath
?.Split(pathNameSeparator, StringSplitOptions.RemoveEmptyEntries)
?.Select(replaceSingleParameterSegmentByItem)
?.Select(static x => CleanupParametersFromPath((x ?? string.Empty).Split('.', StringSplitOptions.RemoveEmptyEntries)
?.Select(static x => x.TrimStart('$')) //$ref from OData
.Last()))
?.Select(static x => CleanupParametersFromPath((x ?? string.Empty)
.Split('.', StringSplitOptions.RemoveEmptyEntries)
.Select(static x => x.TrimStart('$')) //$ref from OData
.Except(SegmentsToSkipForClassNames, StringComparer.OrdinalIgnoreCase)
.Last()))
?.Select(static x => x.CleanupSymbolName())
?.Aggregate(string.Empty,
static (x, y) => $"{x}{GetDotIfBothNotNullOfEmpty(x, y)}{y}") :
Expand Down Expand Up @@ -70,6 +72,8 @@ public static string GetClassName(this OpenApiUrlTreeNode currentNode, HashSet<s
(requestBody ? null : response?.GetResponseSchema(structuredMimeTypes)?.Reference?.GetClassName()) ??
(requestBody ? operation?.GetRequestSchema(structuredMimeTypes) : operation?.GetResponseSchema(structuredMimeTypes))?.Reference?.GetClassName() ??
CleanupParametersFromPath(currentNode.Segment)?.ReplaceValueIdentifier();
if(stripExtensionForIndexersRegex.IsMatch(rawClassName))
rawClassName = stripExtensionForIndexersRegex.Replace(rawClassName, string.Empty);
if((currentNode?.DoesNodeBelongToItemSubnamespace() ?? false) && idClassNameCleanup.IsMatch(rawClassName)) {
rawClassName = idClassNameCleanup.Replace(rawClassName, string.Empty);
if(rawClassName == WithKeyword) // in case the single parameter doesn't follow {classname-id} we get the previous segment
Expand All @@ -80,9 +84,22 @@ public static string GetClassName(this OpenApiUrlTreeNode currentNode, HashSet<s
.ToFirstCharacterUpperCase();

}
return (prefix + rawClassName?.Split('.', StringSplitOptions.RemoveEmptyEntries)?.LastOrDefault() + suffix)
return (prefix +
rawClassName
?.Split('.', StringSplitOptions.RemoveEmptyEntries)
.Except(SegmentsToSkipForClassNames, StringComparer.OrdinalIgnoreCase)
.LastOrDefault() +
suffix)
.CleanupSymbolName();
}
private static readonly HashSet<string> SegmentsToSkipForClassNames = new(StringComparer.OrdinalIgnoreCase) {
"json",
"xml",
"csv",
"yaml",
"yml",
"txt",
};
private static readonly Regex descriptionCleanupRegex = new (@"[\r\n\t]", RegexOptions.Compiled);
public static string CleanupDescription(this string description) => string.IsNullOrEmpty(description) ? description : descriptionCleanupRegex.Replace(description, string.Empty);
public static string GetPathItemDescription(this OpenApiUrlTreeNode currentNode, string label, string defaultValue = default) =>
Expand All @@ -96,10 +113,14 @@ public static bool IsPathSegmentWithSingleSimpleParameter(this OpenApiUrlTreeNod
currentNode?.Segment.IsPathSegmentWithSingleSimpleParameter() ?? false;
private static bool IsPathSegmentWithSingleSimpleParameter(this string currentSegment)
{
return (currentSegment?.StartsWith(requestParametersChar) ?? false) &&
currentSegment.EndsWith(requestParametersEndChar) &&
currentSegment.Count(x => x == requestParametersChar) == 1;
if (string.IsNullOrEmpty(currentSegment)) return false;

var segmentWithoutExtension = stripExtensionForIndexersRegex.Replace(currentSegment, string.Empty);
return segmentWithoutExtension.StartsWith(requestParametersChar) &&
segmentWithoutExtension.EndsWith(requestParametersEndChar) &&
segmentWithoutExtension.Count(x => x == requestParametersChar) == 1;
}
private static readonly Regex stripExtensionForIndexersRegex = new(@"\.(?:json|yaml|yml|csv|txt)$", RegexOptions.Compiled); // so {param-name}.json is considered as indexer
public static bool IsComplexPathWithAnyNumberOfParameters(this OpenApiUrlTreeNode currentNode)
{
return (currentNode?.Segment?.Contains(requestParametersSectionChar) ?? false) && currentNode.Segment.EndsWith(requestParametersSectionEndChar);
Expand Down Expand Up @@ -139,7 +160,8 @@ private static string SanitizePathParameterNamesForUrlTemplate(string original)
}
public static string SanitizeParameterNameForUrlTemplate(this string original) {
if(string.IsNullOrEmpty(original)) return original;
return Uri.EscapeDataString(original
return Uri.EscapeDataString(stripExtensionForIndexersRegex
.Replace(original, string.Empty) // {param-name}.json becomes {param-name}
.TrimStart('{')
.TrimEnd('}'))
.Replace("-", "%2D")
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public void FilterPathsByPatterns(OpenApiDocument doc, List<Glob> includePattern
private void SetApiRootUrl() {
config.ApiRootUrl = openApiDocument.Servers.FirstOrDefault()?.Url.TrimEnd('/');
if(string.IsNullOrEmpty(config.ApiRootUrl))
throw new InvalidOperationException("A servers entry (v3) or host + basePath + schemes properties (v2) must be present in the OpenAPI description.");
logger.LogWarning("A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.");
}
private void StopLogAndReset(Stopwatch sw, string prefix) {
sw.Stop();
Expand Down
3 changes: 0 additions & 3 deletions src/Kiota.Builder/SearchProviders/APIsGuru/APIEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ public record ApiInformation {
public ApiContact contact { get; set;}
public string description { get; set;}
public string title { get; set;}
public string version { get; set;}
[JsonPropertyName("x-origin")]
public List<ApiOrigin> origin { get; set;}
}

public record ApiContact(string email, string name, Uri url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public async Task<IDictionary<string, SearchResult>> SearchAsync(string term, st
.Select(x => x.Value.versions.TryGetValue(GetVersionKey(singleCandidate, version, x), out var versionInfo) ? (x.Key, versionInfo, x.Value.versions.Keys.ToList()) : (x.Key, default, default))
.Where(static x => x.versionInfo is not null)
.ToDictionary(static x => x.Key,
static x => new SearchResult(x.versionInfo.info?.title, x.versionInfo.info?.description, x.versionInfo.info?.contact?.url, x.versionInfo.info?.origin?.FirstOrDefault()?.url, x.Item3),
static x => new SearchResult(x.versionInfo.info?.title, x.versionInfo.info?.description, x.versionInfo.info?.contact?.url, x.versionInfo.swaggerUrl, x.Item3),
StringComparer.OrdinalIgnoreCase);
return results;
}
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,12 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me
var requestAdapterPropertyName = requestAdapterProperty.Name.ToFirstCharacterUpperCase();
WriteSerializationRegistration(method.SerializerModules, writer, "RegisterDefaultSerializer");
WriteSerializationRegistration(method.DeserializerModules, writer, "RegisterDefaultDeserializer");
writer.WriteLine($"if (string.IsNullOrEmpty({requestAdapterPropertyName}.BaseUrl)) {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.BaseUrl = \"{method.BaseUrl}\";");
writer.CloseBlock();
if (!string.IsNullOrEmpty(method.BaseUrl)) {
writer.WriteLine($"if (string.IsNullOrEmpty({requestAdapterPropertyName}.BaseUrl)) {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.BaseUrl = \"{method.BaseUrl}\";");
writer.CloseBlock();
}
if (backingStoreParameter != null)
writer.WriteLine($"{requestAdapterPropertyName}.EnableBackingStore({backingStoreParameter.Name});");
}
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,12 @@ private void WriteApiConstructorBody(CodeClass parentClass, CodeMethod method, L
var backingStoreParameter = method.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.BackingStore));
WriteSerializationRegistration(method.SerializerModules, writer, parentClass, "RegisterDefaultSerializer", "SerializationWriterFactory");
WriteSerializationRegistration(method.DeserializerModules, writer, parentClass, "RegisterDefaultDeserializer", "ParseNodeFactory");
writer.WriteLine($"if m.{requestAdapterPropertyName}.GetBaseUrl() == \"\" {{");
writer.IncreaseIndent();
writer.WriteLine($"m.{requestAdapterPropertyName}.SetBaseUrl(\"{method.BaseUrl}\")");
writer.CloseBlock();
if (!string.IsNullOrEmpty(method.BaseUrl)) {
writer.WriteLine($"if m.{requestAdapterPropertyName}.GetBaseUrl() == \"\" {{");
writer.IncreaseIndent();
writer.WriteLine($"m.{requestAdapterPropertyName}.SetBaseUrl(\"{method.BaseUrl}\")");
writer.CloseBlock();
}
if(backingStoreParameter != null)
writer.WriteLine($"m.{requestAdapterPropertyName}.EnableBackingStore({backingStoreParameter.Name});");
}
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,12 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me
var requestAdapterPropertyName = requestAdapterProperty.Name.ToFirstCharacterLowerCase();
WriteSerializationRegistration(method.SerializerModules, writer, "registerDefaultSerializer");
WriteSerializationRegistration(method.DeserializerModules, writer, "registerDefaultDeserializer");
writer.WriteLine($"if ({requestAdapterPropertyName}.getBaseUrl() == null || {requestAdapterPropertyName}.getBaseUrl().isEmpty()) {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.setBaseUrl(\"{method.BaseUrl}\");");
writer.CloseBlock();
if(!string.IsNullOrEmpty(method.BaseUrl)) {
writer.WriteLine($"if ({requestAdapterPropertyName}.getBaseUrl() == null || {requestAdapterPropertyName}.getBaseUrl().isEmpty()) {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.setBaseUrl(\"{method.BaseUrl}\");");
writer.CloseBlock();
}
if(backingStoreParameter != null)
writer.WriteLine($"this.{requestAdapterPropertyName}.enableBackingStore({backingStoreParameter.Name});");
}
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,12 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod co
var requestAdapterProperty = parentClass.GetPropertyOfKind(CodePropertyKind.RequestAdapter);
WriteSerializationRegistration(codeMethod.SerializerModules, writer, "registerDefaultSerializer");
WriteSerializationRegistration(codeMethod.DeserializerModules, writer, "registerDefaultDeserializer");
writer.WriteLines($"if (empty({GetPropertyCall(requestAdapterProperty, string.Empty)}->getBaseUrl())) {{");
writer.IncreaseIndent();
writer.WriteLine($"{GetPropertyCall(requestAdapterProperty, string.Empty)}->setBaseUrl('{codeMethod.BaseUrl}');");
writer.CloseBlock();
if(!string.IsNullOrEmpty(codeMethod.BaseUrl)) {
writer.WriteLines($"if (empty({GetPropertyCall(requestAdapterProperty, string.Empty)}->getBaseUrl())) {{");
writer.IncreaseIndent();
writer.WriteLine($"{GetPropertyCall(requestAdapterProperty, string.Empty)}->setBaseUrl('{codeMethod.BaseUrl}');");
writer.CloseBlock();
}
}

private static void WriteSerializationRegistration(HashSet<string> serializationModules, LanguageWriter writer, string methodName) {
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me
var requestAdapterPropertyName = requestAdapterProperty.Name.ToSnakeCase();
WriteSerializationRegistration(method.SerializerModules, writer, "register_default_serializer");
WriteSerializationRegistration(method.DeserializerModules, writer, "register_default_deserializer");
writer.WriteLine($"if not {requestAdapterPropertyName}.base_url:");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.base_url = \"{method.BaseUrl}\"");
writer.DecreaseIndent();
if(!string.IsNullOrEmpty(method.BaseUrl)) {
writer.WriteLine($"if not {requestAdapterPropertyName}.base_url:");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.base_url = \"{method.BaseUrl}\"");
writer.DecreaseIndent();
}
if(backingStoreParameter != null)
writer.WriteLine($"self.{requestAdapterPropertyName}.enable_backing_store({backingStoreParameter.Name})");
}
Expand Down
3 changes: 2 additions & 1 deletion src/Kiota.Builder/Writers/Ruby/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me
var requestAdapterPropertyName = requestAdapterProperty.Name.ToSnakeCase();
if (method.Parameters.FirstOrDefault(x => x.IsOfKind(CodeParameterKind.RequestAdapter)) is CodeParameter requestAdapterParameter)
writer.WriteLine($"@{requestAdapterPropertyName} = {requestAdapterParameter.Name.ToSnakeCase()}");
writer.WriteLine($"{requestAdapterPropertyName}.set_base_url('{method.BaseUrl}')");
if(!string.IsNullOrEmpty(method.BaseUrl))
writer.WriteLine($"{requestAdapterPropertyName}.set_base_url('{method.BaseUrl}')");
}
private static void WriteConstructorBody(CodeClass parentClass, CodeMethod currentMethod, LanguageWriter writer, bool inherits) {
if(inherits)
Expand Down
10 changes: 6 additions & 4 deletions src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ private static void WriteApiConstructorBody(CodeClass parentClass, CodeMethod me
var requestAdapterPropertyName = requestAdapterProperty.Name.ToFirstCharacterLowerCase();
WriteSerializationRegistration(method.SerializerModules, writer, "registerDefaultSerializer");
WriteSerializationRegistration(method.DeserializerModules, writer, "registerDefaultDeserializer");
writer.WriteLine($"if ({requestAdapterPropertyName}.baseUrl === undefined || {requestAdapterPropertyName}.baseUrl === \"\") {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.baseUrl = \"{method.BaseUrl}\";");
writer.CloseBlock();
if(!string.IsNullOrEmpty(method.BaseUrl)) {
writer.WriteLine($"if ({requestAdapterPropertyName}.baseUrl === undefined || {requestAdapterPropertyName}.baseUrl === \"\") {{");
writer.IncreaseIndent();
writer.WriteLine($"{requestAdapterPropertyName}.baseUrl = \"{method.BaseUrl}\";");
writer.CloseBlock();
}
if(backingStoreParameter != null)
writer.WriteLine($"this.{requestAdapterPropertyName}.enableBackingStore({backingStoreParameter.Name});");
}
Expand Down
5 changes: 3 additions & 2 deletions src/kiota/Handlers/KiotaGenerationCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,16 @@ public override async Task<int> InvokeAsync(InvocationContext context)

try {
await new KiotaBuilder(logger, Configuration.Generation).GenerateClientAsync(cancellationToken);
Console.WriteLine("Generation completed successfully");
DisplayInfoHint(language, Configuration.Generation.OpenAPIFilePath);
DisplayGenerateAdvancedHint(includePatterns, excludePatterns, Configuration.Generation.OpenAPIFilePath);
return 0;
} catch (Exception ex) {
#if DEBUG
logger.LogCritical(ex, "error generating the SDK: {exceptionMessage}", ex.Message);
logger.LogCritical(ex, "error generating the client: {exceptionMessage}", ex.Message);
throw; // so debug tools go straight to the source of the exception when attached
#else
logger.LogCritical("error generating the SDK: {exceptionMessage}", ex.Message);
logger.LogCritical("error generating the client: {exceptionMessage}", ex.Message);
return 1;
#endif
}
Expand Down
Loading