From 784379d012bb66284d1fa24760ffa913d5bbf382 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 8 May 2026 18:17:26 +0200 Subject: [PATCH] Annotate intentional analyzer-violations with [SuppressMessage]. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four cases where the analyzer rule conflicts with intentional design: * EmptyList.IDisposable.Dispose (CA1063) — explicit IDisposable on IEnumerator; making it public would conflict with the rest of the IList / IEnumerator surface. * MetadataFile.SectionHeaders (CA1065) — throw documents that this MetadataFileKind has no PE sections; PE-like derived kinds override. * LongSet.GetHashCode + LongSet itself (CA1065 + CA2231) — explicit guards against using LongSet in hash containers / via equality operators; SetEquals is the supported comparison and IEquatable.Equals is itself [Obsolete]. * AnnotationList.Clone (CA2002) — AnnotationList is a private nested type; the surrounding Annotatable class deliberately locks on the AnnotationList instance to serialize annotation reads/writes, and external code cannot obtain a reference to it. Co-Authored-By: Claude Opus 4.7 (1M context) --- ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs | 3 +++ ICSharpCode.Decompiler/Metadata/MetadataFile.cs | 3 +++ ICSharpCode.Decompiler/Util/EmptyList.cs | 3 +++ ICSharpCode.Decompiler/Util/LongSet.cs | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs index a82a9d54f..0dba3d644 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -115,6 +116,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { } + [SuppressMessage("Reliability", "CA2002:Do not lock on objects with weak identity", + Justification = "AnnotationList is a private nested type — the surrounding Annotatable class deliberately locks on the AnnotationList instance to serialize annotation reads/writes; external code cannot obtain a reference to it.")] public object Clone() { lock (this) diff --git a/ICSharpCode.Decompiler/Metadata/MetadataFile.cs b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs index 6068800c4..398cf3fe0 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataFile.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; @@ -285,6 +286,8 @@ namespace ICSharpCode.Decompiler.Metadata throw new BadImageFormatException("This metadata file does not support sections."); } + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", + Justification = "Throw signals that this MetadataFileKind has no PE sections; derived PE-like kinds override.")] public virtual ImmutableArray SectionHeaders => throw new BadImageFormatException("This metadata file does not support sections."); /// diff --git a/ICSharpCode.Decompiler/Util/EmptyList.cs b/ICSharpCode.Decompiler/Util/EmptyList.cs index 31f69f08a..8d066332f 100644 --- a/ICSharpCode.Decompiler/Util/EmptyList.cs +++ b/ICSharpCode.Decompiler/Util/EmptyList.cs @@ -20,6 +20,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace ICSharpCode.Decompiler.Util { @@ -99,6 +100,8 @@ namespace ICSharpCode.Decompiler.Util get { throw new NotSupportedException(); } } + [SuppressMessage("Usage", "CA1063:Implement IDisposable Correctly", + Justification = "Explicit IDisposable implementation for IEnumerator; intentional no-op for the singleton.")] void IDisposable.Dispose() { } diff --git a/ICSharpCode.Decompiler/Util/LongSet.cs b/ICSharpCode.Decompiler/Util/LongSet.cs index e4e132929..f4c64aa80 100644 --- a/ICSharpCode.Decompiler/Util/LongSet.cs +++ b/ICSharpCode.Decompiler/Util/LongSet.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace ICSharpCode.Decompiler.Util @@ -28,6 +29,8 @@ namespace ICSharpCode.Decompiler.Util /// /// An immutable set of longs, that is implemented as a list of intervals. /// + [SuppressMessage("Usage", "CA2231:Overload operator equals on overriding value type Equals", + Justification = "Equality on LongSet is intentionally only available via SetEquals — the IEquatable.Equals overload is itself [Obsolete] in favor of SetEquals.")] public struct LongSet : IEquatable { /// @@ -362,6 +365,8 @@ namespace ICSharpCode.Decompiler.Util return obj is LongSet && SetEquals((LongSet)obj); } + [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", + Justification = "Throw is an explicit guard against using LongSet in hash-based containers; use SetEquals for comparison.")] public override int GetHashCode() { throw new NotImplementedException();