Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3bb2199
Remove redundant null checks
christiaanderidder Apr 11, 2026
1e269e1
Check for null on Enerator.Current
christiaanderidder Apr 11, 2026
fd53580
Remove redundant null checks
christiaanderidder Apr 11, 2026
6b2c01e
Remove unused using
christiaanderidder Apr 11, 2026
ddf68a7
Remove redundant null checks
christiaanderidder Apr 11, 2026
e3d6685
Response types should not be created by library users, make construct…
christiaanderidder Apr 11, 2026
b978d61
Remove NNTP response constructors from public API
christiaanderidder Apr 12, 2026
55c423b
Make NttpArticle constructor internal to prevent passing null values.…
christiaanderidder Apr 12, 2026
7b453f8
Make ValidationResult constructor internal to prevent passing null va…
christiaanderidder Apr 12, 2026
7ab4156
Make Nzb constructors internal to prevent passing null values. Librar…
christiaanderidder Apr 12, 2026
c260a47
Remove NNTP response constructors from public API
christiaanderidder Apr 12, 2026
9c5854e
Make NntpArticleRange constructor private. Library users can use the …
christiaanderidder Apr 12, 2026
3ecf71f
Make NntpGroup and NntpGroups constructors internal to prevent passin…
christiaanderidder Apr 12, 2026
1a36cf2
Remove NotNullAttribute without effect
christiaanderidder Apr 12, 2026
af22b8f
Disable duplicate entry warning for test testing duplicate entry hand…
christiaanderidder Apr 12, 2026
c088c3c
Disable access to disposed variable in closure, the task is always aw…
christiaanderidder Apr 12, 2026
1804e55
Make classes containing just constants static
christiaanderidder Apr 12, 2026
2a9e639
Make EnumerableStream abstract
christiaanderidder Apr 12, 2026
20eafc9
Disable unused tuple warning for test helper
christiaanderidder Apr 12, 2026
626df9d
Use pattern matching
christiaanderidder Apr 12, 2026
b202054
Use collection syntax
christiaanderidder Apr 12, 2026
11ed595
Make ValidationFailure constructor internal to prevent passing null v…
christiaanderidder Apr 12, 2026
31dcffd
Remove redundant null checks
christiaanderidder Apr 12, 2026
8ddd16c
Make ValidationFailure constructor internal to prevent passing null v…
christiaanderidder Apr 12, 2026
26d92c4
Use await using for async disposables
christiaanderidder Apr 12, 2026
dec7daf
Add JetBrains annotations package
christiaanderidder Apr 12, 2026
ffd02f6
Mark all classes part of the public API with PublicAPIAttribute
christiaanderidder Apr 12, 2026
c78b77f
Disable CA2007 in tests
christiaanderidder Apr 12, 2026
6978f0e
Fix tests after nullable changes
christiaanderidder Apr 12, 2026
7102fe9
Small syntax fixes
christiaanderidder Apr 12, 2026
cacbd16
Make Usenet.Util.Compatibility using optional
christiaanderidder Apr 12, 2026
c634eda
Use LINQ
christiaanderidder Apr 12, 2026
1a2f9dd
Use return instead of if
christiaanderidder Apr 12, 2026
6087b8c
Make null check optional
christiaanderidder Apr 12, 2026
1192132
Merge branch 'main' into fix-resharper-warnings
christiaanderidder May 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
root = true

[*.cs]
# CSharpier expects adds trailing comma, prevent editor from cleaning it up
trailing_comma_in_multiline_lists = true

[tests/**/*.cs]
dotnet_diagnostic.CA2007.severity = none
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="GitHubActionsTestLogger" Version="3.0.4" />
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.Bcl.Memory" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Abstractions" Version="10.0.7" />
Expand All @@ -17,6 +18,7 @@
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="System.Collections.Immutable" Version="10.0.7" />
<PackageVersion Include="System.Linq.Async" Version="7.0.1" />
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
<PackageVersion Include="TUnit" Version="1.43.41" />
</ItemGroup>
</Project>
5 changes: 4 additions & 1 deletion src/Usenet/Exceptions/InvalidNzbDataException.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace Usenet.Exceptions;
using JetBrains.Annotations;

namespace Usenet.Exceptions;

/// <inheritdoc />
/// <summary>The exception that is thrown when a data stream or text is not in a valid nzb format.</summary>
[PublicAPI]
public class InvalidNzbDataException : Exception
{
/// <inheritdoc />
Expand Down
5 changes: 4 additions & 1 deletion src/Usenet/Exceptions/InvalidYencDataException.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace Usenet.Exceptions;
using JetBrains.Annotations;

namespace Usenet.Exceptions;

/// <inheritdoc />
/// <summary>The exception that is thrown when a data stream or text is not in a valid yEnc format.</summary>
[PublicAPI]
public class InvalidYencDataException : Exception
{
/// <inheritdoc />
Expand Down
5 changes: 4 additions & 1 deletion src/Usenet/Exceptions/NntpException.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace Usenet.Exceptions;
using JetBrains.Annotations;

namespace Usenet.Exceptions;

/// <inheritdoc />
/// <summary>The exception that is thrown when communicating using the Network News Transfer Protocol.</summary>
[PublicAPI]
public class NntpException : Exception
{
/// <inheritdoc />
Expand Down
4 changes: 3 additions & 1 deletion src/Usenet/Logger.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace Usenet;
Expand All @@ -7,6 +8,7 @@ namespace Usenet;
/// Host for a singleton <see cref="ILoggerFactory"/>
/// (<a href="https://stackify.com/net-core-loggerfactory-use-correctly/">Source</a>).
/// </summary>
[PublicAPI]
public static class Logger
{
/// <summary>
Expand Down
18 changes: 10 additions & 8 deletions src/Usenet/Nntp/Builders/NntpArticleBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Usenet.Exceptions;
using Usenet.Extensions;
Expand All @@ -10,6 +11,7 @@ namespace Usenet.Nntp.Builders;
/// <summary>
/// Represents a mutable <see cref="NntpArticle"/>.
/// </summary>
[PublicAPI]
public class NntpArticleBuilder
{
private readonly ILogger _log = Logger.Create<NntpArticleBuilder>();
Expand Down Expand Up @@ -48,7 +50,7 @@ public NntpArticleBuilder InitializeFrom(NntpArticle article)
{
Guard.ThrowIfNull(article);

_messageId = new(article.MessageId.Value);
_messageId = new NntpMessageId(article.MessageId.Value);
_groupsBuilder = new NntpGroupsBuilder().Add(article.Groups);
_headers = [];
_from = string.Empty;
Expand Down Expand Up @@ -326,13 +328,13 @@ public NntpArticle Build()
_headers.Add(NntpHeaders.From, _from);
_headers.Add(NntpHeaders.Subject, _subject);

if (_dateTime.HasValue)
{
var formattedDate = _dateTime
.Value.ToUniversalTime()
.ToString(DateFormat, CultureInfo.InvariantCulture);
_headers.Add(NntpHeaders.Date, $"{formattedDate} +0000");
}
if (!_dateTime.HasValue)
return new NntpArticle(0, _messageId, groups, _headers, _body);

var formattedDate = _dateTime
.Value.ToUniversalTime()
.ToString(DateFormat, CultureInfo.InvariantCulture);
_headers.Add(NntpHeaders.Date, $"{formattedDate} +0000");

return new NntpArticle(0, _messageId, groups, _headers, _body);
}
Expand Down
14 changes: 3 additions & 11 deletions src/Usenet/Nntp/Builders/NntpGroupsBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Usenet.Nntp.Models;
using JetBrains.Annotations;
using Usenet.Nntp.Models;
using Usenet.Nntp.Parsers;
using Usenet.Util;

Expand All @@ -7,6 +8,7 @@ namespace Usenet.Nntp.Builders;
/// <summary>
/// Represents a mutable <see cref="NntpGroups"/>.
/// </summary>
[PublicAPI]
public class NntpGroupsBuilder
{
private readonly List<string> _groups = [];
Expand Down Expand Up @@ -82,11 +84,6 @@ public NntpGroupsBuilder Remove(IEnumerable<string> values)

private void AddGroups(IEnumerable<string> values)
{
if (values == null)
{
return;
}

foreach (var group in values)
{
if (!_groups.Contains(group))
Expand All @@ -98,11 +95,6 @@ private void AddGroups(IEnumerable<string> values)

private void RemoveGroups(IEnumerable<string> values)
{
if (values == null)
{
return;
}

foreach (var group in values)
{
_groups.RemoveAll(g => g == group);
Expand Down
3 changes: 3 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using JetBrains.Annotations;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClient
: INntpClientRfc2980,
INntpClientRfc3977,
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientCompression.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using JetBrains.Annotations;
using Usenet.Nntp.Models;
using Usenet.Nntp.Responses;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClientCompression
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientConnection.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using JetBrains.Annotations;
using Usenet.Nntp.Responses;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClientConnection
{
/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientPool.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using JetBrains.Annotations;

namespace Usenet.Nntp.Contracts;

/// <summary>
/// Represents a pool of authenticated NNTP clients.
/// </summary>
[PublicAPI]
public interface INntpClientPool : IDisposable
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientRfc2980.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using JetBrains.Annotations;
using Usenet.Nntp.Models;
using Usenet.Nntp.Responses;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClientRfc2980
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientRfc3977.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Usenet.Nntp.Models;
using Usenet.Nntp.Responses;

namespace Usenet.Nntp.Contracts;

[SuppressMessage("Naming", "CA1716:Identifiers should not match keywords")]
[PublicAPI]
public interface INntpClientRfc3977
{
/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientRfc4643.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using JetBrains.Annotations;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClientRfc4643
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpClientRfc6048.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using JetBrains.Annotations;
using Usenet.Nntp.Responses;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface INntpClientRfc6048
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Contracts/INntpConnection.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using JetBrains.Annotations;
using Usenet.Nntp.Parsers;
using Usenet.Util;

Expand All @@ -7,6 +8,7 @@ namespace Usenet.Nntp.Contracts;
/// Represents an NNTP connection.
/// Based on Kristian Hellang's NntpLib.Net project https://github.com/khellang/NntpLib.Net.
/// </summary>
[PublicAPI]
public interface INntpConnection : IDisposable
{
/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Usenet/Nntp/Contracts/IPooledNntpClient.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using JetBrains.Annotations;

namespace Usenet.Nntp.Contracts;

/// <summary>
/// An NNTP client for which connections and authentication are managed by a pool.
/// </summary>
[PublicAPI]
public interface IPooledNntpClient
: INntpClientRfc2980,
INntpClientRfc3977,
Expand Down
3 changes: 3 additions & 0 deletions src/Usenet/Nntp/Contracts/IPooledNntpClientLease.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using JetBrains.Annotations;

namespace Usenet.Nntp.Contracts;

[PublicAPI]
public interface IPooledNntpClientLease : IDisposable
{
public IPooledNntpClient Client { get; }
Expand Down
22 changes: 11 additions & 11 deletions src/Usenet/Nntp/Models/NntpArticle.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Immutable;
using JetBrains.Annotations;
using Usenet.Util;
using HashCode = Usenet.Util.HashCode;

Expand All @@ -7,6 +8,7 @@ namespace Usenet.Nntp.Models;
/// <summary>
/// Represents an NNTP article.
/// </summary>
[PublicAPI]
public class NntpArticle : IEquatable<NntpArticle>
{
/// <summary>
Expand Down Expand Up @@ -42,25 +44,23 @@ public class NntpArticle : IEquatable<NntpArticle>
/// <param name="groups">The NNTP newsgroups this <see cref="NntpArticle"/> is posted in.</param>
/// <param name="headers">The headers of the <see cref="NntpArticle"/>.</param>
/// <param name="body">The body of the <see cref="NntpArticle"/>.</param>
public NntpArticle(
internal NntpArticle(
long number,
NntpMessageId? messageId,
NntpGroups? groups,
IDictionary<string, ICollection<string>>? headers,
IList<string>? body
NntpMessageId messageId,
NntpGroups groups,
IDictionary<string, ICollection<string>> headers,
IList<string> body
)
Comment on lines +47 to 53
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor changed from public to internal, which is a breaking change for consumers who previously instantiated NntpArticle directly (and is reflected by the removals in PublicAPI.Shipped.txt). If this PR is meant to only fix warnings, consider keeping the ctor public or introducing a public factory/builder API that fully replaces direct construction.

Copilot uses AI. Check for mistakes.
{
Number = number;
MessageId = messageId ?? NntpMessageId.Empty;
Groups = groups ?? NntpGroups.Empty;
Headers = (
headers ?? MultiValueDictionary<string, string>.EmptyIgnoreCase
).ToImmutableDictionary(
MessageId = messageId;
Groups = groups;
Headers = headers.ToImmutableDictionary(
x => x.Key,
x => x.Value.ToImmutableList(),
keyComparer: StringComparer.OrdinalIgnoreCase
);
Body = (body ?? []).ToImmutableList();
Body = body.ToImmutableList();
}

/// <summary>
Expand Down
18 changes: 8 additions & 10 deletions src/Usenet/Nntp/Models/NntpArticleRange.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using JetBrains.Annotations;
using Usenet.Util;
using HashCode = Usenet.Util.HashCode;

Expand All @@ -12,6 +13,7 @@ namespace Usenet.Nntp.Models;
/// <a href="https://tools.ietf.org/html/rfc2980#section-2.9">XPAT</a> and
/// <a href="https://tools.ietf.org/html/rfc2980#section-2.11">XROVER</a> commands.
/// </summary>
[PublicAPI]
public class NntpArticleRange : IEquatable<NntpArticleRange>
{
/// <summary>
Expand All @@ -29,7 +31,7 @@ public class NntpArticleRange : IEquatable<NntpArticleRange>
/// </summary>
/// <param name="from">The article number to start the range from.</param>
/// <param name="to">The optional article number to end the range with.</param>
public NntpArticleRange(long from, long? to)
private NntpArticleRange(long from, long? to)
{
From = from;
To = to;
Expand All @@ -47,28 +49,24 @@ public NntpArticleRange(long from, long? to)
/// </summary>
/// <param name="from">The article number to start the range from.</param>
/// <returns>A new range containing the given article and all following.</returns>
public static NntpArticleRange AllFollowing(long from) => new(@from, null);
public static NntpArticleRange AllFollowing(long from) => new(from, null);

/// <summary>
/// Creates a range containing all articles between and including <paramref name="from"/> and <paramref name="to"/>.
/// </summary>
/// <param name="from">The article number to start the range from.</param>
/// <param name="to">The article number to end the range with.</param>
/// <returns>A new range containg all articles between and including <paramref name="from"/> and <paramref name="to"/>.</returns>
public static NntpArticleRange Range(long from, long to) => new(@from, to);
public static NntpArticleRange Range(long from, long to) => new(from, to);

/// <summary>
/// Returns the text representation of the value formatted according to the NNTP specifications.
/// </summary>
/// <returns>The text representation of the value formatted according to the NNTP specifications</returns>
public override string ToString() =>
To == null
? $"{From}-"
: (
To.Value == From
? From.ToString(CultureInfo.InvariantCulture)
: $"{From}-{To.Value}"
);
To == null ? $"{From}-"
: To.Value == From ? From.ToString(CultureInfo.InvariantCulture)
: $"{From}-{To.Value}";

/// <summary>
/// Returns the hash code for this instance.
Expand Down
2 changes: 2 additions & 0 deletions src/Usenet/Nntp/Models/NntpDateTime.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using JetBrains.Annotations;
using Usenet.Util;

namespace Usenet.Nntp.Models;

/// <summary>
/// Represents an NNTP datetime object.
/// </summary>
[PublicAPI]
public class NntpDateTime : IEquatable<NntpDateTime>
{
/// <summary>
Expand Down
Loading
Loading