diff --git a/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs b/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs index 5fba21395b..abbefd8916 100644 --- a/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs +++ b/src/Analyzers/MSTest.Analyzers/DoNotUseShadowingAnalyzer.cs @@ -112,7 +112,8 @@ private static bool IsMemberShadowing(ISymbol member, ISymbol baseMember) } // Compare methods - if (member is IMethodSymbol methodSymbol && baseMember is IMethodSymbol baseMethodSymbol) + if (member is IMethodSymbol methodSymbol && baseMember is IMethodSymbol baseMethodSymbol && methodSymbol.IsGenericMethod == baseMethodSymbol.IsGenericMethod + && !(methodSymbol.DeclaredAccessibility == Accessibility.Private && baseMethodSymbol.DeclaredAccessibility == Accessibility.Private)) { return methodSymbol.Name == baseMethodSymbol.Name && methodSymbol.Parameters.Length == baseMethodSymbol.Parameters.Length && diff --git a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs index d14bf4f6cb..7855473260 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs +++ b/src/Analyzers/MSTest.Analyzers/Resources.Designer.cs @@ -375,7 +375,7 @@ internal static string DoNotUseShadowingDescription { } /// - /// Looks up a localized string similar to Member '{0}' is already exist in the base class. + /// Looks up a localized string similar to Member '{0}' already exists in the base class. /// internal static string DoNotUseShadowingMessageFormat { get { diff --git a/src/Analyzers/MSTest.Analyzers/Resources.resx b/src/Analyzers/MSTest.Analyzers/Resources.resx index d7a17fdaf4..ff98060e2e 100644 --- a/src/Analyzers/MSTest.Analyzers/Resources.resx +++ b/src/Analyzers/MSTest.Analyzers/Resources.resx @@ -524,7 +524,7 @@ The type declaring these methods should also respect the following rules: Shadowing test members could cause testing issues (such as NRE). - Member '{0}' is already exist in the base class + Member '{0}' already exists in the base class Do not use shadowing diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf index 73394110d6..4cd87c833a 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf @@ -287,8 +287,8 @@ Typ deklarující tyto metody by měl také respektovat následující pravidla: - Member '{0}' is already exist in the base class - Člen {0} už v základní (kořenové) třídě existuje. + Member '{0}' already exists in the base class + Člen {0} už v základní (kořenové) třídě existuje. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf index 383a305d66..a35c2b26b3 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf @@ -289,8 +289,8 @@ Der Typ, der diese Methoden deklariert, sollte auch die folgenden Regeln beachte - Member '{0}' is already exist in the base class - Der Member "{0}" ist bereits in der Basisklasse vorhanden. + Member '{0}' already exists in the base class + Der Member "{0}" ist bereits in der Basisklasse vorhanden. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf index 31ddf9a43e..418b2f9054 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf @@ -287,8 +287,8 @@ El tipo que declara estos métodos también debe respetar las reglas siguientes: - Member '{0}' is already exist in the base class - El miembro ''{0}'' ya existe en la clase base + Member '{0}' already exists in the base class + El miembro ''{0}'' ya existe en la clase base diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf index 099a43ebcd..77936062db 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf @@ -287,8 +287,8 @@ Le type doit être une classe - Member '{0}' is already exist in the base class - Le membre '{0}' existe déjà dans la classe de base + Member '{0}' already exists in the base class + Le membre '{0}' existe déjà dans la classe de base diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf index f58c263019..fe26e02097 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf @@ -287,8 +287,8 @@ Anche il tipo che dichiara questi metodi deve rispettare le regole seguenti: - Member '{0}' is already exist in the base class - Il membro '{0}' esiste già nella classe di base + Member '{0}' already exists in the base class + Il membro '{0}' esiste già nella classe di base diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf index a4f1826d2e..3bd2cf4781 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf @@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules: - Member '{0}' is already exist in the base class - メンバー '{0}' は既に基本クラスに存在します + Member '{0}' already exists in the base class + メンバー '{0}' は既に基本クラスに存在します diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf index 82099fd9d7..40727f04b8 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf @@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules: - Member '{0}' is already exist in the base class - 멤버 '{0}'이(가) 기본 클래스에 이미 있습니다. + Member '{0}' already exists in the base class + 멤버 '{0}'이(가) 기본 클래스에 이미 있습니다. diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf index f3d8ba95b9..17575fcd40 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf @@ -287,8 +287,8 @@ Typ deklarujący te metody powinien również przestrzegać następujących regu - Member '{0}' is already exist in the base class - Element członkowski „{0}” już istnieje w klasie bazowej + Member '{0}' already exists in the base class + Element członkowski „{0}” już istnieje w klasie bazowej diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf index 07c3b8901e..c28f06456d 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf @@ -287,8 +287,8 @@ O tipo que declara esses métodos também deve respeitar as seguintes regras: - Member '{0}' is already exist in the base class - O membro "{0}" já existe na classe base + Member '{0}' already exists in the base class + O membro "{0}" já existe na classe base diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf index fcfe3418b3..4754573dc2 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf @@ -291,8 +291,8 @@ The type declaring these methods should also respect the following rules: - Member '{0}' is already exist in the base class - Элемент "{0}" уже существует в базовом классе + Member '{0}' already exists in the base class + Элемент "{0}" уже существует в базовом классе diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf index 5d11ebcb46..cf27b7fe90 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf @@ -287,8 +287,8 @@ Bu yöntemleri bildiren tipin ayrıca aşağıdaki kurallara uyması gerekir: - Member '{0}' is already exist in the base class - Üye '{0}' zaten temel sınıfta var + Member '{0}' already exists in the base class + Üye '{0}' zaten temel sınıfta var diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf index b2645ab19c..7fd1291ea8 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf @@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules: - Member '{0}' is already exist in the base class - 基类中已存在成员“{0}” + Member '{0}' already exists in the base class + 基类中已存在成员“{0}” diff --git a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf index bde0377e6c..81de8f35f2 100644 --- a/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf +++ b/src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf @@ -287,8 +287,8 @@ The type declaring these methods should also respect the following rules: - Member '{0}' is already exist in the base class - 成員 '{0}' 已存在於基類中 + Member '{0}' already exists in the base class + 成員 '{0}' 已存在於基類中 diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs b/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs index 71458475d9..9f3e51de07 100644 --- a/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs +++ b/test/UnitTests/MSTest.Analyzers.UnitTests/DoNotUseShadowingAnalyzerTests.cs @@ -48,6 +48,94 @@ public void Method() { } await VerifyCS.VerifyAnalyzerAsync(code); } + public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButBothArePrivate_NoDiagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + public class BaseClass + { + private void Method() { } + } + + [TestClass] + public class DerivedClass : BaseClass + { + private void Method() { } + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButBaseIsPrivate_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + public class BaseClass + { + private void Method() { } + } + + [TestClass] + public class DerivedClass : BaseClass + { + public void [|Method|]() { } + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButDerivedClassIsPrivate_Diagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + public class BaseClass + { + public void Method() { } + } + + [TestClass] + public class DerivedClass : BaseClass + { + private void [|Method|]() { } + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + + public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_ButOneIsGeneric_NoDiagnostic() + { + string code = """ + using Microsoft.VisualStudio.TestTools.UnitTesting; + using System; + [TestClass] + public class BaseTest + { + protected TObject CreateObject() + { + throw new NotImplementedException(); + } + } + + [TestClass] + public class ExtendedTest : BaseTest + { + private SomeType CreateObject() + { + throw new NotImplementedException(); + } + } + + public class SomeType + { + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); + } + public async Task WhenTestClassHaveSameMethodAsBaseClassMethod_WithParameters_Diagnostic() { string code = """