diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs index 887585aab992..d905b372fc19 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs @@ -142,11 +142,12 @@ private static void CheckTypeMembers(IEnumerable members, Action>.GetInstance(StringComparer.OrdinalIgnoreCase); foreach (var member in members) { - // Ignore constructors, indexers, operators and destructors for name check + // Ignore constructors, indexers, operators, destructors and extension blocks for name check if (member.IsConstructor() || member.IsDestructor() || member.IsIndexer() || member.IsUserDefinedOperator() || + member.IsExtension() || overloadsToSkip.Contains(member)) { continue; diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs index 9c395554d9a6..0559da8a4418 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs @@ -17,8 +17,12 @@ internal static class INamedTypeSymbolExtensions private static readonly Func s_isFileLocal = LightupHelpers.CreateSymbolPropertyAccessor(typeof(INamedTypeSymbol), nameof(IsFileLocal), fallbackResult: false); + private static readonly Func s_isExtension = LightupHelpers.CreateSymbolPropertyAccessor(typeof(INamedTypeSymbol), nameof(IsExtension), fallbackResult: false); + public static bool IsFileLocal(this INamedTypeSymbol symbol) => s_isFileLocal(symbol); + public static bool IsExtension(this INamedTypeSymbol symbol) => s_isExtension(symbol); + public static IEnumerable GetBaseTypesAndThis(this INamedTypeSymbol type) { INamedTypeSymbol current = type; diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs index 03b9c0e21630..e3a352b3718e 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs @@ -161,6 +161,11 @@ public static bool IsConversionOperator([NotNullWhen(returnValue: true)] this IS return symbol is IMethodSymbol { MethodKind: MethodKind.Conversion }; } + public static bool IsExtension([NotNullWhen(returnValue: true)] this ISymbol? symbol) + { + return symbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.IsExtension(); + } + public static ImmutableArray GetParameters(this ISymbol? symbol) { return symbol switch diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCaseTests.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCaseTests.cs index 5da69d2d9eda..ecc347e95df9 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCaseTests.cs +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCaseTests.cs @@ -419,6 +419,35 @@ public partial class D GetCA1708CSharpResultAt(30, 30, Parameter, "N.D.SomeDelegate")); } + [Fact] + public async Task TestMultipleExtensionBlocks() + { + string code = @" +public static class StringExtensions +{ + private const string ExtensionString = ""Extension""; + + // Static class extensions + extension(string) + { + public static string CreateExtension() => ExtensionString; + } + + // Instance extensions + extension(string s) + { + public bool IsExtensionString() => s == ExtensionString; + } +} +"; + + await new VerifyCS.Test + { + TestCode = code, + LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp14, + }.RunAsync(); + } + #endregion #region Helper Methods