diff --git a/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs b/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs
index d3c71398f2058..d970743029292 100644
--- a/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs
+++ b/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs
@@ -1334,5 +1334,36 @@ await TestInRegularAndScriptAsync(
@"public record Foo(int [|MyInt|]);",
options: s_options.MergeStyles(s_options.PropertyNamesArePascalCase, s_options.ParameterNamesAreCamelCaseWithPUnderscorePrefix));
}
+
+ [Theory]
+ [InlineData("_")]
+ [InlineData("_1")]
+ [InlineData("_123")]
+ public async Task TestDiscardParameterAsync(string identifier)
+ {
+ await TestMissingInRegularAndScriptAsync(
+$@"class C
+{{
+ void M(int [|{identifier}|])
+ {{
+ }}
+}}", new TestParameters(options: s_options.ParameterNamesAreCamelCase));
+ }
+
+ [Theory]
+ [InlineData("_")]
+ [InlineData("_1")]
+ [InlineData("_123")]
+ public async Task TestDiscardLocalAsync(string identifier)
+ {
+ await TestMissingInRegularAndScriptAsync(
+$@"class C
+{{
+ void M()
+ {{
+ int [|{identifier}|] = 0;
+ }}
+}}", new TestParameters(options: s_options.LocalNamesAreCamelCase));
+ }
}
}
diff --git a/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs b/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs
index 17ec407f421b7..e35c2f2de973c 100644
--- a/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs
+++ b/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs
@@ -9,6 +9,7 @@
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.NamingStyles;
+using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
@@ -116,6 +117,11 @@ void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
return null;
}
+ if (symbol.IsSymbolWithSpecialDiscardName())
+ {
+ return null;
+ }
+
var namingPreferences = GetNamingStylePreferences(compilation, symbol, options, cancellationToken);
if (namingPreferences == null)
{
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
index 57cfdc4c01a5f..72915ad1d0f37 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
@@ -622,7 +622,7 @@ bool ShouldReportUnusedValueDiagnostic(
if (_options.UnusedValueAssignmentSeverity == ReportDiagnostic.Suppress ||
symbol.GetSymbolType().IsErrorType() ||
(symbol.IsStatic && symbol.Kind == SymbolKind.Local) ||
- IsSymbolWithSpecialDiscardName(symbol))
+ symbol.IsSymbolWithSpecialDiscardName())
{
return false;
}
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs
index 99905f446a1a8..486f1d1e1bee9 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs
@@ -259,7 +259,7 @@ private bool IsUnusedParameterCandidate(IParameterSymbol parameter)
// without disabling the diagnostic completely.
// We ignore parameter names that start with an underscore and are optionally followed by an integer,
// such as '_', '_1', '_2', etc.
- if (IsSymbolWithSpecialDiscardName(parameter))
+ if (parameter.IsSymbolWithSpecialDiscardName())
{
return false;
}
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs
index 1c8fe54d2bbe6..b29f07e285047 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs
@@ -323,14 +323,5 @@ public static bool GetIsRemovableAssignmentDiagnostic(Diagnostic diagnostic)
Debug.Assert(TryGetUnusedValuePreference(diagnostic, out _));
return diagnostic.Properties.ContainsKey(IsRemovableAssignmentKey);
}
-
- ///
- /// Returns true for symbols whose name starts with an underscore and
- /// are optionally followed by an integer, such as '_', '_1', '_2', etc.
- /// These are treated as special discard symbol names.
- ///
- private static bool IsSymbolWithSpecialDiscardName(ISymbol symbol)
- => symbol.Name.StartsWith("_") &&
- (symbol.Name.Length == 1 || uint.TryParse(symbol.Name.Substring(1), out _));
}
}
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs
index 60efd1c5ea7cd..4ac7f6e976f24 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs
@@ -740,5 +740,14 @@ public static bool IsKind(this ISymbol symbol, SymbolKind kind, [NotNul
result = (TSymbol)symbol;
return true;
}
+
+ ///
+ /// Returns true for symbols whose name starts with an underscore and
+ /// are optionally followed by an integer, such as '_', '_1', '_2', etc.
+ /// These are treated as special discard symbol names.
+ ///
+ public static bool IsSymbolWithSpecialDiscardName(this ISymbol symbol)
+ => symbol.Name.StartsWith("_") &&
+ (symbol.Name.Length == 1 || uint.TryParse(symbol.Name.Substring(1), out _));
}
}