Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 1, 2025

MA0011 was not reported when a type declares both ToString() and ToString(IFormatProvider) but does not implement IFormattable. The analyzer's culture-sensitivity check would exit early for non-IFormattable types before checking for the overload.

public sealed class Location
{
    public override string ToString() => ToString(CultureInfo.CurrentCulture);
    public string ToString(IFormatProvider formatProvider) => "...";
}

// Previously: no diagnostic
// Now: MA0011 reported
location.ToString();

Changes

  • UseIFormatProviderAnalyzer: Added early check for ToString() calls with IFormatProvider overload before culture-sensitive type validation
  • Test coverage: Added ToString_WithIFormatProviderOverload_WithoutIFormattable test case

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • www.nuget.org
    • Triggering command: /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.runtimeconfig.json --depsfile /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.deps.json /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/testhost.dll --port 44033 --endpoint 127.0.0.1:044033 --role client --parentprocessid 4755 --datacollectionport 38543 --telemetryoptedin false (dns block)
    • Triggering command: /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.runtimeconfig.json --depsfile /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.deps.json /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/testhost.dll --port 38109 --endpoint 127.0.0.1:038109 --role client --parentprocessid 5088 --datacollectionport 45743 --telemetryoptedin false (dns block)
    • Triggering command: /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.runtimeconfig.json --depsfile /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/Meziantou.Analyzer.Test.deps.json /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/bin/Debug/net10.0/testhost.dll --port 46211 --endpoint 127.0.0.1:046211 --role client --parentprocessid 5480 --datacollectionport 45673 --telemetryoptedin false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>MA0011 not reported when type does not implement IFormattable</issue_title>
<issue_description>### Version of the Meziantou.Analyzer NuGet package

2.0.243

Rule Identifier

MA0011

Target Framework

.NET 9.0

C# Language version

4.14.0-3.25412.6 (c167adef)

Description

When a given type does not implement IFormattable and has both a ToString() and a ToString(IFormatProvider), then MA0011 is not reported when ToString() is invoked.

Reproduction Steps

Minimal code:

using System;
using System.Globalization;

internal sealed class Program
{
    private static void Main()
    {
        Location location = new()
            {
                Start = 1,
                End = 5
            };
        Console.WriteLine(location.ToString());
    }
}

public sealed class Location
{
    public required int Start { get; init; }

    public required int End { get; init; }

    public override string ToString()
    {
        return ToString(CultureInfo.CurrentCulture);
    }

    public string ToString(IFormatProvider formatProvider)
    {
        return string.Empty;
    }
}

Other information

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…ut implementing IFormattable

Co-authored-by: meziantou <[email protected]>
Copilot AI changed the title [WIP] Fix MA0011 not reported for non-IFormattable types Fix MA0011 not reported for types with ToString(IFormatProvider) but no IFormattable Nov 1, 2025
Copilot AI requested a review from meziantou November 1, 2025 20:34
Copilot finished work on behalf of meziantou November 1, 2025 20:34
@meziantou meziantou marked this pull request as ready for review November 2, 2025 01:00
Copilot AI review requested due to automatic review settings November 2, 2025 01:00
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

This PR refactors the OverloadFinder API to use new structured types (OverloadOptions and OverloadParameterType) for better encapsulation and extensibility. It also enhances the culture-sensitive type detection to recognize types with ToString(IFormatProvider) methods even when they don't implement IFormattable.

  • Introduced OverloadOptions record struct to consolidate multiple boolean and nullable parameters into a single options object
  • Introduced OverloadParameterType record struct to support inheritance-based type matching for overload parameters
  • Enhanced IsCultureSensitiveType logic to detect types with ToString(IFormatProvider) overloads that don't implement IFormattable

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Meziantou.Analyzer/Internals/OverloadParameterType.cs New record struct for parameter type specification with optional inheritance support
src/Meziantou.Analyzer/Internals/OverloadOptions.cs New record struct to consolidate overload finder options
src/Meziantou.Analyzer/Internals/OverloadFinder.cs Refactored to use new option types, added overloads for IOperation types, and improved type matching logic
src/Meziantou.Analyzer/Internals/CultureSensitiveFormattingContext.cs Enhanced to detect formattable types without IFormattable interface; moved format provider check earlier
src/Meziantou.Analyzer/Rules/UseIFormatProviderAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/UseStringComparisonAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/UseStringComparerAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasTimeProviderAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasCancellationTokenAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/EmbedCaughtExceptionAsInnerExceptionAnalyzer.cs Updated to use new OverloadFinder API with OverloadOptions
src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs Updated to use new static HasSimilarParameters API
tests/Meziantou.Analyzer.Test/Rules/UseIFormatProviderAnalyzerTests.cs Added test for types with ToString(IFormatProvider) overload without IFormattable

This was referenced Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MA0011 not reported when type does not implement IFormattable

2 participants