diff --git a/doc/USP0020.md b/doc/USP0020.md
new file mode 100644
index 00000000..ba7e3653
--- /dev/null
+++ b/doc/USP0020.md
@@ -0,0 +1,33 @@
+# USP0020 The Unity runtime invokes Unity messages
+
+Unity messages should not be flagged as unused because Unity invokes those messages.
+
+## Suppressed Diagnostic ID
+
+IDE0052 - Private method can be removed as it is never invoked.
+
+## Examples of code that produces a suppressed diagnostic
+```csharp
+using UnityEngine;
+
+class Camera : MonoBehaviour
+{
+ void Start()
+ {
+ //Some code
+ }
+
+ ///
+ /// This reference triggers IDE0052
+ ///
+ public float speed = 0f;
+}
+```
+
+## Why is the diagnostic reported?
+
+The IDE cannot find any references to the method `Start` and believes it to be unused.
+
+## Why do we suppress this diagnostic?
+
+Even though the IDE cannot find any references to `Start`, it will be called by Unity, and should not be removed.
\ No newline at end of file
diff --git a/doc/index.md b/doc/index.md
index bd1757d8..fd48bdc8 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -59,3 +59,4 @@ ID | Suppressed ID | Justification
[USP0017](USP0017.md) | IDE0074 | Unity objects should not use coalescing assignment
[USP0018](USP0018.md) | IDE0016 | Unity objects should not be used with throw expressions
[USP0019](USP0012.md) | IDE0051 | Don't flag private methods with PreserveAttribute or UsedImplicitlyAttribute as unused
+[USP0003](USP0020.md) | IDE0052 | The Unity runtime invokes Unity messages
diff --git a/src/Microsoft.Unity.Analyzers.Tests/MessageSuppressorTests.cs b/src/Microsoft.Unity.Analyzers.Tests/MessageSuppressorTests.cs
index efb7035e..9fe803e5 100644
--- a/src/Microsoft.Unity.Analyzers.Tests/MessageSuppressorTests.cs
+++ b/src/Microsoft.Unity.Analyzers.Tests/MessageSuppressorTests.cs
@@ -53,6 +53,31 @@ private void Start()
await VerifyCSharpDiagnosticAsync(test, suppressor);
}
+ [Fact]
+ public async Task UnusedMethodWithCrefSuppressed()
+ {
+ const string test = @"
+using UnityEngine;
+
+public class TestScript : MonoBehaviour
+{
+ private void Start()
+ {
+ }
+
+ ///
+ /// IDE0052 should be suppressed
+ ///
+ public float speed = 0f;
+}
+";
+
+ var suppressor = ExpectSuppressor(MessageSuppressor.MethodCrefRule)
+ .WithLocation(6, 18);
+
+ await VerifyCSharpDiagnosticAsync(test, suppressor);
+ }
+
[Fact]
public async Task UnusedParameterSuppressed()
{
diff --git a/src/Microsoft.Unity.Analyzers/MessageSuppressor.cs b/src/Microsoft.Unity.Analyzers/MessageSuppressor.cs
index 6366281c..b54bcd4a 100644
--- a/src/Microsoft.Unity.Analyzers/MessageSuppressor.cs
+++ b/src/Microsoft.Unity.Analyzers/MessageSuppressor.cs
@@ -20,6 +20,11 @@ public class MessageSuppressor : DiagnosticSuppressor
suppressedDiagnosticId: "IDE0051",
justification: Strings.MessageSuppressorJustification);
+ internal static readonly SuppressionDescriptor MethodCrefRule = new(
+ id: "USP0020",
+ suppressedDiagnosticId: "IDE0052",
+ justification: Strings.MessageSuppressorJustification);
+
internal static readonly SuppressionDescriptor MethodCodeQualityRule = new(
id: "USP0014",
suppressedDiagnosticId: "CA1822",
@@ -36,7 +41,7 @@ public class MessageSuppressor : DiagnosticSuppressor
suppressedDiagnosticId: "CA1801",
justification: Strings.MessageSuppressorJustification);
- public override ImmutableArray SupportedSuppressions => ImmutableArray.Create(MethodRule, MethodCodeQualityRule, ParameterRule, ParameterCodeQualityRule);
+ public override ImmutableArray SupportedSuppressions => ImmutableArray.Create(MethodRule, MethodCrefRule, MethodCodeQualityRule, ParameterRule, ParameterCodeQualityRule);
public override void ReportSuppressions(SuppressionAnalysisContext context)
{