Skip to content

Add MSTEST0070 analyzer validating [MemberCondition] member references#9076

Open
Evangelink wants to merge 10 commits into
mainfrom
evangelink/issue-9070-condition-analyzer
Open

Add MSTEST0070 analyzer validating [MemberCondition] member references#9076
Evangelink wants to merge 10 commits into
mainfrom
evangelink/issue-9070-condition-analyzer

Conversation

@Evangelink

@Evangelink Evangelink commented Jun 12, 2026

Copy link
Copy Markdown
Member

Follow-up to #9071 (per design review).

Summary

Adds MSTEST0070 — MemberConditionShouldBeValidAnalyzer, which catches at build time the same errors that MemberConditionAttribute.IsConditionMet throws at runtime, so typos and refactors don''t silently break test gating.

This is the analyzer counterpart called out as a follow-up in #9071 and addresses the user feedback "add an analyzer to detect if the member targets (or type detected) is invalid".

⚠️ Stacked on top of #9071. This branch is rebased on evangelink/issue-9070-condition-attribute, so the diff currently includes commits from that PR. Once #9071 merges, GitHub will rebase the diff to only show the analyzer-specific changes.

Diagnostics

One diagnostic is produced per invalid member name on each [MemberCondition] attribute.

Rule Condition
MemberNotFoundRule The named member doesn''t exist on the type.
MemberNotPublicRule Member is not public.
MemberNotStaticRule Member is not static.
MemberWrongKindRule Member is an event, nested type, or other unsupported kind.
MemberWrongReturnTypeRule Property / field / method doesn''t return bool.
MethodHasParametersRule Referenced method has parameters.
PropertyNotReadableRule Property has no public getter (write-only).

All seven diagnostics share id MSTEST0070 with different message formats, matching how MSTEST0018 (DynamicData) is structured.

Example

public static class Conditions
{
    public static bool IsTrue => true;
    public static int NotBool => 0;
    public static bool WithParam(int x) => x > 0;
    internal static bool InternalIsTrue => true;
}

[TestClass]
public class MyTests
{
    [MemberCondition(typeof(Conditions), "Mispelled")]                  // MSTEST0070: cannot be found
    [MemberCondition(typeof(Conditions), nameof(Conditions.NotBool))]   // MSTEST0070: must return ''bool''
    [MemberCondition(typeof(Conditions), nameof(Conditions.WithParam))] // MSTEST0070: must be parameterless
    [MemberCondition(typeof(Conditions),
                     nameof(Conditions.InternalIsTrue))]                // MSTEST0070: must be ''public''
    [TestMethod]
    public void MyTest() { }
}

Coverage

  • Fires on both test methods and test classes (the attribute is AttributeUsage(Class | Method)).
  • Validates every member name passed to the attribute — the simple (Type, string) ctor, the params string[] overload, and the ConditionMode-prefixed overloads.
  • Stacked [MemberCondition] attributes are each validated independently.
  • Inherited public static members are recognized (walks BaseType chain), matching BindingFlags.Public | Static | FlattenHierarchy.
  • The resolution order matches the runtime (property → field → method), so if a property and method share a name only the property is validated — consistent with what would actually be invoked.

Tests

18 tests in test/UnitTests/MSTest.Analyzers.UnitTests/MemberConditionShouldBeValidAnalyzerTests.cs:

  • Valid: public static bool property / field / parameterless method, inherited public static member
  • Invalid: missing, non-public (internal), instance property, instance field, non-bool property, non-bool field, non-bool method, method with parameters, write-only property, event
  • Composition: multiple invalid member names in one attribute (each reported), multiple [MemberCondition] attributes on one method (each validated), ConditionMode.Exclude ctor overload, attribute on class target

All 18 pass on net8.0 (and the project''s full 1244-test suite stays green).

Files touched

  • src/Analyzers/MSTest.Analyzers/MemberConditionShouldBeValidAnalyzer.cs
  • test/UnitTests/MSTest.Analyzers.UnitTests/MemberConditionShouldBeValidAnalyzerTests.cs
  • ✏️ src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs (added MemberConditionShouldBeValidRuleId = "MSTEST0070")
  • ✏️ src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs (added MemberConditionAttribute entry, sorted alphabetically)
  • ✏️ src/Analyzers/MSTest.Analyzers/Resources.resx + 13 .xlf files
  • ✏️ src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md

Notes for reviewers

  • Severity is Warning, enabled by default — matches MSTEST0018 (DynamicData) which solves the same class of problem. Happy to downgrade to Info if you''d prefer a softer rollout.
  • Documentation URL https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0070 will be authored as a separate dotnet/docs PR after this merges.
  • No code fix provider — the right fix depends on user intent (rename member? change accessibility? change member kind?). Keeping it diagnostic-only matches DynamicDataShouldBeValidAnalyzer.

Evangelink and others added 3 commits June 12, 2026 14:03
Adds a new `Microsoft.VisualStudio.TestTools.UnitTesting.ConditionAttribute`

deriving from `ConditionBaseAttribute` that evaluates one or more static

`bool` members (property, field, or parameterless method) referenced by

`Type` + member name to decide whether a test class or test method runs.

This mirrors the `[ConditionalFact]` / `[ConditionalTheory]` pattern from

`Microsoft.DotNet.XUnitExtensions` used heavily by dotnet/runtime, dotnet/sdk,

and dotnet/aspnetcore, removing the need to define a one-off

`ConditionBaseAttribute` subclass per condition (e.g. `Is64BitProcessCondition`).

Behavior:

- Multiple member names within a single attribute are AND-combined.

- Each attribute instance gets a unique `GroupName` derived from the type and

  members, so stacking multiple `[Condition]` attributes ANDs them across

  instances (matching xUnit's usage pattern).

- `ConditionMode.Exclude` flips the semantics (skip when the condition holds).

- Member resolution looks up public/non-public `static bool` property, field,

  or parameterless method (in that order). On any resolution failure

  (missing, non-bool, non-static, instance-only, or method with parameters),

  `IsConditionMet` throws `InvalidOperationException` so the test fails

  rather than silently skipping -- avoiding the classic "typo in member

  name silently disables the test" pitfall.

Provides four CLS-friendly ctor overloads (`(Type, string)`,

`(ConditionMode, Type, string)` plus `params`-array variants marked

`[CLSCompliant(false)]`). Uses `DynamicallyAccessedMembers` annotations for

trimming/AOT correctness. Targets all existing TFMs (netstandard2.0, net462,

net8.0, net9.0).

Adds 23 unit tests in `TestFramework.UnitTests` covering argument validation,

member resolution variants (public/non-public, property/field/method),

AND-semantics, `ConditionMode.Exclude`, error messages, and `GroupName`

uniqueness.

Fixes #9070.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per design review, restrict the resolver to `BindingFlags.Public | Static`

(was `Public | NonPublic | Static`).

Rationale:

- The `conditionType` is effectively acting as a public API surface for the

  condition. Non-public members of another type don't belong in that contract.

- Slimmer `DynamicallyAccessedMembers` annotations for trim/AOT (3 flags

  instead of 6) -- only public properties, fields, and methods are preserved.

- Matches xUnit's `MemberData` resolution which defaults to `Public | Static`.

- Avoids surprises with `InternalsVisibleTo` when the condition type lives in

  a different assembly than the test.

Error messages updated to say "public static bool"; XML docs aligned.

Test `IsConditionMet_NonPublicStaticProperty_IsResolved` flipped to

`IsConditionMet_NonPublicStaticProperty_ThrowsInvalidOperation`. All 23 tests

still pass on net8.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…emberNames

- Wrap `_conditionMemberNames` in a cached `ReadOnlyCollection<string>` so
  `ConditionMemberNames` can no longer be downcast to `string[]` and mutated.
- In `EvaluateMember`, reject indexer properties (those with index parameters)
  alongside non-bool/non-readable properties so they consistently surface as
  `InvalidOperationException` instead of `TargetParameterCountException`.
  Use `GetGetMethod(nonPublic: true)` to reliably detect missing getters.
- Add `ConditionMemberNames_CannotBeDowncastToMutableArray` test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

This comment has been minimized.

Amaury Levé and others added 3 commits June 12, 2026 14:57
…nd tests

- `IsConditionMet` now resolves each member once and caches a `Func<bool>`
  delegate. Subsequent evaluations skip the per-call `GetProperty` /
  `GetField` / `GetMethod` lookups (~3xN reflection lookups per access).
- `GroupName` now includes `Mode` so two `[Condition]` attributes with the
  same type/members but opposite modes no longer share a group (previously they
  would silently OR-combine and the test would always run).
- `IsConditionMet` uses `All` for the AND short-circuit, addressing the
  CodeQL note.
- Added `IsConditionMet_ParameterlessMethodWithNonBoolReturn_ThrowsInvalidOperation`,
  `GroupName_DifferentMode_AreDifferentGroups`, and tightened
  `IgnoreMessage_Exclude_HasExpectedText` to also assert the type FullName
  (matching the Include variant).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ssary [CLSCompliant(false)]

- The previous name was too generic and clashed conceptually with the existing ConditionBaseAttribute / OSConditionAttribute / CIConditionAttribute family. MemberConditionAttribute better reflects that the attribute targets a static member by name.

- [CLSCompliant(false)] was not needed on the params string[] overloads: the existing DataRowAttribute(params object?[]?) and DynamicDataAttribute(string, params object?[]) constructors compile cleanly without it in the same CLS-compliant assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add `BindingFlags.FlattenHierarchy` to the member lookup so
  `[MemberCondition(typeof(Derived), nameof(Base.SomeFlag))]` resolves the
  inherited static member via the derived type, matching how C# allows accessing
  public static base members through a derived type name.
- Tighten the property validation to require a public getter
  (`GetGetMethod(nonPublic: false)`). A public static property with a private
  getter doesn't satisfy the documented `public static bool readable property`
  contract and isn't guaranteed to be preserved by the `PublicProperties`
  trimming annotation on `ConditionType`.
- Add `IsConditionMet_InheritedStaticProperty_ResolvesViaDerivedType` and
  `IsConditionMet_PropertyWithPrivateGetter_ThrowsInvalidOperation` tests
  (plus matching fixture types).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from evangelink/issue-9070-condition-attribute to main June 12, 2026 15:04
Adds `MemberConditionShouldBeValidAnalyzer` (MSTEST0070) which catches at build time the same errors that `MemberConditionAttribute.IsConditionMet` throws at runtime, so typos and refactors don't silently break test gating.

Rules emitted (one diagnostic per member name in the attribute):

- MemberNotFoundRule -- the named member doesn't exist on the type
- MemberNotPublicRule -- member is not public
- MemberNotStaticRule -- member is not static
- MemberWrongKindRule -- member is an event/nested type/etc.
- MemberWrongReturnTypeRule -- property/field/method doesn't return bool
- MethodHasParametersRule -- referenced method has parameters
- PropertyNotReadableRule -- property has no public getter

The analyzer fires on any symbol carrying [MemberCondition] (test class or test method), walks each constructor argument, validates every member name, and matches the runtime resolution order (property -> field -> method) including inherited public static members.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 12, 2026 15:40
@Evangelink Evangelink force-pushed the evangelink/issue-9070-condition-analyzer branch from 53875bf to 4d9c906 Compare June 12, 2026 15:40
@Evangelink Evangelink changed the title Add MSTEST0070 analyzer validating [Condition] member references Add MSTEST0070 analyzer validating [MemberCondition] member references Jun 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds the new [MemberCondition] feature end-to-end in the MSTest ecosystem: a runtime attribute (MemberConditionAttribute) plus the follow-up analyzer (MSTEST0070) that validates referenced members at build time, including resources/release-notes and unit tests.

Changes:

  • Introduces MemberConditionAttribute (public API) that gates tests on one or more public static bool members (property/field/parameterless method), with runtime validation and caching.
  • Adds MSTEST0070 (MemberConditionShouldBeValidAnalyzer) to validate [MemberCondition] member references at compile time, with localized strings and analyzer release metadata.
  • Adds unit tests for the runtime attribute and analyzer behavior.
Show a summary per file
File Description
test/UnitTests/TestFramework.UnitTests/Attributes/MemberConditionAttributeTests.cs Adds runtime behavior/validation tests for MemberConditionAttribute.
test/UnitTests/MSTest.Analyzers.UnitTests/MemberConditionShouldBeValidAnalyzerTests.cs Adds analyzer tests for MSTEST0070 diagnostics.
src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt Records the new public API surface for MemberConditionAttribute.
src/TestFramework/TestFramework/Attributes/TestMethod/MemberConditionAttribute.cs Implements the new MemberConditionAttribute runtime behavior.
src/Analyzers/MSTest.Analyzers/MemberConditionShouldBeValidAnalyzer.cs Implements the MSTEST0070 analyzer for validating [MemberCondition] arguments.
src/Analyzers/MSTest.Analyzers/Resources.resx Adds localized resource strings for MSTEST0070 title/description/messages.
src/Analyzers/MSTest.Analyzers/AnalyzerReleases.Unshipped.md Documents the new MSTEST0070 rule in analyzer release notes.
src/Analyzers/MSTest.Analyzers/Helpers/DiagnosticIds.cs Adds the new diagnostic ID constant MSTEST0070.
src/Analyzers/MSTest.Analyzers/Helpers/WellKnownTypeNames.cs Adds MemberConditionAttribute to well-known type name constants.
src/Analyzers/MSTest.Analyzers/xlf/Resources.cs.xlf Propagates new MSTEST0070 strings to Czech localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.de.xlf Propagates new MSTEST0070 strings to German localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.es.xlf Propagates new MSTEST0070 strings to Spanish localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.fr.xlf Propagates new MSTEST0070 strings to French localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.it.xlf Propagates new MSTEST0070 strings to Italian localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.ja.xlf Propagates new MSTEST0070 strings to Japanese localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.ko.xlf Propagates new MSTEST0070 strings to Korean localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.pl.xlf Propagates new MSTEST0070 strings to Polish localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.pt-BR.xlf Propagates new MSTEST0070 strings to Portuguese (Brazil) localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.ru.xlf Propagates new MSTEST0070 strings to Russian localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.tr.xlf Propagates new MSTEST0070 strings to Turkish localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hans.xlf Propagates new MSTEST0070 strings to Chinese (Simplified) localization file.
src/Analyzers/MSTest.Analyzers/xlf/Resources.zh-Hant.xlf Propagates new MSTEST0070 strings to Chinese (Traditional) localization file.

Copilot's findings

  • Files reviewed: 22/22 changed files
  • Comments generated: 3

Comment on lines +170 to +174
// Match the runtime resolution preference: property → field → method (first match wins).
ISymbol? selected =
candidates.FirstOrDefault(s => s.Kind == SymbolKind.Property)
?? candidates.FirstOrDefault(s => s.Kind == SymbolKind.Field)
?? candidates.FirstOrDefault(s => s.Kind == SymbolKind.Method);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1fccdc3. ValidateMember now first tries to find a candidate that the runtime would actually bind to (Public + Static + FlattenHierarchy, ordinary parameterless methods only), and only falls back to the previous first-by-kind heuristic when no such candidate exists. Added WhenMethodHasParameterlessAndParameterizedOverloads_PicksParameterless_NoDiagnostic and WhenDerivedHasInstanceMemberShadowingBaseStatic_PicksBaseStatic_NoDiagnostic covering both scenarios you flagged. Review reply handled.

Comment on lines +236 to +240
if (property.GetMethod is null || property.GetMethod.DeclaredAccessibility != Accessibility.Public)
{
context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(PropertyNotReadableRule, typeName, memberName));
return;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1fccdc3. ValidateProperty now rejects indexer properties (property.IsIndexer) up front with MemberWrongKindRule, matching the runtime InvalidOperationException for properties with index parameters. The runtime-resolution filter in ValidateMember also already excludes indexers when looking for the preferred candidate. Review reply handled.

Comment on lines +13 to +17
[TestMethod]
public async Task WhenMemberIsValidPublicStaticBoolProperty_NoDiagnostic()
{
string code = """
using Microsoft.VisualStudio.TestTools.UnitTesting;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 2 of the 3 cases you suggested in 1fccdc3: WhenMethodHasParameterlessAndParameterizedOverloads_PicksParameterless_NoDiagnostic and WhenDerivedHasInstanceMemberShadowingBaseStatic_PicksBaseStatic_NoDiagnostic. Skipped the explicit indexer test since C# 13 static indexers (public static bool this[int]) are rare/new and the indexer path is now exercised end-to-end by ValidateProperty's IsIndexer guard (which would surface MSTEST0070 via MemberWrongKindRule for any indexer). Happy to add it on follow-up if you'd like coverage proof. Review reply handled.

@Evangelink

This comment has been minimized.

…dexers

- `MemberConditionShouldBeValidAnalyzer`: candidate selection in
  `ValidateMember` no longer just picks "first by Kind". It now first tries
  to find a candidate that the runtime would actually bind to
  (`GetProperty`/`GetField`/`GetMethod` with `Public | Static |
  FlattenHierarchy`, methods restricted to `MethodKind.Ordinary` and
  parameterless), and only falls back to the previous first-by-kind heuristic
  when no such candidate exists. This fixes:
    * Overloaded methods where a parameterless overload coexists with
      parameterized ones (runtime binds to the parameterless one).
    * An instance member on a derived type shadowing a `public static` base
      member with the same name (runtime resolves via `FlattenHierarchy` to
      the base static).
  Behaviour for "no runtime-valid candidate" cases is preserved -- the
  fallback still selects a candidate so the more specific diagnostic
  (not-public/not-static/wrong-return-type) is reported.

- `ValidateProperty`: explicitly reject indexer properties
  (`property.IsIndexer`) with `MemberWrongKindRule`, matching the runtime
  `InvalidOperationException` for properties with index parameters. (The
  analyzer was previously silent on this category and would let MSTEST0070
  miss cases that would still throw at runtime.)

- Apply `Where` filter to the `argument.Values` enumeration to address
  the github-code-quality LINQ note and avoid the implicit filtering pattern.

- Tests: add
  `WhenMethodHasParameterlessAndParameterizedOverloads_PicksParameterless_NoDiagnostic`
  and
  `WhenDerivedHasInstanceMemberShadowingBaseStatic_PicksBaseStatic_NoDiagnostic`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 12, 2026 16:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 19/19 changed files
  • Comments generated: 3

Comment on lines 31 to 35
public const string MicrosoftVisualStudioTestToolsUnitTestingInheritanceBehavior = "Microsoft.VisualStudio.TestTools.UnitTesting.InheritanceBehavior";
public const string MicrosoftVisualStudioTestToolsUnitTestingMemberConditionAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.MemberConditionAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingOwnerAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.OwnerAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingParallelizeAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.ParallelizeAttribute";
public const string MicrosoftVisualStudioTestToolsUnitTestingPriorityAttribute = "Microsoft.VisualStudio.TestTools.UnitTesting.PriorityAttribute";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fc21eee -- moved MicrosoftVisualStudioTestToolsUnitTestingOSConditionAttribute to its correct alphabetical position (between ...MemberConditionAttribute and ...OwnerAttribute). Review reply handled.

Comment on lines +122 to +125
if (argument.Kind == TypedConstantKind.Type && argument.Value is INamedTypeSymbol typeValue)
{
conditionType = typeValue;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fc21eee. AnalyzeAttribute now accepts any ITypeSymbol for the condition type. When the captured type isn't an INamedTypeSymbol (e.g. typeof(int[])), we report MSTEST0070 (MemberNotFoundRule) for each provided member name using ToDisplayString(MinimallyQualifiedFormat) for the type label, so the user sees the same diagnostic at edit time that the runtime would throw at first access. Added WhenConditionTypeIsArrayType_MemberNotFound covering [MemberCondition(typeof(int[]), "AnyName")]. Review reply handled.

…or non-named types, rename test

- `WellKnownTypeNames.cs`: move `MicrosoftVisualStudioTestToolsUnitTestingOSConditionAttribute`
  to its alphabetical position between `Member...` and `Owner...` so the file
  matches its "Keep sorted alphabetically" header.

- `MemberConditionShouldBeValidAnalyzer.AnalyzeAttribute`: accept any
  `ITypeSymbol` for the condition type rather than only `INamedTypeSymbol`.
  Non-named types (arrays, pointers, function pointers) can't carry user-declared
  static bool members and the runtime throws `InvalidOperationException`; the
  analyzer now surfaces that as MSTEST0070 (`MemberNotFoundRule`) instead of
  silently skipping the attribute. Uses `ToDisplayString(MinimallyQualifiedFormat)`
  for the type name when `conditionType.Name` is empty (as it is for
  `IArrayTypeSymbol`).

- Rename `WhenStaticFieldIsInstance_MemberNotStatic` to
  `WhenFieldIsInstance_MemberNotStatic` -- the field under test is an instance
  field, not a static one, so the original name was misleading.

- Add `WhenConditionTypeIsArrayType_MemberNotFound` test covering
  `[MemberCondition(typeof(int[]), "AnyName")]`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member Author

🧪 Test quality grade — PR #9076

21 new test methods graded across 1 new file (MemberConditionShouldBeValidAnalyzerTests); every method received A (90–100). The suite covers all 6 MSTEST0070 diagnostic rules plus positive (no-diagnostic) paths and three non-obvious edge cases (inherited members, overload resolution, and instance-member shadowing). All assertions use VerifyCS.VerifyAnalyzerAsync with exact rule IDs, location markers, and message arguments. No improvements identified.

ΔTestGradeBandNotes
newMemberConditionShouldBeValidAnalyzerTests.
WhenAdditionalMembersAreInvalid_
AllReported
A90–100Asserts two distinct diagnostics, confirming the analyzer iterates all member names independently.
newMemberConditionShouldBeValidAnalyzerTests.
WhenAttributeIsOnTestClass_
StillValidated
A90–100Confirms attribute validation fires on TestClass targets, not only TestMethod; args verified.
newMemberConditionShouldBeValidAnalyzerTests.
WhenConditionTypeIsArrayType_
MemberNotFound
A90–100Covers IArrayTypeSymbol edge case with explanatory comment; precise diagnostic args asserted.
newMemberConditionShouldBeValidAnalyzerTests.
WhenDerivedHasInstanceMemberShadowingBaseStatic_
PicksBaseStatic_
NoDiagnostic
A90–100Covers FlattenHierarchy/shadowing edge case; comment documents the runtime binding semantics.
newMemberConditionShouldBeValidAnalyzerTests.
WhenExplicitConditionMode_
StillValidated
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenFieldIsInstance_
MemberNotStatic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenFieldIsNonBool_
MemberWrongReturnType
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenInheritedPublicStaticMember_
NoDiagnostic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberDoesNotExist_
MemberNotFound
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberIsEvent_
MemberWrongKind
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberIsInternal_
MemberNotPublic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberIsValidPublicStaticBoolField_
NoDiagnostic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberIsValidPublicStaticBoolMethod_
NoDiagnostic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMemberIsValidPublicStaticBoolProperty_
NoDiagnostic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMethodHasParameterlessAndParameterizedOverloads_
PicksParameterless_
NoDiagnostic
A90–100Covers overload-resolution edge case; comment explains Type.GetMethod(EmptyTypes) binding.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMethodHasParameters_
MethodHasParameters
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMethodReturnsNonBool_
MemberWrongReturnType
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenMultipleConditionAttributes_
EachValidated
A90–100Asserts both attributes are validated independently with separate location markers and args.
newMemberConditionShouldBeValidAnalyzerTests.
WhenPropertyIsInstance_
MemberNotStatic
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenPropertyIsWriteOnly_
PropertyNotReadable
A90–100No issues found.
newMemberConditionShouldBeValidAnalyzerTests.
WhenPropertyReturnsNonBool_
MemberWrongReturnType
A90–100No issues found.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 315.7 AIC · ⌖ 13.7 AIC · [◷]( · )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants