Skip to content

Conversation

@HowardvanRooijen
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings January 26, 2026 09:24
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Upgrades the build and project configuration to target .NET 10 and updates the repo’s solution/build setup accordingly.

Changes:

  • Switches the repo from a .sln to a new XML-based .slnx solution file and updates build.ps1 to use it.
  • Updates all projects to target net10.0 and enables nullable + implicit usings with C# language version pinned.
  • Updates CI to build with the .NET 10 SDK and refreshes test package dependencies; adds an additional .gitignore entry.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
build.ps1 Points the build pipeline at the new Solutions/Argotic.slnx solution file.
Solutions/Argotic.slnx New solution definition listing the projects to build.
Solutions/Argotic.sln Removes the old Visual Studio .sln solution file.
Solutions/Argotic.Common/Argotic.Common.csproj Moves the library to net10.0 and enables nullable/implicit usings (breaking change vs prior multi-targeting).
Solutions/Argotic.Core/Argotic.Core.csproj Moves to net10.0, enables nullable/implicit usings, and bumps a dependency version.
Solutions/Argotic.Extensions/Argotic.Extensions.csproj Moves to net10.0 and enables nullable/implicit usings (breaking change vs prior multi-targeting).
Solutions/Argotic.Examples/Argotic.Examples.csproj Moves to net10.0 and enables nullable/implicit usings (breaking change vs prior multi-targeting).
Solutions/Argotic.Extensions.Tests/Argotic.Extensions.Tests.csproj Moves tests to net10.0 and updates test-related package versions.
.gitignore Adds .endjin/ to ignored paths.
.github/workflows/build.yml Updates CI to install/use .NET SDK 10.x only.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;</TargetFrameworks>
<TargetFramework>net10.0</TargetFramework>
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Changing from multi-targeting (TargetFrameworks) to a single TargetFramework (net10.0) drops support for netstandard2.0/2.1 and net8/net9 consumers. If Argotic.Core is intended to remain broadly consumable, consider multi-targeting and adding net10.0 instead (or explicitly treat this as a breaking change with appropriate versioning/docs).

Suggested change
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>

Copilot uses AI. Check for mistakes.

<PropertyGroup>
<TargetFrameworks>netstandard2.1;netstandard2.0;net8.0;net9.0;</TargetFrameworks>
<TargetFramework>net10.0</TargetFramework>
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Switching from TargetFrameworks to a single net10.0 TargetFramework removes previously supported TFMs (netstandard2.x, net8, net9). If Argotic.Extensions is distributed as a library package, consider keeping multi-targeting and adding net10.0, or make the breaking-change intent explicit (including package versioning).

Suggested change
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>

Copilot uses AI. Check for mistakes.

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;</TargetFrameworks>
<TargetFramework>net10.0</TargetFramework>
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Switching Argotic.Examples from TargetFrameworks to a single net10.0 TargetFramework drops prior TFMs (netstandard2.x/net8/net9). If this project needs to remain buildable/runable on older frameworks or be referenced by them, consider restoring multi-targeting and adding net10.0.

Suggested change
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>

Copilot uses AI. Check for mistakes.

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;</TargetFrameworks>
<TargetFramework>net10.0</TargetFramework>
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Changing from multi-targeting (TargetFrameworks) to a single TargetFramework (net10.0) drops support for netstandard2.0/2.1 and net8/net9 consumers. If these projects are published as reusable libraries, consider keeping TargetFrameworks and adding net10.0 (or otherwise document this breaking change and ensure versioning reflects it).

Suggested change
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks>

Copilot uses AI. Check for mistakes.
Get-EndjinGist zf prautoflow
Get-EndjinGist zf dotnet
@github-actions
Copy link

github-actions bot commented Jan 26, 2026

Test Results

3 697 tests  +3 583   3 697 ✅ +3 603   7s ⏱️ +7s
    1 suites ±    0       0 💤  -    20 
    1 files   ±    0       0 ❌ ±    0 

Results for commit d3382d1. ± Comparison against base commit 37fc3cf.

This pull request removes 114 and adds 3697 tests. Note that renamed tests count towards both.
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControlSyndicationExtensionConstructorTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_CompareToTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_ContextTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_CreateXmlTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_EqualsTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_FullTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_GetHashCodeTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_LoadTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_MatchByTypeTest
Argotic.Extensions.Tests.AtomPublishingControlSyndicationExtensionTest ‑ AtomPublishingControl_ToStringTest
…
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenBothEmpty_ReturnsZero
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenBothListsEqual_ReturnsZero
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenDifferentValues_ReturnsNonZero
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenSourceLarger_ReturnsOne
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenSourceNull_ThrowsArgumentNullException
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenSourceSmaller_ReturnsNegativeOne
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_DayOfWeek_WhenTargetNull_ThrowsArgumentNullException
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_Dictionary_CaseInsensitive_WhenSameIgnoringCase_ReturnsZero
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_Dictionary_WhenBothEqual_ReturnsZero
Argotic.Extensions.Tests.Functionality.Common.ComparisonUtilityTests ‑ CompareSequence_Dictionary_WhenDifferentValues_ReturnsNonZero
…

♻️ This comment has been updated with latest results.

HowardvanRooijen and others added 22 commits January 26, 2026 10:43
…cross multiple classes for consistency and adherence to C# coding conventions. Updated comparison methods to use lowercase 'string' as well.
…bility in SyndicationDateTimeUtility and BasicGeocodingSyndicationExtension
Migrate from the custom Guard class to modern .NET 10 built-in exception
helpers, which use CallerArgumentExpression to automatically capture
parameter names without manual string arguments.

Replacements:
- Guard.ArgumentNotNull -> ArgumentNullException.ThrowIfNull (1,322 calls)
- Guard.ArgumentNotNullOrEmptyString -> ArgumentException.ThrowIfNullOrEmpty (140 calls)
- Guard.ArgumentNotGreaterThan -> ArgumentOutOfRangeException.ThrowIfGreaterThan (7 calls)
- Guard.ArgumentNotLessThan -> ArgumentOutOfRangeException.ThrowIfLessThan (13 calls)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…eractively or non-interactively a) to show how to use the APIs b) to prove that the APIs work.
  - Fix RFC 822 date parsing for numeric timezone offsets (+00:00, -05:00)
    in SyndicationDateTimeUtility.ReplaceRfc822TimeZoneWithOffset
  - Fix XPath expression bug in TrackbackDiscoveryMetadata.Load (\\r -> /)

  New test coverage for:
  - Legacy RSS adapters (0.90, 0.91, 0.92, 1.0)
  - Legacy Atom 0.3 and RSD 0.6 adapters
  - BlogML attachment and trackback types
  - XML-RPC array and structure member types
  - Discovery types (TrackbackDiscoveryMetadata, DiscoverableSyndicationEndpoint)
  - MimeMediaTypeAttribute
  - Configuration/DI (ServiceCollectionExtensions, ClientOptions)
  - Async utility methods (SyndicationDiscoveryUtility)

  Coverage improved from 56.2% to 66.1% line coverage (+10%)
  Implement complete support for the Sitemap 0.9 specification, enabling
  web content syndication for search engine crawlers.

  Core Classes:
  - Sitemap: Main class implementing ISyndicationResource with async/sync
    loading from Uri, Stream, XmlReader, and IXPathNavigable
  - SitemapUrl: Individual URL entry with Location, LastModified,
    ChangeFrequency, and Priority (0.0-1.0) properties
  - SitemapIndex: Container for multiple sitemaps (up to 50,000 entries)
  - SitemapIndexEntry: Individual sitemap reference with Location and
    LastModified
  - SitemapChangeFrequency: Enum (Always, Hourly, Daily, Weekly, Monthly,
    Yearly, Never)
  - SitemapUtility: Helper methods for parsing and serialization

  Extensions (Google Sitemap extensions):
  - SitemapImageExtension: Image metadata (caption, geo-location, license)
  - SitemapVideoExtension: Video metadata (duration, rating, view count,
    platform targeting, player location)
  - SitemapNewsExtension: News article metadata (publication, dates)
  - SitemapHreflangExtension: Alternate language versions for i18n SEO

  Infrastructure:
  - Sitemap09SyndicationResourceAdapter for XML parsing
  - Full extension support via IExtensibleSyndicationObject

  Testing:
  - Comprehensive test suite (~3,300 LOC) covering parsing, serialization,
    utility methods, and all extensions

  Examples:
  - SitemapExample: Creating and loading sitemaps
  - SitemapIndexExample: Managing sitemap indexes
  - Sample XML files for sitemap and sitemap index
  Implement complete video:id and content_segment_loc element support per
  the Google Video Sitemap 1.1 XSD specification, along with examples and
  tests for all sitemap extensions.

  New classes:
  - SitemapVideoIdType enum for video identifier types
  - SitemapVideoId class for video:id element support
  - SitemapVideoSegment class for content_segment_loc support

  SitemapVideo enhancements:
  - Add MaxTitleLength (100 chars) constant with truncation
  - Add Identifiers and ContentSegments collections
  - Add deprecation notice for elements removed by Google in May 2022

  Documentation:
  - Add XSD schema references to SitemapVideo, SitemapVideoExtension,
    SitemapImage, SitemapImageExtension, SitemapNewsExtension,
    and SitemapNewsPublication classes

  Examples:
  - Add SitemapVideoExtensionExample with 8 usage examples
  - Add SitemapImageExtensionExample with 6 usage examples
  - Add SitemapNewsExtensionExample with 7 usage examples
  - Add sample XML files: sitemap_video.xml, sitemap_image.xml,
    sitemap_news.xml
  - Update SampleDataPath and ExampleOutput helpers

  Tests:
  - Add SitemapVideoTests with 58 comprehensive unit tests
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 75 out of 428 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/// A <see cref="IList{T}"/> collection of <see cref="XmlRpcStructureMember"/> objects that represent this structure's members.
/// The default value is an <i>empty</i> collection.
/// </value>
public IList<XmlRpcStructureMember> Members { get; } = [];
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Initializing an IList<T> with [] is risky because it may produce a T[] at runtime (arrays implement IList<T> but are fixed-size). This class later calls Members.Add(...), which would throw NotSupportedException if Members is backed by an array. Prefer initializing with a growable list (e.g., new List<XmlRpcStructureMember>() or keep Collection<XmlRpcStructureMember>).

Suggested change
public IList<XmlRpcStructureMember> Members { get; } = [];
public IList<XmlRpcStructureMember> Members { get; } = new List<XmlRpcStructureMember>();

Copilot uses AI. Check for mistakes.
/// A <see cref="IList{T}"/> collection of <see cref="IXmlRpcValue"/> objects that represent the data elements for this array.
/// The default value is an <i>empty</i> collection.
/// </value>
public IList<IXmlRpcValue> Values { get; } = [];
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Same issue as above: [] assigned to IList<IXmlRpcValue> may produce an array-backed list. Since this type calls Values.Add(...), it can throw NotSupportedException at runtime. Initialize with a mutable collection (e.g., new List<IXmlRpcValue>()).

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +11
public string HRef { get; set; }

public Dictionary<string, string> Attributes { get; set; }
public Dictionary<string, string> Attributes { get; } = [];

public string Title { get; set; }
}
public string Title { get; set; }
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

With <Nullable>enable</Nullable>, HRef and Title are non-nullable but not initialized, which will generate nullable warnings (and may become errors depending on repo settings). Consider initializing them (e.g., = string.Empty;) or making them nullable (string?) if they are optional.

Copilot uses AI. Check for mistakes.
/// This indexer uses a <i>case-insensitive</i> comparison of the specified member <paramref name="name"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">The <paramref name="name"/> is a null reference.</exception>
/// <exception cref="ArgumentNullException">The <paramref name="name"/> is an empty string.</exception>
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

ArgumentException.ThrowIfNullOrEmpty(name) throws ArgumentNullException for null and ArgumentException for empty. The XML docs currently claim an ArgumentNullException for empty strings, which is no longer accurate. Update the <exception> documentation (or change the guard to match the documented exception types).

Suggested change
/// <exception cref="ArgumentNullException">The <paramref name="name"/> is an empty string.</exception>
/// <exception cref="ArgumentException">The <paramref name="name"/> is an empty string.</exception>

Copilot uses AI. Check for mistakes.
get
{
Guard.ArgumentNotNullOrEmptyString(name, "name");
ArgumentException.ThrowIfNullOrEmpty(name);
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

ArgumentException.ThrowIfNullOrEmpty(name) throws ArgumentNullException for null and ArgumentException for empty. The XML docs currently claim an ArgumentNullException for empty strings, which is no longer accurate. Update the <exception> documentation (or change the guard to match the documented exception types).

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +21
directories:
- "/"
- "actions/**/*"
schedule:
interval: "daily"
open-pull-requests-limit: 10
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Dependabot config uses directory (singular), not directories. To monitor multiple directories you generally need multiple update entries (one per directory). As written, this block is likely invalid and may cause Dependabot to ignore the configuration.

Suggested change
directories:
- "/"
- "actions/**/*"
schedule:
interval: "daily"
open-pull-requests-limit: 10
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/actions"
schedule:
interval: "daily"
open-pull-requests-limit: 10

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 28
<ItemGroup>
<Compile Remove="Configuration\Provider\XmlSyndicationResourceProvider.cs" />
<Compile Remove="Configuration\Provider\SyndicationResourceProvider.cs" />
<Compile Remove="Configuration\Provider\SyndicationResourceProviderCollection.cs" />
<Compile Remove="Syndication\SyndicationManager.cs" />
</ItemGroup>

Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

This project now explicitly excludes several provider types from compilation, but those files are still present (and updated in this PR). If the provider model is being removed, consider deleting the excluded source files (or moving them to a separate package/TFM) to avoid confusion and prevent other code from accidentally referencing non-compiled types.

Suggested change
<ItemGroup>
<Compile Remove="Configuration\Provider\XmlSyndicationResourceProvider.cs" />
<Compile Remove="Configuration\Provider\SyndicationResourceProvider.cs" />
<Compile Remove="Configuration\Provider\SyndicationResourceProviderCollection.cs" />
<Compile Remove="Syndication\SyndicationManager.cs" />
</ItemGroup>

Copilot uses AI. Check for mistakes.
Comment on lines +182 to +185
public Task<XPathNavigator> CreateNavigatorAsync(CancellationToken cancellationToken = default)
{
return CreateNavigatorAsync(SyndicationEncodingUtility.SharedHttpClient, cancellationToken);
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

It looks like the previous synchronous CreateNavigator() API was replaced with CreateNavigatorAsync(...). If this is a public API, that’s a breaking change for consumers. Consider keeping a synchronous overload for compatibility (possibly implemented as a thin wrapper over the async path) or providing a clear migration path in the API surface.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +35
internal ConditionalGetResult(HttpResponseMessage? response, bool wasModified)
{
this.response = response;
WasModified = wasModified;

if (response != null)
{
StatusCode = response.StatusCode;
LastModified = response.Content.Headers.LastModified;
ETag = response.Headers.ETag?.Tag;
ContentLength = response.Content.Headers.ContentLength ?? -1;
ContentType = response.Content.Headers.ContentType?.MediaType;
}
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

When response is null, StatusCode remains the default value (0), which is not a valid HttpStatusCode and may confuse callers. Consider either making StatusCode nullable, or explicitly setting it to HttpStatusCode.NotModified (or another meaningful value) when WasModified == false and response is null.

Copilot uses AI. Check for mistakes.
/// <exception cref="ArgumentNullException">The <paramref name="source"/> is a null reference (Nothing in Visual Basic).</exception>
bool Load(XPathNavigator source);
/// <param name="source">The <see cref="XPathNavigator"/> to extract information from.</param>
/// <returns><b>true</b> if the <see cref="IXmlRpcValue"/> was initialized using the supplied <paramref name="source"/>, Otherwise, <b>false</b>.</returns>
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

In this sentence, 'Otherwise' should be lowercase ('otherwise') for correct grammar.

Suggested change
/// <returns><b>true</b> if the <see cref="IXmlRpcValue"/> was initialized using the supplied <paramref name="source"/>, Otherwise, <b>false</b>.</returns>
/// <returns><b>true</b> if the <see cref="IXmlRpcValue"/> was initialized using the supplied <paramref name="source"/>, otherwise, <b>false</b>.</returns>

Copilot uses AI. Check for mistakes.
HowardvanRooijen and others added 22 commits January 28, 2026 14:21
  BREAKING CHANGE: Remove non-generic CompareTo(object?) method

  This is a breaking change that modernizes the comparison interface
  implementation by replacing the legacy IComparable interface with
  the strongly-typed IComparable<T> generic interface.

  Changes:
  - Update 8 types in Argotic.Common
  - Update 54 types in Argotic.Core (Atom, RSS, OPML, Sitemap,
    Publishing, APML, BlogML, RSD, Net, Generic)
  - Update 57 types in Argotic.Extensions (Sitemap, YahooMedia,
    FeedSync, iTunes, LiveJournal, SimpleList, and others)
  - Update test files to use strongly-typed CompareTo method
  - Remove tests for ArgumentException on wrong type (no longer
    applicable with generic interface)

  The CompareTo method signature changes from:
    public int CompareTo(object? obj)
  to:
    public int CompareTo(TypeName? other)

  This improves type safety by eliminating runtime type checking
  and the need to throw ArgumentException for incompatible types.
…erators

 Introduce a marker interface and extension class to provide comparison
 operators (<, >, <=, >=) for 72 types implementing IComparable<T>.

 Changes:
 - Add IComparisonOperators marker interface
 - Add ComparisonOperatorExtensions with generic comparison operators
 - Implement IComparisonOperators on 72 types across Common, Core, Extensions
 - Remove redundant per-type comparison operators (keep == and != only)
 - Add 72 test classes covering all extension operator scenarios (1,440 tests)

 This reduces code duplication by ~2,800 lines while maintaining identical
 behavior through the centralized extension operators.
  - Replace verbose type checks with `is` pattern in 26 MatchByType methods
  - Remove unnecessary .ToCharArray() from String.Split calls (9 instances)
  - Convert array initializations to collection expressions in SyndicationDateTimeUtility
  - Replace string.Format(null, ...) with string interpolation (45+ instances)
  - Simplify Context properties using field-backed properties (C# 13) in 8 extensions
  - Add generic enum reflection utilities to EnumerationMetadataAttribute
  - Consolidate repeated enum reflection patterns in iTunes/YahooMedia extensions

  Changes reduce total lines by ~300
Replace bitwise OR operator (|=) with proper conditional comparison logic in all CompareTo methods. This preserves correct ordering semantics by only comparing subsequent fields when the current comparison result is 0.

Fixed patterns:
- YahooMediaUtility: Fixed in CompareCommonObjectEntities, CompareCommonObjectEntityClasses, CompareCommonObjectEntityCollections, and all CompareSequence overloads
- YahooMediaRestriction, YahooMediaThumbnail, YahooMediaTextConstruct, YahooMediaText, YahooMediaPlayer: Fixed consecutive property comparisons
- YahooMediaContent: Fixed comparison of 15+ properties
- FeedSynchronizationRelatedInformation: Fixed comparison of Link, Title, RelationType
- FeedSynchronizationSyndicationExtension: Fixed comparison of extension properties and nested context
- FeedSynchronizationSharingInformation: Fixed in both CompareSequence and CompareTo methods

Co-Authored-By: Claude Opus 4.5 <[email protected]>
  - Replace verbose type checks with `is` pattern in 26 MatchByType methods
  - Remove unnecessary .ToCharArray() from String.Split calls (9 instances)
  - Convert array initializations to collection expressions in SyndicationDateTimeUtility
  - Replace string.Format(null, ...) with string interpolation (45+ instances)
  - Simplify Context properties using field-backed properties (C# 13) in 8 extensions
  - Add generic enum reflection utilities to EnumerationMetadataAttribute
  - Consolidate repeated enum reflection patterns in iTunes/YahooMedia extensions

  Changes reduce total lines by ~300
  - Introduce generic CompareSequence<T> in ComparisonUtility.cs, consolidating
    8 type-specific overloads into a single generic method with Func<T,T,int>
  - Remove duplicate <, >, <=, >= operators from 47 classes now using C# 14
    extension operators via IComparisonOperators marker interface
  - Apply C# 14 field keyword to 55+ properties, eliminating backing field
    boilerplate in RSS, Atom, iTunes, YahooMedia, and other extension classes
  - Consolidate 9 domain-specific CompareSequence methods to use the generic
    ComparisonUtility.CompareSequence<T>
  - Replace exception-based Version parsing with Version.TryParse in
    SyndicationResourceMetadata.cs
…d syntax updates

Replace enum reflection with generic EnumerationMetadataAttribute methods
- Replace 30+ line manual reflection loops with single-line GetAlternateValue<T>()
  and GetEnumByAlternateValue<T>() calls across 15 files
- Affected: AtomTextConstruct, RssCloud, BlogMLTextConstruct, YahooMedia*,
  FeedSync*, DublinCore*, LiveJournalSecurity, XmlRpcClient, and more

Extract FindExtension to centralized extension method
- Create ExtensibleSyndicationObjectExtensions.cs with shared implementation
- Remove duplicate FindExtension methods from 43 implementing classes
- Update IExtensibleSyndicationObject interface (method moved to extension)

Null-conditional operator modernization
- Replace `x != null ? x.Method() : default` with `x?.Method() ?? default`
- Updated 12 files across Extensions and Core projects

Property expression body modernization
- Convert `get { return field; }` to `get => field;`
- Updated BlogML*, ApmlUtility, RsdUtility, and other files

Results: 105 files changed, 302 insertions, 2,596 deletions (-2,294 net)
…or consistency across multiple classes in the Argotic.Extensions library.
…tring'"

This reverts commit 721007a which contained a faulty find-and-replace
that corrupted code by replacing "o(RssEnclosur" with "cref=\"string\""
in method signatures and code blocks.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…or consistency across multiple classes in the Argotic.Extensions library.
@github-actions
Copy link

Code Coverage Summary Report - Linux (No TFM)

Summary
Generated on: 01/30/2026 - 07:39:12
Parser: Cobertura
Assemblies: 3
Classes: 193
Files: 191
Line coverage: 69.2% (11549 of 16666)
Covered lines: 11549
Uncovered lines: 5117
Coverable lines: 16666
Total lines: 64066
Branch coverage: 59.4% (5001 of 8411)
Covered branches: 5001
Total branches: 8411
Method coverage: Feature is only available for sponsors

Coverage

Argotic.Common - 79.1%
Name Line Branch
Argotic.Common 79.1% 66.8%
Argotic.Common.ComparisonOperatorExtensions 100% 100%
Argotic.Common.ComparisonUtility 100% 100%
Argotic.Common.ComparisonUtility 100% 100%
Argotic.Common.ConditionalGetResult 100% 95.4%
Argotic.Common.DiscoverableSyndicationEndpoint 96.3% 84.6%
Argotic.Common.EnumerationMetadataAttribute 67.3% 76.4%
Argotic.Common.EnumerationMetadataAttribute.EnumMetadataCache 100% 100%
Argotic.Common.HtmlAnchor 66.6%
Argotic.Common.MimeMediaTypeAttribute 96% 86.3%
Argotic.Common.SyndicationDateTimeUtility 86.2% 67.3%
Argotic.Common.SyndicationDiscoveryUtility 79.3% 66.3%
Argotic.Common.SyndicationEncodingUtility 89.6% 81.5%
Argotic.Common.SyndicationRequestOptions 100% 100%
Argotic.Common.SyndicationResourceLoadedEventArgs 35.4% 0%
Argotic.Common.SyndicationResourceLoadSettings 65.7% 43.7%
Argotic.Common.SyndicationResourceMetadata 63.8% 46.9%
Argotic.Common.SyndicationResourceSaveSettings 69.2% 58.3%
Argotic.Common.TrackbackDiscoveryMetadata 97.8% 77.2%
Argotic.Common.XmlWritableExtensions 48.1%
Argotic.Core - 65.5%
Name Line Branch
Argotic.Core 65.5% 58%
Argotic.Configuration.ServiceCollectionExtensions 100% 100%
Argotic.Configuration.TrackbackClientOptions 100%
Argotic.Configuration.XmlRpcClientOptions 100%
Argotic.Data.Adapters.Apml06SyndicationResourceAdapter 100% 89.2%
Argotic.Data.Adapters.Atom03SyndicationResourceAdapter 90.4% 82.6%
Argotic.Data.Adapters.Atom10SyndicationResourceAdapter 94% 90.5%
Argotic.Data.Adapters.AtomPublishing10SyndicationResourceAdapter 91.6% 85.7%
Argotic.Data.Adapters.BlogML20SyndicationResourceAdapter 100% 95.1%
Argotic.Data.Adapters.Opml20SyndicationResourceAdapter 100% 81.2%
Argotic.Data.Adapters.Rsd06SyndicationResourceAdapter 100% 87.5%
Argotic.Data.Adapters.Rsd10SyndicationResourceAdapter 100% 85.7%
Argotic.Data.Adapters.Rss090SyndicationResourceAdapter 100% 100%
Argotic.Data.Adapters.Rss091SyndicationResourceAdapter 97.6% 95.9%
Argotic.Data.Adapters.Rss092SyndicationResourceAdapter 96.4% 96%
Argotic.Data.Adapters.Rss10SyndicationResourceAdapter 100% 100%
Argotic.Data.Adapters.Rss20SyndicationResourceAdapter 100% 100%
Argotic.Data.Adapters.Sitemap09SyndicationResourceAdapter 0% 0%
Argotic.Data.Adapters.SyndicationResourceAdapter 71.3% 64%
Argotic.Net.TrackbackClient 23.6% 14.2%
Argotic.Net.TrackbackMessage 38.4% 10.8%
Argotic.Net.TrackbackResponse 21% 10%
Argotic.Net.WebContentType 35.4% 14.2%
Argotic.Net.XmlRpcArrayValue 98.2% 93.3%
Argotic.Net.XmlRpcClient 27.6% 27.2%
Argotic.Net.XmlRpcMessage 37.3% 28.5%
Argotic.Net.XmlRpcResponse 20.3% 22.9%
Argotic.Net.XmlRpcScalarValue 56.5% 16.6%
Argotic.Net.XmlRpcStructureMember 98.3% 90%
Argotic.Net.XmlRpcStructureValue 2.3% 2.2%
Argotic.Publishing.AtomAcceptedMediaRange 79.1% 57.1%
Argotic.Publishing.AtomCategoryDocument 47.3% 61.7%
Argotic.Publishing.AtomEntryResource 14.4% 0%
Argotic.Publishing.AtomMemberResources 50.7% 65.2%
Argotic.Publishing.AtomServiceDocument 58.1% 70%
Argotic.Publishing.AtomWorkspace 72.5% 76.6%
Argotic.Syndication.AtomCategory 62.1% 30.5%
Argotic.Syndication.AtomContent 22.9% 12.9%
Argotic.Syndication.AtomEntry 64.4% 67.2%
Argotic.Syndication.AtomFeed 66.8% 57.6%
Argotic.Syndication.AtomGenerator 78% 55.5%
Argotic.Syndication.AtomIcon 76.4% 45.4%
Argotic.Syndication.AtomId 76.4% 40.9%
Argotic.Syndication.AtomLink 68.9% 44.8%
Argotic.Syndication.AtomLogo 76.4% 45.4%
Argotic.Syndication.AtomPersonConstruct 75.5% 64.7%
Argotic.Syndication.AtomSource 1% 0.6%
Argotic.Syndication.AtomTextConstruct 71.7% 63%
Argotic.Syndication.AtomUtility 68% 50%
Argotic.Syndication.GenericSyndicationCategory 100% 94.4%
Argotic.Syndication.GenericSyndicationFeed 85.3% 81.8%
Argotic.Syndication.GenericSyndicationItem 100% 94.7%
Argotic.Syndication.OpmlDocument 92.5% 87.5%
Argotic.Syndication.OpmlHead 91.7% 83.3%
Argotic.Syndication.OpmlOutline 80.2% 70.3%
Argotic.Syndication.OpmlOwner 77.1% 53.8%
Argotic.Syndication.OpmlWindow 39.3% 18.7%
Argotic.Syndication.RssCategory 63% 41.1%
Argotic.Syndication.RssChannel 73.4% 61.9%
Argotic.Syndication.RssCloud 41.4% 10.5%
Argotic.Syndication.RssEnclosure 76.5% 52.9%
Argotic.Syndication.RssFeed 89.5% 78.9%
Argotic.Syndication.RssGuid 30.1% 12.5%
Argotic.Syndication.RssImage 38.5% 6.8%
Argotic.Syndication.RssItem 56% 48.5%
Argotic.Syndication.RssSource 26.1% 15.6%
Argotic.Syndication.RssTextInput 32.9% 7.8%
Argotic.Syndication.Sitemap 0% 0%
Argotic.Syndication.SitemapIndex 0% 0%
Argotic.Syndication.SitemapIndexEntry 25% 16.6%
Argotic.Syndication.SitemapUrl 23.5% 12.5%
Argotic.Syndication.SitemapUtility 100% 75.8%
Argotic.Syndication.Specialized.ApmlApplication 80.3% 50%
Argotic.Syndication.Specialized.ApmlAuthor 85.2% 69.4%
Argotic.Syndication.Specialized.ApmlConcept 85.2% 69.4%
Argotic.Syndication.Specialized.ApmlDocument 87.5% 94.7%
Argotic.Syndication.Specialized.ApmlHead 84.6% 65.7%
Argotic.Syndication.Specialized.ApmlProfile 63.6% 57.6%
Argotic.Syndication.Specialized.ApmlSource 59.3% 46.5%
Argotic.Syndication.Specialized.ApmlUtility 100% 50%
Argotic.Syndication.Specialized.BlogMLAttachment 100% 97.6%
Argotic.Syndication.Specialized.BlogMLAuthor 62.5% 38.4%
Argotic.Syndication.Specialized.BlogMLCategory 58.9% 38.2%
Argotic.Syndication.Specialized.BlogMLComment 58.6% 38.4%
Argotic.Syndication.Specialized.BlogMLDocument 94.3% 92.8%
Argotic.Syndication.Specialized.BlogMLPost 56.9% 51%
Argotic.Syndication.Specialized.BlogMLTextConstruct 92.3% 79.1%
Argotic.Syndication.Specialized.BlogMLTrackback 100% 90%
Argotic.Syndication.Specialized.BlogMLUtility 87.5% 75.4%
Argotic.Syndication.Specialized.RsdApplicationInterface 73.9% 61.2%
Argotic.Syndication.Specialized.RsdDocument 91.1% 88.4%
Argotic.Syndication.Specialized.RsdUtility 100% 87.5%
Argotic.Extensions - 72.5%
Name Line Branch
Argotic.Extensions 72.5% 59.9%
Argotic.Extensions.Core.AtomPublishingControlSyndicationExtension 77.7% 50%
Argotic.Extensions.Core.AtomPublishingControlSyndicationExtensionContext 54.7% 42.8%
Argotic.Extensions.Core.AtomPublishingEditedSyndicationExtension 96.2% 100%
Argotic.Extensions.Core.AtomPublishingEditedSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.AtomPublishingUtility 70.4% 50%
Argotic.Extensions.Core.BasicGeocodingSyndicationExtension 85.2% 71.8%
Argotic.Extensions.Core.BasicGeocodingSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.BlogChannelSyndicationExtension 85.7% 50%
Argotic.Extensions.Core.BlogChannelSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.CreativeCommonsSyndicationExtension 87% 60%
Argotic.Extensions.Core.CreativeCommonsSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.DublinCoreElementSetSyndicationExtension 85.8% 43.7%
Argotic.Extensions.Core.DublinCoreElementSetSyndicationExtensionContext 92.1% 89.8%
Argotic.Extensions.Core.DublinCoreMetadataTermsSyndicationExtension 94.9% 68.7%
Argotic.Extensions.Core.DublinCoreMetadataTermsSyndicationExtensionContext 93.2% 89.6%
Argotic.Extensions.Core.FeedHistoryLinkRelation 39.3% 20.8%
Argotic.Extensions.Core.FeedHistorySyndicationExtension 96.7% 100%
Argotic.Extensions.Core.FeedHistorySyndicationExtensionContext 81.5% 65.3%
Argotic.Extensions.Core.FeedRankSyndicationExtension 85.7% 50%
Argotic.Extensions.Core.FeedRankSyndicationExtensionContext 80.3% 71.8%
Argotic.Extensions.Core.FeedSynchronizationHistory 70.2% 32.1%
Argotic.Extensions.Core.FeedSynchronizationItem 62.7% 33.3%
Argotic.Extensions.Core.FeedSynchronizationRelatedInformation 75.9% 58.3%
Argotic.Extensions.Core.FeedSynchronizationSharingInformation 86.5% 61.6%
Argotic.Extensions.Core.FeedSynchronizationSyndicationExtension 83.3% 73.6%
Argotic.Extensions.Core.FeedSynchronizationSyndicationExtensionContext 84.6% 78.5%
Argotic.Extensions.Core.ITunesCategory 52.3% 30.7%
Argotic.Extensions.Core.ITunesOwner 66.1% 66.6%
Argotic.Extensions.Core.ITunesSyndicationExtension 88.7% 50%
Argotic.Extensions.Core.ITunesSyndicationExtensionContext 86.4% 72%
Argotic.Extensions.Core.LiveJournalMood 72.7% 83.3%
Argotic.Extensions.Core.LiveJournalSecurity 67.7% 60%
Argotic.Extensions.Core.LiveJournalSyndicationExtension 75.7% 43.7%
Argotic.Extensions.Core.LiveJournalSyndicationExtensionContext 92.1% 78.1%
Argotic.Extensions.Core.LiveJournalUserPicture 38.2% 7.8%
Argotic.Extensions.Core.PheedSyndicationExtension 83.3% 50%
Argotic.Extensions.Core.PheedSyndicationExtensionContext 88.2% 77.7%
Argotic.Extensions.Core.PingbackSyndicationExtension 83.6% 50%
Argotic.Extensions.Core.PingbackSyndicationExtensionContext 85% 60%
Argotic.Extensions.Core.SimpleListGroup 69.2% 43.7%
Argotic.Extensions.Core.SimpleListSort 63.8% 39.1%
Argotic.Extensions.Core.SimpleListSyndicationExtension 91.8% 100%
Argotic.Extensions.Core.SimpleListSyndicationExtensionContext 76.1% 72.2%
Argotic.Extensions.Core.SitemapHreflangExtension 21.4% 15%
Argotic.Extensions.Core.SitemapHreflangLink 29% 10%
Argotic.Extensions.Core.SitemapImage 100% 91.6%
Argotic.Extensions.Core.SitemapImageExtension 5.3% 0%
Argotic.Extensions.Core.SitemapNewsExtension 4.5% 0%
Argotic.Extensions.Core.SitemapNewsPublication 32% 10%
Argotic.Extensions.Core.SitemapVideo 21.5% 8.6%
Argotic.Extensions.Core.SitemapVideoExtension 5.3% 0%
Argotic.Extensions.Core.SitemapVideoId 18.6% 9.3%
Argotic.Extensions.Core.SitemapVideoSegment 18.7% 7.6%
Argotic.Extensions.Core.SiteSummaryContentItem 26.7% 7.6%
Argotic.Extensions.Core.SiteSummaryContentSyndicationExtension 86.5% 70%
Argotic.Extensions.Core.SiteSummaryContentSyndicationExtensionContext 69.2% 42.3%
Argotic.Extensions.Core.SiteSummarySlashSyndicationExtension 88% 75%
Argotic.Extensions.Core.SiteSummarySlashSyndicationExtensionContext 92.1% 88.6%
Argotic.Extensions.Core.SiteSummaryUpdateSyndicationExtension 89.2% 75%
Argotic.Extensions.Core.SiteSummaryUpdateSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.TrackbackSyndicationExtension 83.3% 50%
Argotic.Extensions.Core.TrackbackSyndicationExtensionContext 80% 54.5%
Argotic.Extensions.Core.WellFormedWebCommentsSyndicationExtension 83.3% 50%
Argotic.Extensions.Core.WellFormedWebCommentsSyndicationExtensionContext 100% 100%
Argotic.Extensions.Core.YahooMediaCategory 88.5% 71.4%
Argotic.Extensions.Core.YahooMediaContent 88.4% 88.4%
Argotic.Extensions.Core.YahooMediaCopyright 89.4% 70.8%
Argotic.Extensions.Core.YahooMediaCredit 95.7% 78.5%
Argotic.Extensions.Core.YahooMediaGroup 92.6% 90%
Argotic.Extensions.Core.YahooMediaHash 47.5% 34.6%
Argotic.Extensions.Core.YahooMediaPlayer 92.3% 79.4%
Argotic.Extensions.Core.YahooMediaRating 95.1% 80%
Argotic.Extensions.Core.YahooMediaRestriction 26.5% 19.4%
Argotic.Extensions.Core.YahooMediaSyndicationExtension 64.1% 0%
Argotic.Extensions.Core.YahooMediaSyndicationExtensionContext 97.7% 95.8%
Argotic.Extensions.Core.YahooMediaText 36.1% 31.4%
Argotic.Extensions.Core.YahooMediaTextConstruct 80% 54.5%
Argotic.Extensions.Core.YahooMediaThumbnail 96.6% 85.7%
Argotic.Extensions.Core.YahooMediaUtility 66.5% 51%
Argotic.Extensions.ExtensibleSyndicationObjectExtensions 100% 100%
Argotic.Extensions.SyndicationExtension 82.4% 91.6%
Argotic.Extensions.SyndicationExtensionAdapter 95.7% 92%
Argotic.Extensions.SyndicationExtensionLoadedEventArgs 22.7% 0%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants