Skip to content

MA0003: don't require naming extension receivers and self-named arguments - #1361

Merged
meziantou merged 1 commit into
mainfrom
feature/requirenamedargument-extension-methods-44bcf1
Aug 29, 2026
Merged

meziantou merged 1 commit into
mainfrom
feature/requirenamedargument-extension-methods-44bcf1

Conversation

@meziantou

Copy link
Copy Markdown
Owner

Two cases where MA0003 asked for a named argument that could not be written, or that would not have improved readability.

[RequireNamedArgument] on an extension-method receiver

The attribute is now ignored on the this parameter of an extension method.

Before this change the behavior depended on the call syntax: value.Foo() has no argument to name at all, so nothing was reported, while Ext.Foo(value) mapped the argument to the this parameter and reported a diagnostic. Naming the receiver is never the readability win the attribute is meant to ask for, so the parameter is now skipped in both forms.

The check also covers C# 14 extension(...) blocks: their synthesized static method exposes the receiver as an extension-method parameter at ordinal 0, and the attribute written on the extension(...) clause does flow to it — I verified both with a Roslyn probe, and the corresponding tests fail when the guard is removed.

Arguments already carrying the name of the parameter

Foo(sample) for a parameter named sample is no longer reported — naming it would only repeat the name:

var sample = 0;
Foo(sample);  // no diagnostic

void Foo([RequireNamedArgument] int sample) { }

Details:

  • Covers locals, parameters, properties, and fields; the comparison ignores the case.
  • For fields, the _ and s_ prefixes are removed before comparing, so Foo(_sample) and Foo(s_sample) also match a parameter named sample.
  • The prefixes are stripped for fields only. A local named _sample is still reported, since the prefix is not a convention for locals and silencing it would hide real cases.
  • The raw name is compared before stripping, so a field _sample still matches a parameter actually named _sample.
  • The new MA0003.ignore_arguments_matching_parameter_name option (default true) turns the behavior off.

In practice this only affects the [RequireNamedArgument] path: the general MA0003 rule reports literals, which have no name. The check is placed on the shared path anyway so it applies to the rule as a whole.

Notes for the reviewer

  • The general MA0003 rule is deliberately left alone for extension receivers: Ext.Foo(null) still reports as before. Only the attribute path changed, matching what was asked for.
  • The config lookup for the new option only runs once the names actually match, so it costs nothing on the common path.
  • While restructuring, the two GetOperation calls previously made for every argument were folded into one.
  • No file under src/Meziantou.Analyzer.Annotations changed, so no package version bump; the attribute's new behavior is documented on the MA0003 page the annotations README already links to.

Testing

  • 13 new tests in NamedParameterAnalyzerTests (the extension(...) block one guarded by #if CSHARP14_OR_GREATER), passing on all five Roslyn versions.
  • Full suite: 18972 tests, 0 failures.
  • dotnet run --project src/DocumentationGenerator run until it reported no further changes.

…ents

Two cases where MA0003 asked for a named argument that could not be
written, or that would not have improved readability:

- `[RequireNamedArgument]` on the receiver of an extension method (the
  `this` parameter) was reported when the method was called using the
  static syntax (`Ext.Foo(value)`), while the instance syntax
  (`value.Foo()`) has no argument to name at all. The attribute is now
  ignored on that parameter. The check covers C# 14 `extension(...)`
  blocks, as their synthesized static method also exposes the receiver
  as an extension method parameter at ordinal 0.

- An argument that is a local, a parameter, a property, or a field
  already carrying the name of the parameter is no longer reported, as
  naming it would only repeat the name. The comparison ignores the case,
  and removes the `_` and `s_` prefixes for fields. The raw name is
  compared first, so a field `_value` still matches a parameter named
  `_value`. The new `MA0003.ignore_arguments_matching_parameter_name`
  option (default `true`) disables the behavior.

Also fold the two `GetOperation` calls made for every argument into one.
@meziantou
meziantou merged commit a34a73f into main Aug 29, 2026
13 checks passed
@meziantou
meziantou deleted the feature/requirenamedargument-extension-methods-44bcf1 branch August 29, 2026 22:17
IhateTrains pushed a commit to ParadoxGameConverters/ImperatorToCK3 that referenced this pull request Aug 30, 2026
Updated
[Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer)
from 3.0.190 to 3.0.194.

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

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

## 3.0.194

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

## What's Changed
* chore(deps): update dependency meziantou.framework.roslyn to 1.0.6 by
@​renovate[bot] in
meziantou/Meziantou.Analyzer#1362


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.193...3.0.194

## 3.0.193

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

## What's Changed
* MA0003: don't require naming extension receivers and self-named
arguments by @​meziantou in
meziantou/Meziantou.Analyzer#1361


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.192...3.0.193

## 3.0.192

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

## What's Changed
* chore(deps): update dependency meziantou.framework.roslyn to 1.0.5 by
@​renovate[bot] in
meziantou/Meziantou.Analyzer#1360


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.191...3.0.192

## 3.0.191

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

## What's Changed
* Give Meziantou.Framework.Roslyn its own auto-merged Renovate group by
@​meziantou in meziantou/Meziantou.Analyzer#1358
* chore(deps): update dependency meziantou.framework.roslyn to 1.0.4 by
@​renovate[bot] in
meziantou/Meziantou.Analyzer#1359


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.190...3.0.191

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Meziantou.Analyzer&package-manager=nuget&previous-version=3.0.190&new-version=3.0.194)](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 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] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced Sep 14, 2026
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.

1 participant