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 classDo 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 = """