From c77f2d99a50fb5b0a6b5fd4cf28731534a49fcb3 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Sun, 25 Feb 2024 12:40:56 +0000 Subject: [PATCH 01/12] Update DynamicallyAccessMembers for IParseNode Enum methods --- src/serialization/IParseNode.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialization/IParseNode.cs b/src/serialization/IParseNode.cs index e9628dd3..541fcc14 100644 --- a/src/serialization/IParseNode.cs +++ b/src/serialization/IParseNode.cs @@ -101,7 +101,7 @@ public interface IParseNode /// /// The collection of enum values. #if NET5_0_OR_GREATER - IEnumerable GetCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]T>() where T : struct, Enum; + IEnumerable GetCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] T>() where T : struct, Enum; #else IEnumerable GetCollectionOfEnumValues() where T : struct, Enum; #endif @@ -116,7 +116,7 @@ public interface IParseNode /// /// The enum value of the node. #if NET5_0_OR_GREATER - T? GetEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]T>() where T : struct, Enum; + T? GetEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] T>() where T : struct, Enum; #else T? GetEnumValue() where T : struct, Enum; #endif From 8021a05eafd0b653ed2b6417d564fca9926113cc Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Sun, 25 Feb 2024 12:41:37 +0000 Subject: [PATCH 02/12] Fix ILC IL2075 warning when compiling AOT --- src/RequestInformation.cs | 59 ++++++++++++++++---------------- src/extensions/EnumExtensions.cs | 48 ++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 src/extensions/EnumExtensions.cs diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index e8573f5a..57d2adb4 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -8,8 +8,6 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.Kiota.Abstractions.Serialization; #if NET5_0_OR_GREATER @@ -53,7 +51,7 @@ public RequestInformation(Method method, string urlTemplate, IDictionary(Action>? requestConfiguration) where T : class, new() #endif { - if(requestConfiguration == null) return; + if (requestConfiguration == null) return; var requestConfig = new RequestConfiguration(); requestConfiguration(requestConfig); AddQueryParameters(requestConfig.QueryParameters); @@ -69,7 +67,7 @@ public Uri URI { set { - if(value == null) + if (value == null) throw new ArgumentNullException(nameof(value)); QueryParameters.Clear(); PathParameters.Clear(); @@ -77,9 +75,9 @@ public Uri URI } get { - if(_rawUri != null) + if (_rawUri != null) return _rawUri; - else if(PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && + else if (PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && rawUrl is string rawUrlString) { URI = new Uri(rawUrlString); @@ -87,18 +85,18 @@ public Uri URI } else { - if(UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) + if (UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) throw new InvalidOperationException($"{nameof(PathParameters)} must contain a value for \"baseurl\" for the url to be built."); var substitutions = new Dictionary(); - foreach(var urlTemplateParameter in PathParameters) + foreach (var urlTemplateParameter in PathParameters) { substitutions.Add(urlTemplateParameter.Key, GetSanitizedValues(urlTemplateParameter.Value)); } - foreach(var queryStringParameter in QueryParameters) + foreach (var queryStringParameter in QueryParameters) { - if(queryStringParameter.Value != null) + if (queryStringParameter.Value != null) { substitutions.Add(queryStringParameter.Key, GetSanitizedValues(queryStringParameter.Value)); } @@ -157,8 +155,8 @@ public Uri URI public void AddQueryParameters(T source) #endif { - if(source == null) return; - foreach(var property in typeof(T) + if (source == null) return; + foreach (var property in typeof(T) .GetProperties() .Select( x => ( @@ -179,7 +177,7 @@ public void AddQueryParameters(T source) private static object[] ExpandArray(Array collection) { var passedArray = new object[collection.Length]; - for(var i = 0; i < collection.Length; i++) + for (var i = 0; i < collection.Length; i++) { passedArray[i] = GetSanitizedValue(collection.GetValue(i)!); } @@ -188,7 +186,7 @@ private static object[] ExpandArray(Array collection) private static object ReplaceEnumValueByStringRepresentation(object source) { - if(source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) + if (source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) { return enumValueName; } @@ -203,14 +201,15 @@ private static object ReplaceEnumValueByStringRepresentation(object source) { var type = value.GetType(); - if(Enum.GetName(type, value) is not { } name) + if (Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); - if(type.GetField(name)?.GetCustomAttribute() is { } attribute) - return attribute.Value; + if (value.GetEnumMemberName(name) is { } enumMemberName) + return enumMemberName; return name.ToFirstCharacterLowerCase(); } + /// /// The Request Headers. /// @@ -220,7 +219,7 @@ private static object ReplaceEnumValueByStringRepresentation(object source) /// public void AddHeaders(RequestHeaders headers) { - if(headers == null) return; + if (headers == null) return; Headers.AddAll(headers); } /// @@ -238,8 +237,8 @@ public void AddHeaders(RequestHeaders headers) /// The option to add. public void AddRequestOptions(IEnumerable options) { - if(options == null) return; - foreach(var option in options.Where(x => x != null)) + if (options == null) return; + foreach (var option in options.Where(x => x != null)) _requestOptions.AddOrReplace(option.GetType().FullName!, option); } /// @@ -248,8 +247,8 @@ public void AddRequestOptions(IEnumerable options) /// Options to remove. public void RemoveRequestOptions(params IRequestOption[] options) { - if(options.Length == 0) throw new ArgumentNullException(nameof(options)); - foreach(var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) + if (options.Length == 0) throw new ArgumentNullException(nameof(options)); + foreach (var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) _requestOptions.Remove(optionName!); } @@ -263,7 +262,7 @@ public void RemoveRequestOptions(params IRequestOption[] options) /// public void SetResponseHandler(IResponseHandler responseHandler) { - if(responseHandler == null) + if (responseHandler == null) throw new ArgumentNullException(nameof(responseHandler)); var responseHandlerOption = new ResponseHandlerOption @@ -322,7 +321,7 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con using var activity = _activitySource?.StartActivity(nameof(SetContentFromParsable)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - if(item is MultipartBody mpBody) + if (item is MultipartBody mpBody) { contentType += "; boundary=" + mpBody.Boundary; mpBody.RequestAdapter = requestAdapter; @@ -333,15 +332,15 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con } private static void SetRequestType(object? result, Activity? activity) { - if(activity == null) return; - if(result == null) return; + if (activity == null) return; + if (result == null) return; activity.SetTag("com.microsoft.kiota.request.type", result.GetType().FullName); } private static ISerializationWriter GetSerializationWriter(IRequestAdapter requestAdapter, string contentType, T item) { - if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); - if(requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); - if(item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); + if (string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if (requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); + if (item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); return requestAdapter.SerializationWriterFactory.GetSerializationWriter(contentType); } /// @@ -372,7 +371,7 @@ public void SetContentFromScalar(IRequestAdapter requestAdapter, string conte using var activity = _activitySource?.StartActivity(nameof(SetContentFromScalar)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - switch(item) + switch (item) { case string s: writer.WriteStringValue(null, s); diff --git a/src/extensions/EnumExtensions.cs b/src/extensions/EnumExtensions.cs new file mode 100644 index 00000000..6e92a876 --- /dev/null +++ b/src/extensions/EnumExtensions.cs @@ -0,0 +1,48 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +using System; +using System.Reflection; +using System.Runtime.Serialization; +#if NET5_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +#endif + +namespace Microsoft.Kiota.Abstractions.Extensions +{ + /// + /// The class for extension methods for types + /// + internal static class EnumExtensions + { + /// + /// Returns the value of the on an Enum field, if present. + /// + /// The enum value. + /// The enum field name to check for . + /// The value of an for the named field, or . +#if NET5_0_OR_GREATER + internal static string? GetEnumMemberName<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(this T value, string name) where T : Enum +#else + internal static string? GetEnumMemberName(this T value, string name) where T : Enum +#endif + { +#if NET5_0_OR_GREATER + if(!RuntimeFeature.IsDynamicCodeSupported) + return typeof(T).GetField(name)?.GetCustomAttribute()?.Value; +#endif + + // We can suppress ILC warning IL2075 as dynamic code is supported, so the field has not been trimmed +#pragma warning disable IL2075 + var type = value.GetType(); + + if(type.GetField(name)?.GetCustomAttribute() is { } runtimeTypeAttribute) + return runtimeTypeAttribute.Value; +#pragma warning restore IL2075 + + return null; + } + } +} \ No newline at end of file From fd47a5dbed94db88c68c9b6e601c65cc3c4d8463 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Sun, 25 Feb 2024 12:42:27 +0000 Subject: [PATCH 03/12] Update version and changelog --- CHANGELOG.md | 6 ++++++ src/Microsoft.Kiota.Abstractions.csproj | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 712d2a62..1fdd448b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.7.11] - 2024-02-26 + +### Changed + +- Fixed AOT compiler warnings from ILC. + ## [1.7.10] - 2024-02-26 ### Changed diff --git a/src/Microsoft.Kiota.Abstractions.csproj b/src/Microsoft.Kiota.Abstractions.csproj index e423838a..b8d78f67 100644 --- a/src/Microsoft.Kiota.Abstractions.csproj +++ b/src/Microsoft.Kiota.Abstractions.csproj @@ -14,7 +14,7 @@ https://aka.ms/kiota/docs true true - 1.7.10 + 1.7.11 true false From 6f4da01985a7189ee6a440822a7b91dd24b0de6a Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 12:29:01 +0000 Subject: [PATCH 04/12] Updates per review Also reverts styling changes --- src/RequestInformation.cs | 60 +++++++++++++++++--------------- src/extensions/EnumExtensions.cs | 48 ------------------------- 2 files changed, 31 insertions(+), 77 deletions(-) delete mode 100644 src/extensions/EnumExtensions.cs diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index 57d2adb4..fa6126a5 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -10,6 +10,8 @@ using System.Linq; using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.Kiota.Abstractions.Serialization; +using System.Runtime.Serialization; +using System.Reflection; #if NET5_0_OR_GREATER using System.Diagnostics.CodeAnalysis; #endif @@ -51,7 +53,7 @@ public RequestInformation(Method method, string urlTemplate, IDictionary(Action>? requestConfiguration) where T : class, new() #endif { - if (requestConfiguration == null) return; + if(requestConfiguration == null) return; var requestConfig = new RequestConfiguration(); requestConfiguration(requestConfig); AddQueryParameters(requestConfig.QueryParameters); @@ -67,7 +69,7 @@ public Uri URI { set { - if (value == null) + if(value == null) throw new ArgumentNullException(nameof(value)); QueryParameters.Clear(); PathParameters.Clear(); @@ -75,9 +77,9 @@ public Uri URI } get { - if (_rawUri != null) + if(_rawUri != null) return _rawUri; - else if (PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && + else if(PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && rawUrl is string rawUrlString) { URI = new Uri(rawUrlString); @@ -85,18 +87,18 @@ public Uri URI } else { - if (UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) + if(UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) throw new InvalidOperationException($"{nameof(PathParameters)} must contain a value for \"baseurl\" for the url to be built."); var substitutions = new Dictionary(); - foreach (var urlTemplateParameter in PathParameters) + foreach(var urlTemplateParameter in PathParameters) { substitutions.Add(urlTemplateParameter.Key, GetSanitizedValues(urlTemplateParameter.Value)); } - foreach (var queryStringParameter in QueryParameters) + foreach(var queryStringParameter in QueryParameters) { - if (queryStringParameter.Value != null) + if(queryStringParameter.Value != null) { substitutions.Add(queryStringParameter.Key, GetSanitizedValues(queryStringParameter.Value)); } @@ -155,8 +157,8 @@ public Uri URI public void AddQueryParameters(T source) #endif { - if (source == null) return; - foreach (var property in typeof(T) + if(source == null) return; + foreach(var property in typeof(T) .GetProperties() .Select( x => ( @@ -177,7 +179,7 @@ public void AddQueryParameters(T source) private static object[] ExpandArray(Array collection) { var passedArray = new object[collection.Length]; - for (var i = 0; i < collection.Length; i++) + for(var i = 0; i < collection.Length; i++) { passedArray[i] = GetSanitizedValue(collection.GetValue(i)!); } @@ -186,7 +188,7 @@ private static object[] ExpandArray(Array collection) private static object ReplaceEnumValueByStringRepresentation(object source) { - if (source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) + if(source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) { return enumValueName; } @@ -199,13 +201,13 @@ private static object ReplaceEnumValueByStringRepresentation(object source) private static string? GetEnumName(T value) where T : Enum #endif { - var type = value.GetType(); + var type = typeof(T); - if (Enum.GetName(type, value) is not { } name) + if(Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); - if (value.GetEnumMemberName(name) is { } enumMemberName) - return enumMemberName; + if(type.GetField(name)?.GetCustomAttribute() is { } attribute) + return attribute.Value; return name.ToFirstCharacterLowerCase(); } @@ -219,7 +221,7 @@ private static object ReplaceEnumValueByStringRepresentation(object source) /// public void AddHeaders(RequestHeaders headers) { - if (headers == null) return; + if(headers == null) return; Headers.AddAll(headers); } /// @@ -237,8 +239,8 @@ public void AddHeaders(RequestHeaders headers) /// The option to add. public void AddRequestOptions(IEnumerable options) { - if (options == null) return; - foreach (var option in options.Where(x => x != null)) + if(options == null) return; + foreach(var option in options.Where(x => x != null)) _requestOptions.AddOrReplace(option.GetType().FullName!, option); } /// @@ -247,8 +249,8 @@ public void AddRequestOptions(IEnumerable options) /// Options to remove. public void RemoveRequestOptions(params IRequestOption[] options) { - if (options.Length == 0) throw new ArgumentNullException(nameof(options)); - foreach (var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) + if(options.Length == 0) throw new ArgumentNullException(nameof(options)); + foreach(var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) _requestOptions.Remove(optionName!); } @@ -262,7 +264,7 @@ public void RemoveRequestOptions(params IRequestOption[] options) /// public void SetResponseHandler(IResponseHandler responseHandler) { - if (responseHandler == null) + if(responseHandler == null) throw new ArgumentNullException(nameof(responseHandler)); var responseHandlerOption = new ResponseHandlerOption @@ -321,7 +323,7 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con using var activity = _activitySource?.StartActivity(nameof(SetContentFromParsable)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - if (item is MultipartBody mpBody) + if(item is MultipartBody mpBody) { contentType += "; boundary=" + mpBody.Boundary; mpBody.RequestAdapter = requestAdapter; @@ -332,15 +334,15 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con } private static void SetRequestType(object? result, Activity? activity) { - if (activity == null) return; - if (result == null) return; + if(activity == null) return; + if(result == null) return; activity.SetTag("com.microsoft.kiota.request.type", result.GetType().FullName); } private static ISerializationWriter GetSerializationWriter(IRequestAdapter requestAdapter, string contentType, T item) { - if (string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); - if (requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); - if (item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); + if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if(requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); + if(item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); return requestAdapter.SerializationWriterFactory.GetSerializationWriter(contentType); } /// @@ -371,7 +373,7 @@ public void SetContentFromScalar(IRequestAdapter requestAdapter, string conte using var activity = _activitySource?.StartActivity(nameof(SetContentFromScalar)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - switch (item) + switch(item) { case string s: writer.WriteStringValue(null, s); diff --git a/src/extensions/EnumExtensions.cs b/src/extensions/EnumExtensions.cs deleted file mode 100644 index 6e92a876..00000000 --- a/src/extensions/EnumExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. -// ------------------------------------------------------------------------------ - -using System; -using System.Reflection; -using System.Runtime.Serialization; -#if NET5_0_OR_GREATER -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -#endif - -namespace Microsoft.Kiota.Abstractions.Extensions -{ - /// - /// The class for extension methods for types - /// - internal static class EnumExtensions - { - /// - /// Returns the value of the on an Enum field, if present. - /// - /// The enum value. - /// The enum field name to check for . - /// The value of an for the named field, or . -#if NET5_0_OR_GREATER - internal static string? GetEnumMemberName<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(this T value, string name) where T : Enum -#else - internal static string? GetEnumMemberName(this T value, string name) where T : Enum -#endif - { -#if NET5_0_OR_GREATER - if(!RuntimeFeature.IsDynamicCodeSupported) - return typeof(T).GetField(name)?.GetCustomAttribute()?.Value; -#endif - - // We can suppress ILC warning IL2075 as dynamic code is supported, so the field has not been trimmed -#pragma warning disable IL2075 - var type = value.GetType(); - - if(type.GetField(name)?.GetCustomAttribute() is { } runtimeTypeAttribute) - return runtimeTypeAttribute.Value; -#pragma warning restore IL2075 - - return null; - } - } -} \ No newline at end of file From e61bed7e4696b899f68f168a2ca501dba0df98db Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 12:33:03 +0000 Subject: [PATCH 05/12] Reduce IParseNode enum methods to only specify PublicFields DynamicAccess --- src/serialization/IParseNode.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialization/IParseNode.cs b/src/serialization/IParseNode.cs index 541fcc14..422ef532 100644 --- a/src/serialization/IParseNode.cs +++ b/src/serialization/IParseNode.cs @@ -101,7 +101,7 @@ public interface IParseNode /// /// The collection of enum values. #if NET5_0_OR_GREATER - IEnumerable GetCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] T>() where T : struct, Enum; + IEnumerable GetCollectionOfEnumValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>() where T : struct, Enum; #else IEnumerable GetCollectionOfEnumValues() where T : struct, Enum; #endif @@ -116,7 +116,7 @@ public interface IParseNode /// /// The enum value of the node. #if NET5_0_OR_GREATER - T? GetEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] T>() where T : struct, Enum; + T? GetEnumValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>() where T : struct, Enum; #else T? GetEnumValue() where T : struct, Enum; #endif From f9e5880d5eac29f771dab966d665a60cacdc6223 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 13:14:59 +0000 Subject: [PATCH 06/12] Revert GetEnumName change --- src/RequestInformation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index fa6126a5..cc8a0fff 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -201,7 +201,7 @@ private static object ReplaceEnumValueByStringRepresentation(object source) private static string? GetEnumName(T value) where T : Enum #endif { - var type = typeof(T); + var type = value.GetType(); if(Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); From 80afc6df686934b6da2aed6478801b1cc4065b2f Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 13:16:31 +0000 Subject: [PATCH 07/12] Update changelog to reflect reduced scope --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fdd448b..9ec9b796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Fixed AOT compiler warnings from ILC. +- Update IParseNode enum methods `DynamicallyAccessedMembersAttribute` to `PublicFields`. ## [1.7.10] - 2024-02-26 From ab2974f719e398403747e3e60b2ca4054c49dbe3 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 13:17:17 +0000 Subject: [PATCH 08/12] Fully revert change --- src/RequestInformation.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index cc8a0fff..e1be9ffc 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -8,10 +8,10 @@ using System.Diagnostics; using System.IO; using System.Linq; -using Microsoft.Kiota.Abstractions.Extensions; -using Microsoft.Kiota.Abstractions.Serialization; using System.Runtime.Serialization; using System.Reflection; +using Microsoft.Kiota.Abstractions.Extensions; +using Microsoft.Kiota.Abstractions.Serialization; #if NET5_0_OR_GREATER using System.Diagnostics.CodeAnalysis; #endif @@ -211,7 +211,6 @@ private static object ReplaceEnumValueByStringRepresentation(object source) return name.ToFirstCharacterLowerCase(); } - /// /// The Request Headers. /// From 89fe76a234b65278c15d78740d98b1addd34c439 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 13:20:39 +0000 Subject: [PATCH 09/12] Actually fully revert change --- src/RequestInformation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index e1be9ffc..e8573f5a 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -8,8 +8,8 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.Serialization; using System.Reflection; +using System.Runtime.Serialization; using Microsoft.Kiota.Abstractions.Extensions; using Microsoft.Kiota.Abstractions.Serialization; #if NET5_0_OR_GREATER From 7c179bfeeea29a66d52db7a25f8d347ca5aeaa05 Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 14:34:27 +0000 Subject: [PATCH 10/12] Add IL2075 suppression Per https://github.com/microsoft/kiota-abstractions-dotnet/pull/202#issuecomment-1964246030, we know that enumerating an enum here is trimming-safe --- CHANGELOG.md | 3 ++- src/RequestInformation.cs | 56 ++++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec9b796..063ec50f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Update IParseNode enum methods `DynamicallyAccessedMembersAttribute` to `PublicFields`. +- Updated IParseNode enum methods `DynamicallyAccessedMembersAttribute` to `PublicFields`. +- Fixed AOT compiler warnings from ILC. ## [1.7.10] - 2024-02-26 diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index e8573f5a..dbe19775 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -53,7 +53,7 @@ public RequestInformation(Method method, string urlTemplate, IDictionary(Action>? requestConfiguration) where T : class, new() #endif { - if(requestConfiguration == null) return; + if (requestConfiguration == null) return; var requestConfig = new RequestConfiguration(); requestConfiguration(requestConfig); AddQueryParameters(requestConfig.QueryParameters); @@ -69,7 +69,7 @@ public Uri URI { set { - if(value == null) + if (value == null) throw new ArgumentNullException(nameof(value)); QueryParameters.Clear(); PathParameters.Clear(); @@ -77,9 +77,9 @@ public Uri URI } get { - if(_rawUri != null) + if (_rawUri != null) return _rawUri; - else if(PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && + else if (PathParameters.TryGetValue(RawUrlKey, out var rawUrl) && rawUrl is string rawUrlString) { URI = new Uri(rawUrlString); @@ -87,18 +87,18 @@ public Uri URI } else { - if(UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) + if (UrlTemplate?.IndexOf("{+baseurl}", StringComparison.OrdinalIgnoreCase) >= 0 && !PathParameters.ContainsKey("baseurl")) throw new InvalidOperationException($"{nameof(PathParameters)} must contain a value for \"baseurl\" for the url to be built."); var substitutions = new Dictionary(); - foreach(var urlTemplateParameter in PathParameters) + foreach (var urlTemplateParameter in PathParameters) { substitutions.Add(urlTemplateParameter.Key, GetSanitizedValues(urlTemplateParameter.Value)); } - foreach(var queryStringParameter in QueryParameters) + foreach (var queryStringParameter in QueryParameters) { - if(queryStringParameter.Value != null) + if (queryStringParameter.Value != null) { substitutions.Add(queryStringParameter.Key, GetSanitizedValues(queryStringParameter.Value)); } @@ -157,8 +157,8 @@ public Uri URI public void AddQueryParameters(T source) #endif { - if(source == null) return; - foreach(var property in typeof(T) + if (source == null) return; + foreach (var property in typeof(T) .GetProperties() .Select( x => ( @@ -179,7 +179,7 @@ public void AddQueryParameters(T source) private static object[] ExpandArray(Array collection) { var passedArray = new object[collection.Length]; - for(var i = 0; i < collection.Length; i++) + for (var i = 0; i < collection.Length; i++) { passedArray[i] = GetSanitizedValue(collection.GetValue(i)!); } @@ -188,7 +188,7 @@ private static object[] ExpandArray(Array collection) private static object ReplaceEnumValueByStringRepresentation(object source) { - if(source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) + if (source is Enum enumValue && GetEnumName(enumValue) is string enumValueName) { return enumValueName; } @@ -203,11 +203,13 @@ private static object ReplaceEnumValueByStringRepresentation(object source) { var type = value.GetType(); - if(Enum.GetName(type, value) is not { } name) + if (Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); - if(type.GetField(name)?.GetCustomAttribute() is { } attribute) +#pragma warning disable IL2075 // Enumerating Enum fields is always trimming/AOT safe - https://github.com/dotnet/runtime/issues/97737 + if (type.GetField(name, BindingFlags.Static | BindingFlags.Public)?.GetCustomAttribute() is { } attribute) return attribute.Value; +#pragma warning restore IL2075 return name.ToFirstCharacterLowerCase(); } @@ -220,7 +222,7 @@ private static object ReplaceEnumValueByStringRepresentation(object source) /// public void AddHeaders(RequestHeaders headers) { - if(headers == null) return; + if (headers == null) return; Headers.AddAll(headers); } /// @@ -238,8 +240,8 @@ public void AddHeaders(RequestHeaders headers) /// The option to add. public void AddRequestOptions(IEnumerable options) { - if(options == null) return; - foreach(var option in options.Where(x => x != null)) + if (options == null) return; + foreach (var option in options.Where(x => x != null)) _requestOptions.AddOrReplace(option.GetType().FullName!, option); } /// @@ -248,8 +250,8 @@ public void AddRequestOptions(IEnumerable options) /// Options to remove. public void RemoveRequestOptions(params IRequestOption[] options) { - if(options.Length == 0) throw new ArgumentNullException(nameof(options)); - foreach(var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) + if (options.Length == 0) throw new ArgumentNullException(nameof(options)); + foreach (var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName)) _requestOptions.Remove(optionName!); } @@ -263,7 +265,7 @@ public void RemoveRequestOptions(params IRequestOption[] options) /// public void SetResponseHandler(IResponseHandler responseHandler) { - if(responseHandler == null) + if (responseHandler == null) throw new ArgumentNullException(nameof(responseHandler)); var responseHandlerOption = new ResponseHandlerOption @@ -322,7 +324,7 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con using var activity = _activitySource?.StartActivity(nameof(SetContentFromParsable)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - if(item is MultipartBody mpBody) + if (item is MultipartBody mpBody) { contentType += "; boundary=" + mpBody.Boundary; mpBody.RequestAdapter = requestAdapter; @@ -333,15 +335,15 @@ public void SetContentFromParsable(IRequestAdapter requestAdapter, string con } private static void SetRequestType(object? result, Activity? activity) { - if(activity == null) return; - if(result == null) return; + if (activity == null) return; + if (result == null) return; activity.SetTag("com.microsoft.kiota.request.type", result.GetType().FullName); } private static ISerializationWriter GetSerializationWriter(IRequestAdapter requestAdapter, string contentType, T item) { - if(string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); - if(requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); - if(item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); + if (string.IsNullOrEmpty(contentType)) throw new ArgumentNullException(nameof(contentType)); + if (requestAdapter == null) throw new ArgumentNullException(nameof(requestAdapter)); + if (item == null) throw new InvalidOperationException($"{nameof(item)} cannot be null"); return requestAdapter.SerializationWriterFactory.GetSerializationWriter(contentType); } /// @@ -372,7 +374,7 @@ public void SetContentFromScalar(IRequestAdapter requestAdapter, string conte using var activity = _activitySource?.StartActivity(nameof(SetContentFromScalar)); using var writer = GetSerializationWriter(requestAdapter, contentType, item); SetRequestType(item, activity); - switch(item) + switch (item) { case string s: writer.WriteStringValue(null, s); From 44b98e02c42a7d0feef26ad2004bce3c9050ea3d Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 16:25:32 +0000 Subject: [PATCH 11/12] Update to use UnconditionalSuppressMessage Thank you @eerhardt Co-authored-by: Eric Erhardt --- src/RequestInformation.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index dbe19775..4df30824 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -206,12 +206,12 @@ private static object ReplaceEnumValueByStringRepresentation(object source) if (Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); -#pragma warning disable IL2075 // Enumerating Enum fields is always trimming/AOT safe - https://github.com/dotnet/runtime/issues/97737 - if (type.GetField(name, BindingFlags.Static | BindingFlags.Public)?.GetCustomAttribute() is { } attribute) - return attribute.Value; -#pragma warning restore IL2075 + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "Enumerating Enum fields is always trimming/AOT safe - https://github.com/dotnet/runtime/issues/97737")] + static string? GetEnumMemberValue(Type enumType, string name) => + enumType.GetField(name, BindingFlags.Static | BindingFlags.Public)?.GetCustomAttribute() is { } attribute ? attribute.Value : null; - return name.ToFirstCharacterLowerCase(); + return GetEnumMemberValue(type, name) ?? name.ToFirstCharacterLowerCase(); } /// /// The Request Headers. From e25da97b31375061bc186783d4d39bf48ebc3e4b Mon Sep 17 00:00:00 2001 From: Hugo Woodiwiss Date: Mon, 26 Feb 2024 17:04:48 +0000 Subject: [PATCH 12/12] Fix Trim Warning, version gate Co-authored-by: Eric Erhardt --- src/RequestInformation.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/RequestInformation.cs b/src/RequestInformation.cs index 4df30824..56ff78e1 100644 --- a/src/RequestInformation.cs +++ b/src/RequestInformation.cs @@ -206,8 +206,10 @@ private static object ReplaceEnumValueByStringRepresentation(object source) if (Enum.GetName(type, value) is not { } name) throw new ArgumentException($"Invalid Enum value {value} for enum of type {type}"); - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", +#if NET5_0_OR_GREATER + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "Enumerating Enum fields is always trimming/AOT safe - https://github.com/dotnet/runtime/issues/97737")] +#endif static string? GetEnumMemberValue(Type enumType, string name) => enumType.GetField(name, BindingFlags.Static | BindingFlags.Public)?.GetCustomAttribute() is { } attribute ? attribute.Value : null;