Skip to content

Commit ac62342

Browse files
authored
Merge pull request #63 from microsoft/andrueastman/NRT
Adds support for nullable ref types
2 parents b0cd595 + 8a58f9a commit ac62342

23 files changed

+133
-118
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Changed
1313

14+
## [1.0.0-rc.4] - 2023-01-17
15+
16+
### Changed
17+
18+
- Adds support for nullable reference types
19+
1420
## [1.0.0-rc.3] - 2023-01-09
1521

1622
### Changed

Microsoft.Kiota.Abstractions.Tests/Microsoft.Kiota.Abstractions.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<TargetFrameworks>net462;net6.0</TargetFrameworks>
66
<LangVersion>latest</LangVersion>
77
<OutputType>Library</OutputType>
8+
<IsTestProject>true</IsTestProject>
89
</PropertyGroup>
910

1011
<ItemGroup>

Microsoft.Kiota.Abstractions.Tests/RequestHeadersTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ public void RemovesValue() {
4242
instance.Remove("name", "value");
4343
Assert.Equal(new [] { "value2" }, instance["name"]);
4444
instance.Remove("name", "value2");
45-
Assert.Null(instance["name"]);
45+
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
4646
}
4747
[Fact]
4848
public void Removes() {
4949
var instance = new RequestHeaders();
5050
instance.Add("name", "value");
5151
instance.Add("name", "value2");
5252
Assert.True(instance.Remove("name"));
53-
Assert.Null(instance["name"]);
53+
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
5454
Assert.False(instance.Remove("name"));
5555
}
5656
[Fact]
@@ -59,7 +59,7 @@ public void RemovesKVP() {
5959
instance.Add("name", "value");
6060
instance.Add("name", "value2");
6161
Assert.True(instance.Remove(new KeyValuePair<string, IEnumerable<string>>("name", new [] { "value", "value2" })));
62-
Assert.Null(instance["name"]);
62+
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
6363
Assert.False(instance.Remove("name"));
6464
}
6565
[Fact]
@@ -68,7 +68,8 @@ public void Clears() {
6868
instance.Add("name", "value");
6969
instance.Add("name", "value2");
7070
instance.Clear();
71-
Assert.Null(instance["name"]);
71+
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
72+
Assert.Empty(instance.Keys);
7273
}
7374
[Fact]
7475
public void GetsEnumerator() {

src/IRequestAdapter.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ------------------------------------------------------------------------------
1+
// ------------------------------------------------------------------------------
22
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
33
// ------------------------------------------------------------------------------
44

@@ -32,7 +32,7 @@ public interface IRequestAdapter
3232
/// <param name="errorMapping">The error factories mapping to use in case of a failed request.</param>
3333
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
3434
/// <returns>The deserialized response model.</returns>
35-
Task<ModelType> SendAsync<ModelType>(RequestInformation requestInfo, ParsableFactory<ModelType> factory, Dictionary<string, ParsableFactory<IParsable>> errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable;
35+
Task<ModelType?> SendAsync<ModelType>(RequestInformation requestInfo, ParsableFactory<ModelType> factory, Dictionary<string, ParsableFactory<IParsable>>? errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable;
3636
/// <summary>
3737
/// Executes the HTTP request specified by the given RequestInformation and returns the deserialized response model collection.
3838
/// </summary>
@@ -41,42 +41,42 @@ public interface IRequestAdapter
4141
/// <param name="errorMapping">The error factories mapping to use in case of a failed request.</param>
4242
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
4343
/// <returns>The deserialized response model collection.</returns>
44-
Task<IEnumerable<ModelType>> SendCollectionAsync<ModelType>(RequestInformation requestInfo, ParsableFactory<ModelType> factory, Dictionary<string, ParsableFactory<IParsable>> errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable;
44+
Task<IEnumerable<ModelType>?> SendCollectionAsync<ModelType>(RequestInformation requestInfo, ParsableFactory<ModelType> factory, Dictionary<string, ParsableFactory<IParsable>>? errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable;
4545
/// <summary>
4646
/// Executes the HTTP request specified by the given RequestInformation and returns the deserialized primitive response model.
4747
/// </summary>
4848
/// <param name="requestInfo">The RequestInformation object to use for the HTTP request.</param>
4949
/// <param name="errorMapping">The error factories mapping to use in case of a failed request.</param>
5050
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
5151
/// <returns>The deserialized primitive response model.</returns>
52-
Task<ModelType> SendPrimitiveAsync<ModelType>(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>> errorMapping = default, CancellationToken cancellationToken = default);
52+
Task<ModelType?> SendPrimitiveAsync<ModelType>(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>>? errorMapping = default, CancellationToken cancellationToken = default);
5353
/// <summary>
5454
/// Executes the HTTP request specified by the given RequestInformation and returns the deserialized primitive response model collection.
5555
/// </summary>
5656
/// <param name="requestInfo">The RequestInformation object to use for the HTTP request.</param>
5757
/// <param name="errorMapping">The error factories mapping to use in case of a failed request.</param>
5858
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
5959
/// <returns>The deserialized primitive response model collection.</returns>
60-
Task<IEnumerable<ModelType>> SendPrimitiveCollectionAsync<ModelType>(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>> errorMapping = default, CancellationToken cancellationToken = default);
60+
Task<IEnumerable<ModelType>?> SendPrimitiveCollectionAsync<ModelType>(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>>? errorMapping = default, CancellationToken cancellationToken = default);
6161
/// <summary>
6262
/// Executes the HTTP request specified by the given RequestInformation with no return content.
6363
/// </summary>
6464
/// <param name="requestInfo">The RequestInformation object to use for the HTTP request.</param>
6565
/// <param name="errorMapping">The error factories mapping to use in case of a failed request.</param>
6666
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
6767
/// <returns>A Task to await completion.</returns>
68-
Task SendNoContentAsync(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>> errorMapping = default, CancellationToken cancellationToken = default);
68+
Task SendNoContentAsync(RequestInformation requestInfo, Dictionary<string, ParsableFactory<IParsable>>? errorMapping = default, CancellationToken cancellationToken = default);
6969
/// <summary>
7070
/// The base url for every request.
7171
/// </summary>
72-
string BaseUrl { get; set; }
72+
string? BaseUrl { get; set; }
7373
/// <summary>
7474
/// Converts the given RequestInformation into a native HTTP request used by the implementing adapter.
7575
/// </summary>
7676
/// <typeparam name="T">The type of the native request.</typeparam>
7777
/// <param name="requestInfo">The RequestInformation object to use for the HTTP request.</param>
7878
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use for cancelling the requests.</param>
7979
/// <returns>The native HTTP request.</returns>
80-
Task<T> ConvertToNativeRequestAsync<T>(RequestInformation requestInfo, CancellationToken cancellationToken = default);
80+
Task<T?> ConvertToNativeRequestAsync<T>(RequestInformation requestInfo, CancellationToken cancellationToken = default);
8181
}
8282
}

src/IResponseHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public interface IResponseHandler
2222
/// <typeparam name="NativeResponseType">The type of the native response object.</typeparam>
2323
/// <typeparam name="ModelType">The type of the response model object.</typeparam>
2424
/// <returns>A task that represents the asynchronous operation and contains the deserialized response.</returns>
25-
Task<ModelType> HandleResponseAsync<NativeResponseType, ModelType>(NativeResponseType response, Dictionary<string, ParsableFactory<IParsable>> errorMappings);
25+
Task<ModelType?> HandleResponseAsync<NativeResponseType, ModelType>(NativeResponseType response, Dictionary<string, ParsableFactory<IParsable>>? errorMappings);
2626
}
2727
}

src/Microsoft.Kiota.Abstractions.csproj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@
66
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
77
<AssemblyTitle>Kiota Abstractions Library for dotnet</AssemblyTitle>
88
<Authors>Microsoft</Authors>
9-
<TargetFramework>netstandard2.0</TargetFramework>
9+
<TargetFrameworks>netstandard2.0;netstandard2.1;</TargetFrameworks>
1010
<LangVersion>latest</LangVersion>
1111
<PublishRepositoryUrl>true</PublishRepositoryUrl>
1212
<RepositoryUrl>https://github.com/microsoft/kiota-abstractions-dotnet</RepositoryUrl>
1313
<PackageProjectUrl>https://microsoft.github.io/kiota/</PackageProjectUrl>
1414
<EmbedUntrackedSources>true</EmbedUntrackedSources>
1515
<Deterministic>true</Deterministic>
1616
<VersionPrefix>1.0.0</VersionPrefix>
17-
<VersionSuffix>rc.3</VersionSuffix>
17+
<VersionSuffix>rc.4</VersionSuffix>
1818
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1919
<SignAssembly>false</SignAssembly>
2020
<DelaySign>false</DelaySign>
2121
<AssemblyOriginatorKeyFile>35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
2222
<GenerateDocumentationFile>true</GenerateDocumentationFile>
23+
<LangVersion>latest</LangVersion>
24+
<Nullable>enable</Nullable>
25+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
2326
<!-- Enable this line once we go live to prevent breaking changes -->
2427
<!-- <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion> -->
2528
<PackageReleaseNotes>

src/NativeResponseHandler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ public class NativeResponseHandler : IResponseHandler
1717
/// <summary>
1818
/// The value of the response
1919
/// </summary>
20-
public object Value;
20+
public object? Value;
2121

2222
/// <summary>
2323
/// The error mappings for the response to use when deserializing failed responses bodies. Where an error code like 401 applies specifically to that status code, a class code like 4XX applies to all status codes within the range if an the specific error code is not present.
2424
/// </summary>
25-
public Dictionary<string, ParsableFactory<IParsable>> ErrorMappings { get; set; }
25+
public Dictionary<string, ParsableFactory<IParsable>>? ErrorMappings { get; set; }
2626

2727
/// <inheritdoc />
28-
public Task<ModelType> HandleResponseAsync<NativeResponseType, ModelType>(NativeResponseType response, Dictionary<string, ParsableFactory<IParsable>> errorMappings)
28+
public Task<ModelType?> HandleResponseAsync<NativeResponseType, ModelType>(NativeResponseType response, Dictionary<string, ParsableFactory<IParsable>>? errorMappings)
2929
{
30-
Value = response;
30+
Value = response ?? throw new ArgumentNullException(nameof(response));
3131
ErrorMappings = errorMappings;
3232
return Task.FromResult(default(ModelType));
3333
}

src/NativeResponseWrapper.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ public class NativeResponseWrapper
2222
/// <param name="h">The request headers of the request</param>
2323
/// <param name="o">Request options</param>
2424
/// <returns></returns>
25-
public static async Task<NativeResponseType> CallAndGetNativeType<ModelType, NativeResponseType, QueryParametersType>(
26-
Func<Action<QueryParametersType>, Action<IDictionary<string, string>>, IEnumerable<IRequestOption>, IResponseHandler, Task<ModelType>> originalCall,
27-
Action<QueryParametersType> q = default,
28-
Action<IDictionary<string, string>> h = default,
29-
IEnumerable<IRequestOption> o = default) where NativeResponseType : class
25+
public static async Task<NativeResponseType?> CallAndGetNativeType<ModelType, NativeResponseType, QueryParametersType>(
26+
Func<Action<QueryParametersType>?, Action<IDictionary<string, string>>?, IEnumerable<IRequestOption>?, IResponseHandler, Task<ModelType>> originalCall,
27+
Action<QueryParametersType>? q = default,
28+
Action<IDictionary<string, string>>? h = default,
29+
IEnumerable<IRequestOption>? o = default) where NativeResponseType : class
3030
{
3131
var responseHandler = new NativeResponseHandler();
3232
await originalCall.Invoke(q, h, o, responseHandler);
@@ -42,12 +42,12 @@ public static async Task<NativeResponseType> CallAndGetNativeType<ModelType, Nat
4242
/// <param name="q">The query parameters of the request</param>
4343
/// <param name="h">The request headers of the request</param>
4444
/// <param name="o">Request options</param>
45-
public static async Task<NativeResponseType> CallAndGetNativeType<ModelType, NativeResponseType, QueryParametersType, RequestBodyType>(
46-
Func<RequestBodyType, Action<QueryParametersType>, Action<IDictionary<string, string>>, IEnumerable<IRequestOption>, IResponseHandler, Task<ModelType>> originalCall,
45+
public static async Task<NativeResponseType?> CallAndGetNativeType<ModelType, NativeResponseType, QueryParametersType, RequestBodyType>(
46+
Func<RequestBodyType, Action<QueryParametersType>?, Action<IDictionary<string, string>>?, IEnumerable<IRequestOption>?, IResponseHandler, Task<ModelType>> originalCall,
4747
RequestBodyType requestBody,
48-
Action<QueryParametersType> q = default,
49-
Action<IDictionary<string, string>> h = default,
50-
IEnumerable<IRequestOption> o = default) where NativeResponseType : class
48+
Action<QueryParametersType>? q = default,
49+
Action<IDictionary<string, string>>? h = default,
50+
IEnumerable<IRequestOption>? o = default) where NativeResponseType : class
5151
{
5252
var responseHandler = new NativeResponseHandler();
5353
await originalCall.Invoke(requestBody, q, h, o, responseHandler);

src/RequestHeaders.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void Add(string headerName, params string[] headerValues) {
3535
/// <inheritdoc/>
3636
public bool IsReadOnly => false;
3737
/// <inheritdoc/>
38-
public IEnumerable<string> this[string key] { get => TryGetValue(key, out var result) ? result : null; set => Add(key, value); }
38+
public IEnumerable<string> this[string key] { get => TryGetValue(key, out var result) ? result : throw new KeyNotFoundException($"Key not found : {key}"); set => Add(key, value); }
3939

4040
/// <summary>
4141
/// Removes the specified value from the header with the specified name.
@@ -75,7 +75,9 @@ public void Clear() {
7575
/// <inheritdoc/>
7676
public bool ContainsKey(string key) => !string.IsNullOrEmpty(key) && _headers.ContainsKey(key);
7777
/// <inheritdoc/>
78+
#pragma warning disable CS8604 // Possible null reference argument. //Can't change signature of overriden method implementation
7879
public void Add(string key, IEnumerable<string> value) => Add(key, value?.ToArray());
80+
#pragma warning restore CS8604 // Possible null reference argument.
7981
/// <inheritdoc/>
8082
public bool Remove(string key) {
8183
if(string.IsNullOrEmpty(key))

0 commit comments

Comments
 (0)