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

IhateTrains pushed a commit to ParadoxGameConverters/ImperatorToCK3 that referenced this pull request Nov 3, 2025
Updated
[Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer)
from 2.0.239 to 2.0.248.

<details>
<summary>Release notes</summary>

_Sourced from [Meziantou.Analyzer's
releases](https://github.com/meziantou/Meziantou.Analyzer/releases)._

## 2.0.248

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.248>

## What's Changed
* Update MA0053 to mention both class and record types by @​Copilot in
meziantou/Meziantou.Analyzer#915


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.247...2.0.248

## 2.0.247

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.247>

## What's Changed
* Update Roslyn dependencies and clean up PackageReferences by
@​meziantou in meziantou/Meziantou.Analyzer#916


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.246...2.0.247

## 2.0.246

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.246>

**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.245...2.0.246

## 2.0.245

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.245>

## What's Changed
* Fix MA0015 not detecting static ThrowIf methods on ArgumentException
and related types by @​Copilot in
meziantou/Meziantou.Analyzer#912


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.244...2.0.245

## 2.0.244

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.244>

## What's Changed
* Fix MA0011 not reported for types with ToString(IFormatProvider) but
no IFormattable by @​Copilot in
meziantou/Meziantou.Analyzer#910


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.243...2.0.244

## 2.0.243

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.243>

## What's Changed
* Add Roslyn analyzer for multiline XML comments by @​Copilot in
meziantou/Meziantou.Analyzer#908

## New Contributors
* @​Copilot made their first contribution in
meziantou/Meziantou.Analyzer#908

**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.242...2.0.243

## 2.0.242

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.242>

**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.241...2.0.242

## 2.0.241

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.241>

**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.240...2.0.241

## 2.0.240

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/2.0.240>

## What's Changed
* Add copilot instructions by @​meziantou in
meziantou/Meziantou.Analyzer#907


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.239...2.0.240

Commits viewable in [compare
view](meziantou/Meziantou.Analyzer@2.0.239...2.0.248).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Meziantou.Analyzer&package-manager=nuget&previous-version=2.0.239&new-version=2.0.248)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced Nov 3, 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