Skip to content

Commit 33b9582

Browse files
authored
Address some static analysis and TODOs (#12)
1 parent 3de19d3 commit 33b9582

24 files changed

+132
-123
lines changed

src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using ModelContextProtocol.Utils;
2+
13
namespace System.Collections.Generic;
24

35
internal static class CollectionExtensions
@@ -9,10 +11,7 @@ internal static class CollectionExtensions
911

1012
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
1113
{
12-
if (dictionary is null)
13-
{
14-
throw new ArgumentNullException(nameof(dictionary));
15-
}
14+
Throw.IfNull(dictionary);
1615

1716
return dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
1817
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using ModelContextProtocol.Utils;
2+
using System.Buffers;
3+
using System.Runtime.InteropServices;
4+
5+
namespace System.IO;
6+
7+
internal static class StreamExtensions
8+
{
9+
public static ValueTask WriteAsync(this Stream stream, ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
10+
{
11+
Throw.IfNull(stream);
12+
13+
if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> segment))
14+
{
15+
return new ValueTask(stream.WriteAsync(segment.Array, segment.Offset, segment.Count, cancellationToken));
16+
}
17+
else
18+
{
19+
return WriteAsyncCore(stream, buffer, cancellationToken);
20+
21+
static async ValueTask WriteAsyncCore(Stream stream, ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
22+
{
23+
byte[] array = ArrayPool<byte>.Shared.Rent(buffer.Length);
24+
try
25+
{
26+
buffer.Span.CopyTo(array);
27+
await stream.WriteAsync(array, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
28+
}
29+
finally
30+
{
31+
ArrayPool<byte>.Shared.Return(array);
32+
}
33+
}
34+
}
35+
}
36+
}

src/Common/Polyfills/System/IO/TextReaderExtensions.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,21 @@ internal static class TextReaderExtensions
44
{
55
public static Task<string> ReadLineAsync(this TextReader reader, CancellationToken cancellationToken)
66
{
7-
_ = cancellationToken;
7+
if (cancellationToken.IsCancellationRequested)
8+
{
9+
return Task.FromCanceled<string>(cancellationToken);
10+
}
11+
812
return reader.ReadLineAsync();
913
}
14+
15+
public static Task<string> ReadToEndAsync(this TextReader reader, CancellationToken cancellationToken)
16+
{
17+
if (cancellationToken.IsCancellationRequested)
18+
{
19+
return Task.FromCanceled<string>(cancellationToken);
20+
}
21+
22+
return reader.ReadToEndAsync();
23+
}
1024
}

src/Common/Polyfills/System/IO/TextWriterExtensions.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using ModelContextProtocol.Utils;
12
using System.Runtime.InteropServices;
23

34
namespace System.IO;
@@ -6,10 +7,7 @@ internal static class TextWriterExtensions
67
{
78
public static async Task WriteLineAsync(this TextWriter writer, ReadOnlyMemory<char> value, CancellationToken cancellationToken)
89
{
9-
if (writer is null)
10-
{
11-
throw new ArgumentNullException(nameof(writer));
12-
}
10+
Throw.IfNull(writer);
1311

1412
if (value.IsEmpty)
1513
{

src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1+
using ModelContextProtocol.Utils;
2+
13
namespace System.Net.Http;
24

35
internal static class HttpClientExtensions
46
{
57
public static async Task<Stream> ReadAsStreamAsync(this HttpContent content, CancellationToken cancellationToken)
68
{
7-
if (content is null)
8-
{
9-
throw new ArgumentNullException(nameof(content));
10-
}
9+
Throw.IfNull(content);
1110

1211
cancellationToken.ThrowIfCancellationRequested();
1312
return await content.ReadAsStreamAsync();
1413
}
1514

1615
public static async Task<string> ReadAsStringAsync(this HttpContent content, CancellationToken cancellationToken)
1716
{
18-
if (content is null)
19-
{
20-
throw new ArgumentNullException(nameof(content));
21-
}
17+
Throw.IfNull(content);
2218

2319
cancellationToken.ThrowIfCancellationRequested();
2420
return await content.ReadAsStringAsync();

src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
using ModelContextProtocol.Utils;
2+
13
namespace System.Threading.Tasks;
24

35
internal static class CancellationTokenSourceExtensions
46
{
57
public static Task CancelAsync(this CancellationTokenSource cancellationTokenSource)
68
{
7-
if (cancellationTokenSource is null)
8-
{
9-
throw new ArgumentNullException(nameof(cancellationTokenSource));
10-
}
9+
Throw.IfNull(cancellationTokenSource);
1110

1211
cancellationTokenSource.Cancel();
1312
return Task.CompletedTask;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace System.Threading;
4+
5+
/// <summary>
6+
/// await default(ForceYielding) to provide the same behavior as
7+
/// await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding).
8+
/// </summary>
9+
internal readonly struct ForceYielding : INotifyCompletion, ICriticalNotifyCompletion
10+
{
11+
public ForceYielding GetAwaiter() => this;
12+
13+
public bool IsCompleted => false;
14+
public void OnCompleted(Action continuation) => ThreadPool.QueueUserWorkItem(a => ((Action)a!)(), continuation);
15+
public void UnsafeOnCompleted(Action continuation) => ThreadPool.UnsafeQueueUserWorkItem(a => ((Action)a!)(), continuation);
16+
public void GetResult() { }
17+
}

src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using ModelContextProtocol.Utils;
2+
13
namespace System.Threading.Tasks;
24

35
internal static class TaskExtensions
@@ -15,10 +17,7 @@ public static async Task<T> WaitAsync<T>(this Task<T> task, CancellationToken ca
1517

1618
public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken)
1719
{
18-
if (task is null)
19-
{
20-
throw new ArgumentNullException(nameof(task));
21-
}
20+
Throw.IfNull(task);
2221

2322
if (timeout < TimeSpan.Zero && timeout != Timeout.InfiniteTimeSpan)
2423
{

src/ModelContextProtocol/Client/McpClientExtensions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
using System.Runtime.CompilerServices;
77
using System.Text.Json;
88

9-
#pragma warning disable CA1508 // Avoid dead conditional code
10-
119
namespace ModelContextProtocol.Client;
1210

1311
/// <summary>
@@ -439,7 +437,7 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat
439437
}
440438

441439
private static JsonRpcRequest CreateRequest(string method, Dictionary<string, object?>? parameters) =>
442-
new JsonRpcRequest
440+
new()
443441
{
444442
Method = method,
445443
Params = parameters

src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.Transports.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ public static IMcpServerBuilder WithStdioServerTransport(this IMcpServerBuilder
3030
/// <param name="builder">The builder instance.</param>
3131
public static IMcpServerBuilder WithHttpListenerSseServerTransport(this IMcpServerBuilder builder)
3232
{
33-
if (builder is null)
34-
{
35-
throw new ArgumentNullException(nameof(builder));
36-
}
33+
Throw.IfNull(builder);
3734

3835
builder.Services.AddSingleton<IServerTransport, HttpListenerSseServerTransport>();
3936
builder.Services.AddHostedService<McpServerHostedService>();

0 commit comments

Comments
 (0)