Skip to content

Comments

Fix MA0158 not reported when lock field is initialized in constructor#1037

Merged
meziantou merged 2 commits intomainfrom
copilot/fix-ma0158-reporting-issue
Feb 22, 2026
Merged

Fix MA0158 not reported when lock field is initialized in constructor#1037
meziantou merged 2 commits intomainfrom
copilot/fix-ma0158-reporting-issue

Conversation

Copy link
Contributor

Copilot AI commented Feb 22, 2026

MA0158 was silently suppressed when an object lock field was assigned in a constructor (.ctor or .cctor) instead of inline, even if the field was exclusively used in lock statements.

Root Cause

Every assignment to a field (_lock = new object()) produces an IFieldReferenceOperation on the left-hand side. The analyzer treated any field reference whose parent wasn't an ILockOperation as a disqualifying usage, calling ExcludeSymbol — permanently preventing the diagnostic regardless of how the field was used elsewhere.

Fix

Skip field/local references that are assignment targets — they represent writes, not reads, and carry no information about how the symbol is used:

// Assignment targets (e.g., initializations in constructors) are not usages
if (operation.Parent is IAssignmentOperation { Target: var assignTarget } && assignTarget == operation)
    return;

This correctly handles both instance and static constructor initialization:

public sealed class A
{
    private readonly object _lock; // now correctly reported as MA0158

    public A() { _lock = new object(); }

    public void Run() { lock (_lock) { } }
}

Tests Added

  • Field initialized in .ctor, used only in lock → diagnostic reported
  • Field initialized in .ctor, also used outside lock → no diagnostic
  • Static field initialized in .cctor, used only in lock → diagnostic reported
  • Static field initialized in .cctor, also used outside lock → no diagnostic

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:

  • 1s1vsblobprodcus386.vsblob.vsassets.io
    • Triggering command: /usr/share/dotnet/dotnet dotnet restore --no-dependencies /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/Meziantou.Analyzer.slnx --packages /home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)
    • Triggering command: /usr/share/dotnet/dotnet dotnet restore --no-dependencies /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/Meziantou.Analyzer.Test.csproj --packages /home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)
  • pdfvsblobprodcus380.vsblob.vsassets.io
    • Triggering command: /usr/share/dotnet/dotnet dotnet restore --no-dependencies /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/Meziantou.Analyzer.Test.csproj --packages /home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)
  • st8vsblobprodcus339.vsblob.vsassets.io
    • Triggering command: /usr/share/dotnet/dotnet dotnet restore --no-dependencies /home/REDACTED/work/Meziantou.Analyzer/Meziantou.Analyzer/tests/Meziantou.Analyzer.Test/Meziantou.Analyzer.Test.csproj --packages /home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/Meziantou.Analyzer/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (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>MA0158 is not reported when lock is initialized in .ctor or .cctor</issue_title>
<issue_description>### Version of the Meziantou.Analyzer NuGet package

3.0.11

Rule Identifier

MA0158

Target Framework

.NET 10.0

C# Language version

C# 14

Description

When the lock field is initialized in the instance or static constructor, MA0158 is not reported if the type of the field is not System.Threading.Lock.

Reproduction Steps

Constructor:

public sealed class A
{
    private readonly object _lock; // MA0158 is not reported

    public A()
    {
        _lock = new object();
    }

    public void Run()
    {
        lock (_lock)
        {
        }
    }
}

Type initializer / .cctor:

public sealed class B
{
    private static readonly object Lock; // MA0158 is not reported

    static B()
    {
        Lock = new object();
    }

    public void Run()
    {
        lock (Lock)
        {
        }
    }
}

Other information

No response</issue_description>

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


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: meziantou <509220+meziantou@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix MA0158 not reported for lock initialization Fix MA0158 not reported when lock field is initialized in constructor Feb 22, 2026
Copilot AI requested a review from meziantou February 22, 2026 15:32
@meziantou meziantou marked this pull request as ready for review February 22, 2026 15:37
@meziantou meziantou enabled auto-merge (squash) February 22, 2026 15:39
@meziantou meziantou merged commit 12bfd87 into main Feb 22, 2026
12 checks passed
@meziantou meziantou deleted the copilot/fix-ma0158-reporting-issue branch February 22, 2026 15:42
This was referenced Feb 22, 2026
IhateTrains pushed a commit to ParadoxGameConverters/ImperatorToCK3 that referenced this pull request Feb 23, 2026
Updated
[Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer)
from 2.0.302 to 3.0.15.

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

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

## 3.0.15

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

## What's Changed
* MA0183: Extend detection to Console.Write, Console.WriteLine, and
StringBuilder.AppendFormat by @​Copilot in
meziantou/Meziantou.Analyzer#1042


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.14...3.0.15

## 3.0.14

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

## What's Changed
* docs(MA0028): Remove incorrect AppendFormat optimization example by
@​Copilot in meziantou/Meziantou.Analyzer#1039
* docs: Document MA0158 as similar to IDE0330 by @​Copilot in
meziantou/Meziantou.Analyzer#1040
* MA0028: Detect StringBuilder.AppendFormat with no-placeholder format
strings by @​Copilot in
meziantou/Meziantou.Analyzer#1041


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.13...3.0.14

## 3.0.13

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

## What's Changed
* Fix incorrect CA1065 → MA0072 equivalence mapping by @​Copilot in
meziantou/Meziantou.Analyzer#1028
* Fix IDE0330 comparison incorrectly referencing MA0153 instead of
MA0158 by @​Copilot in
meziantou/Meziantou.Analyzer#1036
* docs(MA0042): Document false positive when calling sync method from
its own async counterpart by @​Copilot in
meziantou/Meziantou.Analyzer#1038
* Fix MA0158 not reported when lock field is initialized in constructor
by @​Copilot in
meziantou/Meziantou.Analyzer#1037


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.12...3.0.13

## 3.0.12

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

## What's Changed
* MA0056: Reclassify as "similar to" CA2214 and document differences by
@​Copilot in meziantou/Meziantou.Analyzer#1024
* Fix MA0027 not firing for derived exception types by @​Copilot in
meziantou/Meziantou.Analyzer#1026


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.11...3.0.12

## 3.0.11

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

## What's Changed
* Reduce test fakiness with source generators by @​meziantou in
meziantou/Meziantou.Analyzer#1022


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.10...3.0.11

## 3.0.10

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

## What's Changed
* Add test for implicit params array in AppendLine with AppendFormat by
@​meziantou in meziantou/Meziantou.Analyzer#1021


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.9...3.0.10

## 3.0.9

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

## What's Changed
* MA0029: Suppress all Where().X() diagnostics on IQueryable by
@​Copilot in meziantou/Meziantou.Analyzer#1017


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.8...3.0.9

## 3.0.8

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

## What's Changed
* Remove exception handling from WithSourceGeneratorsFromNuGet and
document Roslyn version testing by @​Copilot in
meziantou/Meziantou.Analyzer#1015


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.7...3.0.8

## 3.0.7

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

## What's Changed
* Fix MA0110 to handle property initializers by @​Copilot in
meziantou/Meziantou.Analyzer#1014


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.6...3.0.7

## 3.0.6

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

## What's Changed
* MA0110: Suggest partial property before partial method by @​Copilot in
meziantou/Meziantou.Analyzer#1013


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.5...3.0.6

## 3.0.5

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

## What's Changed
* MA0110: Support top-level statements by @​Copilot in
meziantou/Meziantou.Analyzer#1012


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.4...3.0.5

## 3.0.4

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

## What's Changed
* MA0110: Remove field/variable when generating partial property code
fix by @​Copilot in
meziantou/Meziantou.Analyzer#1011


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.3...3.0.4

## 3.0.3

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

## What's Changed
* MA0110: Derive generated regex names from field/variable context by
@​Copilot in meziantou/Meziantou.Analyzer#1010


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.2...3.0.3

## 3.0.2

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

## What's Changed
* Add partial property support for MA0110 Regex Source Generator by
@​Copilot in meziantou/Meziantou.Analyzer#1009


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.1...3.0.2

## 3.0.1

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

## What's Changed
* Remove Roslyn 3.x support by @​Copilot in
meziantou/Meziantou.Analyzer#1007


**Full Changelog**:
meziantou/Meziantou.Analyzer@2.0.302...3.0.1

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Meziantou.Analyzer&package-manager=nuget&previous-version=2.0.302&new-version=3.0.15)](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 Feb 23, 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.

MA0158 is not reported when lock is initialized in .ctor or .cctor

2 participants