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

fix/error message missing #5314

Merged
merged 8 commits into from
Sep 4, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed shorthand for refresh option in workspace experience. [#5240](https://github.com/microsoft/kiota/issues/5240)
- Fixed missing type options in help for plugin commands. [#5230](https://github.com/microsoft/kiota/issues/5230)
- Removed OpenAI plugins generation since the service does not support them anymore.
- Fixed a bug where the error message would not be deserialized if the property name matched a reserved property. [#5311](https://github.com/microsoft/kiota/issues/5311)
- Fixed an issue where TypeScript clients would be missing path parameters. [#5247](https://github.com/microsoft/kiota/issues/5247)
- Fixed a bug where names normalization could lead to collisions in Ruby and other languages. [#5310](https://github.com/microsoft/kiota/issues/5310)
- Redirect status codes documenting an application/octet-stream content type now generate a stream return type. [#5246](https://github.com/microsoft/kiota/issues/5246)
Expand Down
15 changes: 10 additions & 5 deletions src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
.Union(parseNodeFactoryInterfaceAndRegistrationFullName)
.Where(x => !string.IsNullOrEmpty(x))
.ToList();
currentMethod.DeserializerModules = currentMethod.DeserializerModules.Select(x => x.Split(separator).Last()).ToHashSet(StringComparer.OrdinalIgnoreCase);

Check warning on line 39 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last" (https://rules.sonarsource.com/csharp/RSPEC-6608)
currentMethod.SerializerModules = currentMethod.SerializerModules.Select(x => x.Split(separator).Last()).ToHashSet(StringComparer.OrdinalIgnoreCase);

Check warning on line 40 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last" (https://rules.sonarsource.com/csharp/RSPEC-6608)
declaration.AddUsings(cumulatedSymbols.Select(x => new CodeUsing
{
Name = x.Split(separator).Last(),

Check warning on line 43 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Indexing at Count-1 should be used instead of the "Enumerable" extension method "Last" (https://rules.sonarsource.com/csharp/RSPEC-6608)
Declaration = new CodeType
{
Name = x.Split(separator).SkipLast(1).Aggregate((x, y) => $"{x}{separator}{y}"),
Expand Down Expand Up @@ -159,7 +159,7 @@
}
CrawlTree(current, x => ReplacePropertyNames(x, propertyKindsToReplace!, refineAccessorName));
}
protected static void AddGetterAndSetterMethods(CodeElement current, HashSet<CodePropertyKind> propertyKindsToAddAccessors, Func<CodeElement, string, string> refineAccessorName, bool removeProperty, bool parameterAsOptional, string getterPrefix, string setterPrefix, string fieldPrefix = "_", AccessModifier propertyAccessModifier = AccessModifier.Private)

Check warning on line 162 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 20 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)

Check warning on line 162 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Method has 9 parameters, which is greater than the 7 authorized. (https://rules.sonarsource.com/csharp/RSPEC-107)
{
ArgumentNullException.ThrowIfNull(refineAccessorName);
var isSetterPrefixEmpty = string.IsNullOrEmpty(setterPrefix);
Expand Down Expand Up @@ -298,10 +298,10 @@
null,
x => (((x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Custom)) || x is CodeMethod) && x.Parent is CodeClass parent && parent.IsOfKind(CodeClassKind.Model) && parent.IsErrorDefinition) // rename properties or method of error classes matching the reserved names.
|| (x is CodeClass codeClass && codeClass.IsOfKind(CodeClassKind.Model) && codeClass.IsErrorDefinition
&& codeClass.Properties.FirstOrDefault(classProp => provider.ReservedNames.Contains(classProp.Name)) is { } matchingProperty && matchingProperty.Name.Equals(codeClass.Name, StringComparison.OrdinalIgnoreCase)) // rename the a class if it has a matching property and the class has the same name as the property.
&& codeClass.Properties.FirstOrDefault(classProp => provider.ReservedNames.Contains(classProp.Name)) is { } matchingProperty && matchingProperty.Name.Equals(codeClass.Name, StringComparison.OrdinalIgnoreCase)) // rename the class if it has a matching property and the class has the same name as the property.
);
}
protected static void ReplaceReservedNames(CodeElement current, IReservedNamesProvider provider, Func<string, string> replacement, HashSet<Type>? codeElementExceptions = null, Func<CodeElement, bool>? shouldReplaceCallback = null)

Check warning on line 304 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 20 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
ArgumentNullException.ThrowIfNull(current);
ArgumentNullException.ThrowIfNull(provider);
Expand Down Expand Up @@ -370,7 +370,7 @@
currentDeclaration.Usings
.Where(static codeUsing => codeUsing is { IsExternal: false })
.Select(static codeUsing => new Tuple<CodeUsing, string[]>(codeUsing, codeUsing.Name.Split('.')))
.Where(tuple => tuple.Item2.Any(x => provider.ReservedNames.Contains(x)))

Check warning on line 373 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Collection-specific "Exists" method should be used instead of the "Any" extension. (https://rules.sonarsource.com/csharp/RSPEC-6605)
.ToList()
.ForEach(tuple =>
{
Expand Down Expand Up @@ -414,7 +414,7 @@
CrawlTree(current, c => AddDefaultImports(c, evaluators));
}
private static readonly HashSet<string> BinaryTypes = new(StringComparer.OrdinalIgnoreCase) { "binary", "base64", "base64url" };
protected static void ReplaceBinaryByNativeType(CodeElement currentElement, string symbol, string ns, bool addDeclaration = false, bool isNullable = false)

Check warning on line 417 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
if (currentElement is CodeMethod currentMethod)
{
Expand Down Expand Up @@ -625,9 +625,9 @@
if (currentElement is CodeIndexer currentIndexer &&
currentElement.Parent is CodeClass indexerParentClass)
{
if (indexerParentClass.ContainsMember(currentElement.Name)) // TODO remove condition for v2 necessary because of the second case of Go block

Check warning on line 628 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
indexerParentClass.RemoveChildElement(currentElement);
//TODO remove whole block except for last else if body for v2

Check warning on line 630 in src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs

View workflow job for this annotation

GitHub Actions / Build

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
if (language == GenerationLanguage.Go)
{
if (currentIndexer.IsLegacyIndexer)
Expand Down Expand Up @@ -1514,12 +1514,17 @@
{
if (asProperty)
{
if (currentClass.Properties.FirstOrDefault(property => property.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) is { } sameNameProperty)
if (currentClass.FindChildByName<CodeProperty>(name, false) is { } sameNameProperty)
{
if (sameNameProperty.Type.Name.Equals(type().Name, StringComparison.OrdinalIgnoreCase))
currentClass.RemoveChildElementByName(name); // type matches so just remove it for replacement
else
currentClass.RenameChildElement(name, $"{name}Escaped"); // type mismatch so just rename it
{
// As the type may not be settable by the serialization logic
// set this as the primary error message as it matches the type so that the deserialization logic can map this correctly.
sameNameProperty.IsPrimaryErrorMessage = true;
}
if (string.IsNullOrEmpty(sameNameProperty.SerializationName))
sameNameProperty.SerializationName = sameNameProperty.Name;
currentClass.RenameChildElement(name, $"{name}Escaped"); // rename to prevent collisions and keep the original
}

currentClass.AddProperty(new CodeProperty
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Writers/CodeClassExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static class CodeClassExtensions
public static IEnumerable<CodeProperty> GetPropertiesOfKind(this CodeClass parentClass, params CodePropertyKind[] kinds)
{
if (parentClass == null)
return Enumerable.Empty<CodeProperty>();
return [];
if (kinds == null || kinds.Length == 0)
throw new ArgumentOutOfRangeException(nameof(kinds));
return parentClass.Properties
Expand All @@ -25,7 +25,7 @@ public static IEnumerable<CodeProperty> GetPropertiesOfKind(this CodeClass paren
public static IEnumerable<CodeMethod> GetMethodsOffKind(this CodeClass parentClass, params CodeMethodKind[] kinds)
{
if (parentClass == null)
return Enumerable.Empty<CodeMethod>();
return [];
if (kinds == null || kinds.Length == 0)
throw new ArgumentOutOfRangeException(nameof(kinds));
return parentClass.Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ public async Task ReplacesExceptionPropertiesNamesAsync()
Assert.Equal("stacktrace", propToAdd.SerializationName, StringComparer.OrdinalIgnoreCase);
}
[Fact]
public async Task DoesNotRenamePrimaryErrorMessageIfMatchAlreadyExistsAsync()
public async Task RenamesMatchAndAddsPrimaryErrorMessageIfMatchAlreadyExistsAsync()
{
var exception = root.AddClass(new CodeClass
{
Expand All @@ -484,10 +484,13 @@ public async Task DoesNotRenamePrimaryErrorMessageIfMatchAlreadyExistsAsync()
}).First();
Assert.False(exception.Properties.First().IsOfKind(CodePropertyKind.ErrorMessageOverride));// property is NOT message override
await ILanguageRefiner.RefineAsync(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
Assert.Equal("message", propToAdd.Name, StringComparer.OrdinalIgnoreCase);// property remains
Assert.Single(exception.Properties); // no new properties added
Assert.True(exception.Properties.First().IsOfKind(CodePropertyKind.ErrorMessageOverride));// property is now message override
Assert.Equal("message", exception.Properties.First().Name, StringComparer.OrdinalIgnoreCase); // name is expected.
var properties = exception.Properties.ToArray();
Assert.Equal("messageEscaped", propToAdd.Name, StringComparer.OrdinalIgnoreCase);// property remains
Assert.Equal(2, properties.Length); // no primary message property added
Assert.Equal("message", properties[0].Name, StringComparer.OrdinalIgnoreCase); // name is expected.
Assert.True(properties[0].IsOfKind(CodePropertyKind.ErrorMessageOverride));// property is now message override
Assert.Equal("messageEscaped", properties[1].Name, StringComparer.OrdinalIgnoreCase); // renamed property is renamed as expected.
Assert.True(properties[1].IsPrimaryErrorMessage);// property is IsPrimaryErrorMessage so that information deserialized into it shows up in the error information.
}
[Fact]
public async Task RenamesExceptionClassWithReservedPropertyNameAsync()
Expand All @@ -507,10 +510,12 @@ public async Task RenamesExceptionClassWithReservedPropertyNameAsync()
}
}).First();
await ILanguageRefiner.RefineAsync(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
var properties = exception.Properties.ToArray();
Assert.Equal("messageEscaped", exception.Name, StringComparer.OrdinalIgnoreCase);// class is renamed to avoid removing special overidden property
Assert.Equal("message", propToAdd.Name, StringComparer.OrdinalIgnoreCase); // property is unchanged
Assert.Single(exception.Properties); // no new properties added
Assert.Equal("message", exception.Properties.First().Name, StringComparer.OrdinalIgnoreCase);
Assert.Equal("messageEscapedProp", propToAdd.Name, StringComparer.OrdinalIgnoreCase); // property renamed to avoid conflicting with base
Assert.Equal(2, properties.Length); // primary message is added
Assert.Equal("message", properties[0].Name, StringComparer.OrdinalIgnoreCase); // we can still override exception message
Assert.Equal("messageEscapedProp", properties[1].Name, StringComparer.OrdinalIgnoreCase); // collision with class name
}
[Fact]
public async Task RenamesExceptionClassWithReservedPropertyNameWhenPropertyIsInitiallyAbsentAsync()
Expand Down
Loading