Skip to content

Commit

Permalink
Merge branch 'main' into elinor/add-kiota-workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
baywet committed Jul 3, 2024
2 parents 03edf32 + 77b80dd commit 30d12af
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 61 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Push to GitHub Packages - Nightly
if: contains(github.ref, env.PREVIEW_BRANCH)
uses: docker/build-push-action@v6.2.0
uses: docker/build-push-action@v6.3.0
with:
push: true
platforms: linux/amd64,linux/arm64/v8,linux/arm/v7
Expand All @@ -84,7 +84,7 @@ jobs:
# we can't get the sequence number from ADO so we default it back to github run number
- name: Push to GitHub Packages - Release
if: contains(github.ref, 'refs/tags/v')
uses: docker/build-push-action@v6.2.0
uses: docker/build-push-action@v6.3.0
with:
push: true
platforms: linux/amd64,linux/arm64/v8,linux/arm/v7
Expand Down
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

<!-- markdownlint-disable-file MD024 -->

## [Unreleased]

### Added
Expand All @@ -22,6 +24,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- References to C# types generated by kiota are prefixed with `global::` to avoid name collisions. [#4796](https://github.com/microsoft/kiota/issues/4796)
- Ensures HashSet properties in `KiotaLock` maintain IgnoreCase comparer across runs [#4916](https://github.com/microsoft/kiota/issues/4916)
- Dropped `client base url set to` message when generating plugins. [#4905](https://github.com/microsoft/kiota/issues/4905)
- Emit `[GeneratedCode]` attribute for C# types. [#4907](https://github.com/microsoft/kiota/issues/4907)
- Fixes error property disambiguation when the property has the same name as class [#4893](https://github.com/microsoft/kiota/issues/)
- Fixes missing imports for `UntypedNode` for method parameter and return value scenarios. [#4925](https://github.com/microsoft/kiota/issues/4925)

## [1.15.0] - 2024-06-06

Expand Down Expand Up @@ -880,7 +885,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Split parsable interface and additional property/data interface in Ruby. [#1654](https://github.com/microsoft/kiota/issues/1654)
- Changed format of datetimes in Go to be converted to ISO 8601 by default when place in path parameters(Go)
- Defined the Access Token Provider Interface for Ruby authentication. [#1638](https://github.com/microsoft/kiota/issues/1638)
- Reduce code verbosity on Go Getters and Setters. [G0#26][https://github.com/microsoftgraph/msgraph-sdk-go-core/issues/26]
- Reduce code verbosity on Go Getters and Setters. [G0#26](https://github.com/microsoftgraph/msgraph-sdk-go-core/issues/26)

## [0.3.0] - 2022-07-08

Expand Down
12 changes: 11 additions & 1 deletion src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ protected static void ReplaceReservedExceptionPropertyNames(CodeElement current,
provider,
replacement,
null,
static x => ((x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Custom)) || x is CodeMethod) && x.Parent is CodeClass parent && parent.IsOfKind(CodeClassKind.Model) && parent.IsErrorDefinition
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.
);
}
protected static void ReplaceReservedNames(CodeElement current, IReservedNamesProvider provider, Func<string, string> replacement, HashSet<Type>? codeElementExceptions = null, Func<CodeElement, bool>? shouldReplaceCallback = null)
Expand Down Expand Up @@ -1507,6 +1509,14 @@ internal static void AddPrimaryErrorMessage(CodeElement currentElement, string n
{
if (asProperty)
{
if (currentClass.Properties.FirstOrDefault(property => property.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) 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
}

currentClass.AddProperty(new CodeProperty
{
Name = name,
Expand Down
3 changes: 2 additions & 1 deletion src/Kiota.Builder/Refiners/TypeScriptRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,8 @@ private static bool HasMultipartBody(CodeMethod m) =>
AbstractionsPackageName, true, "BackingStore", "BackedModel"),
new (static x => x is CodeMethod m && HasMultipartBody(m),
AbstractionsPackageName, MultipartBodyClassName, $"serialize{MultipartBodyClassName}"),
new (static x => x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Custom) && prop.Type.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase),
new (static x => (x is CodeProperty prop && prop.IsOfKind(CodePropertyKind.Custom) && prop.Type.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase))
|| (x is CodeMethod method && (method.Parameters.Any(param => param.Type.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase)) || method.ReturnType.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase))),
AbstractionsPackageName, KiotaBuilder.UntypedNodeName, "createUntypedNodeFromDiscriminatorValue"),
};
private const string MultipartBodyClassName = "MultipartBody";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Kiota.Builder.Writers.CSharp;
public class CodeClassDeclarationWriter : BaseElementWriter<ClassDeclaration, CSharpConventionService>
{
public static string AutoGenerationHeader => "// <auto-generated/>";
public static string GeneratedCodeAttribute { get; } = $"[global::System.CodeDom.Compiler.GeneratedCode(\"Kiota\", \"{Kiota.Generated.KiotaVersion.Current()}\")]";
public CodeClassDeclarationWriter(CSharpConventionService conventionService) : base(conventionService) { }
public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWriter writer)
{
Expand Down Expand Up @@ -37,6 +38,7 @@ public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWrit
var derivation = derivedTypes.Length != 0 ? ": " + derivedTypes.Aggregate(static (x, y) => $"{x}, {y}") : string.Empty;
bool hasDescription = conventions.WriteLongDescription(parentClass, writer);
conventions.WriteDeprecationAttribute(parentClass, writer);
writer.WriteLine(GeneratedCodeAttribute);
if (!hasDescription) writer.WriteLine("#pragma warning disable CS1591");
writer.WriteLine($"public partial class {codeElement.Name.ToFirstCharacterUpperCase()} {derivation}");
if (!hasDescription) writer.WriteLine("#pragma warning restore CS1591");
Expand Down
2 changes: 2 additions & 0 deletions src/Kiota.Builder/Writers/CSharp/CodeEnumWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Kiota.Builder.Writers.CSharp;
public class CodeEnumWriter : BaseElementWriter<CodeEnum, CSharpConventionService>
{
public static string AutoGenerationHeader => "// <auto-generated/>";
public static string GeneratedCodeAttribute { get; } = $"[global::System.CodeDom.Compiler.GeneratedCode(\"Kiota\", \"{Kiota.Generated.KiotaVersion.Current()}\")]";
public CodeEnumWriter(CSharpConventionService conventionService) : base(conventionService) { }
public override void WriteCodeElement(CodeEnum codeElement, LanguageWriter writer)
{
Expand All @@ -30,6 +31,7 @@ public override void WriteCodeElement(CodeEnum codeElement, LanguageWriter write
writer.WriteLine($"namespace {codeNamespace.Name}");
writer.StartBlock();
}
writer.WriteLine(GeneratedCodeAttribute);
bool hasDescription = conventions.WriteShortDescription(codeElement, writer);
if (codeElement.Flags)
writer.WriteLine("[Flags]");
Expand Down
75 changes: 73 additions & 2 deletions tests/Kiota.Builder.Tests/Refiners/CSharpLanguageRefinerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,27 @@ public async Task KeepsCancellationParametersInRequestExecutors()
}
[Fact]
public async Task ReplacesExceptionPropertiesNames()
{
var exception = root.AddClass(new CodeClass
{
Name = "error403",
Kind = CodeClassKind.Model,
IsErrorDefinition = true,
}).First();
var propToAdd = exception.AddProperty(new CodeProperty
{
Name = "stacktrace",
Type = new CodeType
{
Name = "string"
}
}).First();
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
Assert.Equal("stacktraceEscaped", propToAdd.Name, StringComparer.OrdinalIgnoreCase);
Assert.Equal("stacktrace", propToAdd.SerializationName, StringComparer.OrdinalIgnoreCase);
}
[Fact]
public async Task DoesNotRenamePrimaryErrorMessageIfMatchAlreadyExists()
{
var exception = root.AddClass(new CodeClass
{
Expand All @@ -461,9 +482,59 @@ public async Task ReplacesExceptionPropertiesNames()
Name = "string"
}
}).First();
Assert.False(exception.Properties.First().IsOfKind(CodePropertyKind.ErrorMessageOverride));// property is NOT message override
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
Assert.Equal("messageEscaped", propToAdd.Name, StringComparer.OrdinalIgnoreCase);
Assert.Equal("message", propToAdd.SerializationName, StringComparer.OrdinalIgnoreCase);
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.
}
[Fact]
public async Task RenamesExceptionClassWithReservedPropertyName()
{
var exception = root.AddClass(new CodeClass
{
Name = "message",
Kind = CodeClassKind.Model,
IsErrorDefinition = true,
}).First();
var propToAdd = exception.AddProperty(new CodeProperty
{
Name = "message",
Type = new CodeType
{
Name = "string"
}
}).First();
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
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);
}
[Fact]
public async Task RenamesExceptionClassWithReservedPropertyNameWhenPropertyIsInitiallyAbsent()
{
var exception = root.AddClass(new CodeClass
{
Name = "message",
Kind = CodeClassKind.Model,
IsErrorDefinition = true,
}).First();
var propToAdd = exception.AddProperty(new CodeProperty
{
Name = "something",
Type = new CodeType
{
Name = "string"
}
}).First();
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.CSharp }, root);
Assert.Equal("messageEscaped", exception.Name, StringComparer.OrdinalIgnoreCase);// class is renamed to avoid removing special overidden property
Assert.Equal("something", propToAdd.Name, StringComparer.OrdinalIgnoreCase); // existing property remains
Assert.Equal(2, exception.Properties.Count()); // initial property plus primary message
Assert.Equal("message", exception.Properties.ToArray()[0].Name, StringComparer.OrdinalIgnoreCase); // primary error message is present
Assert.Equal("something", exception.Properties.ToArray()[1].Name, StringComparer.OrdinalIgnoreCase);// existing property remains
}
[Fact]
public async Task DoesNotReplaceNonExceptionPropertiesNames()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -840,5 +840,55 @@ public async Task AddsUsingForUntypedNode()
Assert.Single(nodeUsing);
Assert.Equal("@microsoft/kiota-abstractions", nodeUsing[0].Declaration.Name);
}
[Fact]
public async Task AddsUsingForUntypedNodeInReturnType()
{
var requestBuilderClass = root.AddClass(new CodeClass() { Name = "NodeRequestBuilder" }).First();
var model = new CodeMethod
{
Name = "getAsync",
ReturnType = new CodeType
{
Name = KiotaBuilder.UntypedNodeName
}
};
requestBuilderClass.AddMethod(model);
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.TypeScript }, root);
Assert.Equal(KiotaBuilder.UntypedNodeName, model.ReturnType.Name);// type is renamed
Assert.NotEmpty(requestBuilderClass.StartBlock.Usings);
var nodeUsing = requestBuilderClass.StartBlock.Usings.Where(static declaredUsing => declaredUsing.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase)).ToArray();
Assert.Single(nodeUsing);
Assert.Equal("@microsoft/kiota-abstractions", nodeUsing[0].Declaration.Name);
}
[Fact]
public async Task AddsUsingForUntypedNodeInMethodParameter()
{
var requestBuilderClass = root.AddClass(new CodeClass() { Name = "NodeRequestBuilder" }).First();
var method = new CodeMethod
{
Name = "getAsync",
ReturnType = new CodeType
{
Name = "string",
IsExternal = true
}
};
method.AddParameter(new CodeParameter()
{
Name = "jsonData",
Type = new CodeType()
{
Name = KiotaBuilder.UntypedNodeName,
IsExternal = true
}
});
requestBuilderClass.AddMethod(method);
await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.TypeScript }, root);
Assert.Equal(KiotaBuilder.UntypedNodeName, method.Parameters.First().Type.Name);// type is renamed
Assert.NotEmpty(requestBuilderClass.StartBlock.Usings);
var nodeUsing = requestBuilderClass.StartBlock.Usings.Where(static declaredUsing => declaredUsing.Name.Equals(KiotaBuilder.UntypedNodeName, StringComparison.OrdinalIgnoreCase)).ToArray();
Assert.Single(nodeUsing);
Assert.Equal("@microsoft/kiota-abstractions", nodeUsing[0].Declaration.Name);
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,13 @@ public void WritesImports()
Assert.Contains("Project.Graph", result);
Assert.Contains("System.Util", result);
}

[Fact]
public void WritesGeneratedCodeAttribute()
{
codeElementWriter.WriteCodeElement(parentClass.StartBlock, writer);
var result = tw.ToString();
var pattern = @"\s+\[global::System\.CodeDom\.Compiler\.GeneratedCode\(""Kiota"", ""[0-9]+\.[0-9]+\.[0-9]+\""\)\]";
Assert.Matches(pattern, result);
}
}
12 changes: 12 additions & 0 deletions tests/Kiota.Builder.Tests/Writers/CSharp/CodeEnumWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public void WritesFlagsEnum()
Assert.Contains("= 1", result);
Assert.Contains("= 2", result);
}

[Fact]
public void WritesEnumOptionDescription()
{
Expand All @@ -120,11 +121,22 @@ public void WritesEnumOptionDescription()
Assert.Contains($"<summary>{Option.Documentation.DescriptionTemplate}</summary>", result);
AssertExtensions.CurlyBracesAreClosed(result, 1);
}

[Fact]
public void DoesntWriteAnythingOnNoOption()
{
writer.Write(currentEnum);
var result = tw.ToString();
Assert.Empty(result);
}

[Fact]
public void WritesGeneratedCodeAttribute()
{
currentEnum.AddOption(new CodeEnumOption { Name = "option2" });
writer.Write(currentEnum);
var result = tw.ToString();
var pattern = @"\s+\[global::System\.CodeDom\.Compiler\.GeneratedCode\(""Kiota"", ""[0-9]+\.[0-9]+\.[0-9]+\""\)\]";
Assert.Matches(pattern, result);
}
}
Loading

0 comments on commit 30d12af

Please sign in to comment.