Skip to content

Commit 02c9fe1

Browse files
Fix namespace matching and remove TypeKind.Error fallback in IsTestMethod
- Fix StartsWith bug: 'Xunit'.StartsWith('Xunit') would also match 'Xunit2Extensions' etc. Now uses exact match or dotted prefix check to prevent false positive suppression. - Remove s_commonTestAttributeNames fallback: now that DiagnosticVerifier adds real framework assembly references to every test compilation, TypeKind.Error can no longer occur in tests. The fallback was also risky in production — any user-defined [Test] or [Fact] attribute in an unresolved assembly would incorrectly suppress INTL0003. - Rename s_testFrameworkNamespaces -> _TestFrameworkNamespaces to comply with INTL0001.
1 parent 267e87f commit 02c9fe1

1 file changed

Lines changed: 8 additions & 31 deletions

File tree

IntelliTect.Analyzer/IntelliTect.Analyzer/Analyzers/NamingMethodPascal.cs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,17 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context)
105105
context.ReportDiagnostic(diagnostic);
106106
}
107107

108-
// Test framework namespaces — any method decorated with an attribute from these namespaces
109-
// is considered a test method and exempt from PascalCase validation.
108+
// Test framework namespaces — any method decorated with an attribute whose namespace
109+
// exactly matches or starts with one of these is exempt from PascalCase validation.
110110
// To add a new framework, append its root namespace here and update TestFrameworkReferences.cs.
111-
private static readonly string[] s_testFrameworkNamespaces =
111+
private static readonly string[] _TestFrameworkNamespaces =
112112
[
113113
"Xunit", // xUnit (namespace is "Xunit", not "XUnit")
114114
"NUnit.Framework", // NUnit
115115
"Microsoft.VisualStudio.TestTools.UnitTesting", // MSTest
116116
"TUnit.Core" // TUnit
117117
];
118118

119-
// Fallback attribute names for compilations without framework assembly references.
120-
// Only used when the attribute type is unresolved (TypeKind.Error).
121-
private static readonly string[] s_commonTestAttributeNames =
122-
[
123-
"TestMethod", "TestMethodAttribute", // MSTest
124-
"Fact", "FactAttribute", // xUnit
125-
"Theory", "TheoryAttribute", // xUnit
126-
"Test", "TestAttribute", // NUnit / TUnit
127-
"TestCase", "TestCaseAttribute", // NUnit
128-
"TestCaseSource", "TestCaseSourceAttribute" // NUnit
129-
];
130-
131119
private static bool IsTestMethod(IMethodSymbol methodSymbol)
132120
{
133121
ImmutableArray<AttributeData> attributes = methodSymbol.GetAttributes();
@@ -138,22 +126,11 @@ private static bool IsTestMethod(IMethodSymbol methodSymbol)
138126
return false;
139127
}
140128

141-
// Check namespace first — works whenever the compilation includes real framework references.
142-
string containingNamespace = attribute.AttributeClass.ContainingNamespace?.ToDisplayString();
143-
if (containingNamespace != null &&
144-
s_testFrameworkNamespaces.Any(ns => containingNamespace.StartsWith(ns, StringComparison.Ordinal)))
145-
{
146-
return true;
147-
}
148-
149-
// Fallback: check by name only for unresolved types (missing assembly reference in compilation).
150-
// Gated on TypeKind.Error to avoid false negatives for user-defined attributes with the same names.
151-
if (attribute.AttributeClass.TypeKind == TypeKind.Error)
152-
{
153-
return s_commonTestAttributeNames.Contains(attribute.AttributeClass.Name);
154-
}
155-
156-
return false;
129+
string? containingNamespace = attribute.AttributeClass.ContainingNamespace?.ToDisplayString();
130+
return containingNamespace != null &&
131+
_TestFrameworkNamespaces.Any(ns =>
132+
string.Equals(containingNamespace, ns, StringComparison.Ordinal) ||
133+
containingNamespace.StartsWith(ns + ".", StringComparison.Ordinal));
157134
});
158135
}
159136
}

0 commit comments

Comments
 (0)