-
Notifications
You must be signed in to change notification settings - Fork 292
Rework MSTEST0016 message and description #7258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7a364d4
8fd8816
e356ac0
38168bf
074135e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,9 +32,13 @@ public sealed class TestClassShouldHaveTestMethodAnalyzer : DiagnosticAnalyzer | |
| DiagnosticSeverity.Info, | ||
| isEnabledByDefault: true); | ||
|
|
||
| /// <inheritdoc cref="Resources.TestClassShouldHaveTestMethodMessageFormat_BaseClassHasAssemblyAttributes" /> | ||
| public static readonly DiagnosticDescriptor TestClassShouldHaveTestMethodRuleBaseClassHasAssemblyAttributes = TestClassShouldHaveTestMethodRule | ||
| .WithMessage(new LocalizableResourceString(nameof(Resources.TestClassShouldHaveTestMethodMessageFormat_BaseClassHasAssemblyAttributes), Resources.ResourceManager, typeof(Resources))); | ||
|
|
||
| /// <inheritdoc /> | ||
| public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } | ||
| = ImmutableArray.Create(TestClassShouldHaveTestMethodRule); | ||
| = ImmutableArray.Create(TestClassShouldHaveTestMethodRule, TestClassShouldHaveTestMethodRuleBaseClassHasAssemblyAttributes); | ||
|
|
||
| /// <inheritdoc /> | ||
| public override void Initialize(AnalysisContext context) | ||
|
|
@@ -78,10 +82,13 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo | |
| return; | ||
| } | ||
|
|
||
| bool hasAssemblyAttribute = false; | ||
| bool hasAssemblyAttributeInCurrentClass = false; | ||
| bool hasAssemblyAttributeInBaseClass = false; | ||
| INamedTypeSymbol? baseClassWithAssemblyAttribute = null; | ||
| bool hasTestMethod = false; | ||
|
|
||
| INamedTypeSymbol? currentType = classSymbol; | ||
| bool isCurrentClass = true; | ||
| do | ||
| { | ||
| foreach (ISymbol classMember in currentType.GetMembers()) | ||
|
|
@@ -98,18 +105,44 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo | |
| || SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, globalTestInitializeAttributeSymbol) | ||
| || SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, globalTestCleanupAttributeSymbol)) | ||
| { | ||
| hasAssemblyAttribute = true; | ||
| if (isCurrentClass) | ||
| { | ||
| hasAssemblyAttributeInCurrentClass = true; | ||
| } | ||
| else | ||
| { | ||
| hasAssemblyAttributeInBaseClass = true; | ||
| baseClassWithAssemblyAttribute ??= currentType; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| currentType = currentType.BaseType; | ||
| isCurrentClass = false; | ||
| } | ||
| while (currentType is not null); | ||
|
|
||
| if (!hasTestMethod && (!classSymbol.IsStatic || (classSymbol.IsStatic && !hasAssemblyAttribute))) | ||
| if (hasTestMethod) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // Static class with assembly attributes in the current class is valid | ||
| if (classSymbol.IsStatic && hasAssemblyAttributeInCurrentClass) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // Non-static class that inherits assembly attributes from base class - suggest making it static | ||
| if (!classSymbol.IsStatic && hasAssemblyAttributeInBaseClass && baseClassWithAssemblyAttribute is not null) | ||
| { | ||
| context.ReportDiagnostic(classSymbol.CreateDiagnostic(TestClassShouldHaveTestMethodRule, classSymbol.Name)); | ||
| context.ReportDiagnostic(classSymbol.CreateDiagnostic(TestClassShouldHaveTestMethodRuleBaseClassHasAssemblyAttributes, classSymbol.Name, baseClassWithAssemblyAttribute.Name)); | ||
|
|
||
| return; | ||
| } | ||
|
Comment on lines
+137
to
143
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if this is really addressing the original reported complaint. Per the description in the linked DC ticket, I think a repro would be something like this: [TestClass]
public abstract class TestClass
{
[AssemblyInitialize]
public static void M(TestContext _) { }
}So, asm init is in the same class being analyzed. Given that the class doesn't have any non-static members, the correct action user needs to take is to mark the class A different scenario to consider in this case is when the abstract class have other non-static members. In this case, we might have two options:
|
||
|
|
||
| // All other cases: class without test methods | ||
| context.ReportDiagnostic(classSymbol.CreateDiagnostic(TestClassShouldHaveTestMethodRule, classSymbol.Name)); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.