From 5efc38a23ee24b7b0d4047690772922061c8e267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 17 Jul 2026 08:51:35 +0200 Subject: [PATCH] test: assert diagnostics by wildcard so failures show the actual output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsTrue()` collapses the diagnostics to a bool before the assertion sees them, so a failure reports only `expected true, but it was false` and says nothing about what the generator actually produced. Asserting on the collection instead keeps the diagnostics in the failure message: ``` Expected that result.Diagnostics contains "*AWT999*" as wildcard at least once, but it did not contain it Collection: [ "(9,2): error AWT101: 'MyCode.Service' cannot be resolved: 'MyCode.Service' requires 'MyCode.IMissing…" ] ``` Converts all 192 sites across 55 files: `.IsTrue()` becomes `Contains("*AWT101*").AsWildcard()` and `.IsFalse()` becomes `DoesNotContain("*AWT101*").AsWildcard()`. Two shapes needed more than a mechanical rewrite. Three predicates combining terms with `&&` flatten to an ordered wildcard (`d.Contains("AWT120") && d.Contains("Repository") && d.Contains("Connection")` becomes `"*AWT120*Repository*Connection*"`); `&&` is order-independent and a wildcard is not, so these tightened slightly, and they pass. Three `.IsFalse()` predicates combining terms with `||` split into two `DoesNotContain` assertions each, since negating a disjunction distributes over both terms. No behavioral change: the same 586 tests pass before and after. --- .../CrossAssemblyModuleTests.cs | 2 +- ...DiagnosticTests.Awt101MissingDependency.cs | 4 +- ...sticTests.Awt113RuntimeArgumentMismatch.cs | 4 +- ...nosticTests.Awt114ParameterizedLifetime.cs | 6 +-- ...icTests.Awt115ParameterizedRequiresFunc.cs | 6 +-- .../DiagnosticTests.Awt117DuplicateKey.cs | 6 +-- ....Awt119Awt120SynchronousAsyncResolution.cs | 2 +- .../DiagnosticTests.Awt123Awt124Decorator.cs | 18 ++++----- .../DiagnosticTests.Awt125OpenGenericArity.cs | 4 +- ...nosticTests.Awt126OpenGenericConstraint.cs | 10 ++--- ...nosticTests.Awt127OpenGenericNotUnbound.cs | 6 +-- ...agnosticTests.Awt128OpenGenericRemapped.cs | 4 +- ...gnosticTests.Awt129OpenGenericRecursion.cs | 4 +- .../DiagnosticTests.Awt130Composite.cs | 4 +- .../DiagnosticTests.Awt131Composite.cs | 6 +-- .../DiagnosticTests.Awt132Composite.cs | 2 +- .../DiagnosticTests.Awt133Composite.cs | 6 +-- ...sticTests.Awt136Awt137PropertyInjection.cs | 10 ++--- ...iagnosticTests.Awt138ScanMatchedNothing.cs | 4 +- ...Tests.Awt139ScanNoImplementedInterfaces.cs | 4 +- ...Tests.Awt140ScanAssemblyHasNoCandidates.cs | 2 +- .../DiagnosticTests.Awt141ScanMatchSkipped.cs | 10 ++--- ...gnosticTests.Awt142ScanLifetimeConflict.cs | 2 +- ...agnosticTests.Awt143ScanAssembliesEmpty.cs | 4 +- ...ests.Awt144Awt145Awt146DeferredProperty.cs | 38 ++++++++++--------- .../DiagnosticTests.Awt148AmbiguousDefault.cs | 8 ++-- ...ticTests.Awt149Awt150Awt151ModuleImport.cs | 6 +-- .../DiagnosticTests.Awt152NonStaticModule.cs | 6 +-- .../DiagnosticTests.Awt154ScanOnModule.cs | 6 +-- ...gnosticTests.Awt155CrossModuleDuplicate.cs | 10 ++--- ...osticTests.Awt157Awt158OptionalProperty.cs | 14 +++---- ...gnosticTests.Awt164InvalidLifecycleHook.cs | 16 ++++---- ...sticTests.Awt165LifecycleHookOnInstance.cs | 4 +- ...DiagnosticTests.Awt167ContextualBinding.cs | 10 ++--- ...icTests.Awt172ScanFiltersMatchedNothing.cs | 4 +- ...icTests.Awt173ScanExclusionNeverMatched.cs | 2 +- ...ests.Awt174ScanPatternMatchesEverything.cs | 2 +- ...ests.Awt175ContradictingExternalService.cs | 2 +- ...icTests.Awt176UnconsumedExternalService.cs | 6 +-- ...cTests.Awt177Awt178Awt179InjectProperty.cs | 22 +++++------ ...sticTests.Awt182ScanNoMatchingInterface.cs | 4 +- ...nosticTests.Awt183MarkerlessScanInvalid.cs | 6 +-- ...s.Awt184MarkerlessScanRegisteredNothing.cs | 4 +- ...iagnosticTests.Awt185ScanExposesNothing.cs | 2 +- ...s.Awt187ScanAmbiguousMatchingInterfaces.cs | 10 ++--- ...icTests.Awt188ScanInterfaceInaccessible.cs | 2 +- ...iagnosticTests.Awt189HookParameterIsArg.cs | 4 +- ...osticTests.Awt190AmbiguousLifecycleHook.cs | 10 +++-- ...ests.Awt191ReleaseHookDeferredParameter.cs | 10 ++--- ...cTests.Awt192SuppressDisposalOnInstance.cs | 6 +-- .../DiagnosticTests.HookParameterKeyMisuse.cs | 6 +-- .../GeneralTests.cs | 26 ++++++------- .../ModuleTests.cs | 2 +- .../OpenGenericDecoratorTests.cs | 12 +++--- .../PropertyInjectionTests.cs | 4 +- 55 files changed, 200 insertions(+), 194 deletions(-) diff --git a/Tests/Awaiten.SourceGenerators.Tests/CrossAssemblyModuleTests.cs b/Tests/Awaiten.SourceGenerators.Tests/CrossAssemblyModuleTests.cs index 6bc9bb9d..62d31251 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/CrossAssemblyModuleTests.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/CrossAssemblyModuleTests.cs @@ -100,7 +100,7 @@ public static partial class MyContainer """); // The metadata module's Default loses to AppModule's (AWT148). With no syntax of its own the diagnostic must fall back to the container's [Import] line. ToString() prefixes the location only when one exists. - await That(result.Diagnostics.Any(d => d.Contains("AWT148"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT148*").AsWildcard() .Because("two Defaults collide across assemblies with nothing stronger to resolve them"); await That(result.Diagnostics).Contains("(*,*): *AWT148*").AsWildcard() .Because("the metadata registration's diagnostic falls back to the container's [Import] location"); diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt101MissingDependency.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt101MissingDependency.cs index 8d797560..8b848458 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt101MissingDependency.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt101MissingDependency.cs @@ -74,9 +74,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("a [FromKey] with no registration under that key is a missing dependency"); - await That(result.Diagnostics.Any(d => d.Contains("AWT101") && d.Contains("key: missing"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT101*key: missing*").AsWildcard() .Because("the missing dependency names the requested key"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt113RuntimeArgumentMismatch.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt113RuntimeArgumentMismatch.cs index 1408d546..cf455274 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt113RuntimeArgumentMismatch.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt113RuntimeArgumentMismatch.cs @@ -29,7 +29,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT113"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT113*").AsWildcard() .Because("the Func requests an int but the [Arg] parameter expects a string"); } @@ -56,7 +56,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT113"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT113*").AsWildcard() .Because("a parameterized service cannot be produced from a Func that supplies no runtime arguments"); await That(result.Diagnostics.Single(d => d.Contains("AWT113"))).Contains("(none)") .Because("an empty runtime-argument list reads as 'none' rather than an empty '()'"); diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt114ParameterizedLifetime.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt114ParameterizedLifetime.cs index befd8cf3..0727f20b 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt114ParameterizedLifetime.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt114ParameterizedLifetime.cs @@ -26,7 +26,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT114"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT114*").AsWildcard() .Because("a parameterized service is built fresh per call, so a singleton lifetime cannot be honored"); } @@ -50,7 +50,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT114"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT114*").AsWildcard() .Because("a scoped lifetime cannot be honored for a per-call parameterized service either"); } @@ -74,7 +74,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT114"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT114*").AsWildcard() .Because("transient is the only lifetime a parameterized service can honor"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt115ParameterizedRequiresFunc.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt115ParameterizedRequiresFunc.cs index 297d0968..0a664902 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt115ParameterizedRequiresFunc.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt115ParameterizedRequiresFunc.cs @@ -28,7 +28,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT115"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT115*").AsWildcard() .Because("a parameterized service cannot be supplied its runtime arguments through a plain dependency"); } @@ -55,7 +55,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT115"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT115*").AsWildcard() .Because("Lazy cannot carry runtime arguments either, so it cannot build a parameterized service"); } @@ -82,7 +82,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT115"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT115*").AsWildcard() .Because("a Func supplies the runtime arguments, so it is the correct way to obtain it"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt117DuplicateKey.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt117DuplicateKey.cs index 18c488fa..49994e9b 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt117DuplicateKey.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt117DuplicateKey.cs @@ -26,7 +26,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT117"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT117*").AsWildcard() .Because("two different implementations claim the same service type and key"); } @@ -50,7 +50,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT117"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT117*").AsWildcard() .Because("several implementations may share one service type under different keys"); } @@ -74,7 +74,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT117"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT117*").AsWildcard() .Because("registering one implementation under several service types with one key is a coalesce, not a conflict"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt119Awt120SynchronousAsyncResolution.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt119Awt120SynchronousAsyncResolution.cs index 9d5f663b..81dac89c 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt119Awt120SynchronousAsyncResolution.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt119Awt120SynchronousAsyncResolution.cs @@ -189,7 +189,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT120") && d.Contains("Repository") && d.Contains("Connection"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT120*Repository*Connection*").AsWildcard() .Because("the diagnostic names the dependency path from the synchronously-resolved service to the async-initialized one"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt123Awt124Decorator.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt123Awt124Decorator.cs index a5c087d9..d340f046 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt123Awt124Decorator.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt123Awt124Decorator.cs @@ -25,7 +25,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT123"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT123*").AsWildcard() .Because("a [Decorate] over a service with no registration has nothing to wrap"); } @@ -50,7 +50,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT124"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT124*").AsWildcard() .Because("a decorator with more than one parameter assignable to the service is ambiguous"); } @@ -75,7 +75,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT124"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT124*").AsWildcard() .Because("a decorator with no parameter assignable to the service cannot receive the inner instance"); } @@ -125,7 +125,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT124"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT124*").AsWildcard() .Because("the inner is the most-derived assignable parameter, so an unrelated `object` sibling is not ambiguous"); } @@ -178,7 +178,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT124"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT124*").AsWildcard() .Because("a [FromKey] parameter is not the chain inner, so the decorator has no parameter to receive it"); } @@ -205,9 +205,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT102") && d.Contains("MyCode.Deco"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT102*MyCode.Deco*").AsWildcard() .Because("the cycle diagnostic must name the real decorator type"); - await That(result.Diagnostics.Any(d => d.Contains("@__dec:"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*@__dec:*").AsWildcard() .Because("the internal synthetic '@__dec:' identity must not leak into user-facing diagnostics"); } @@ -235,9 +235,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT105") && d.Contains("MyCode.Deco"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT105*MyCode.Deco*").AsWildcard() .Because("the captive-dependency diagnostic must name the real decorator type"); - await That(result.Diagnostics.Any(d => d.Contains("@__dec:"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*@__dec:*").AsWildcard() .Because("the internal synthetic '@__dec:' identity must not leak into the captive-dependency diagnostic"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt125OpenGenericArity.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt125OpenGenericArity.cs index 2a78ba24..7428c8c2 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt125OpenGenericArity.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt125OpenGenericArity.cs @@ -25,7 +25,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT125"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT125*").AsWildcard() .Because("the open implementation's arity must match the service's, so a closed service can be re-mapped onto the implementation"); } @@ -50,7 +50,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT125"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT125*").AsWildcard() .Because("the implementation and service both declare one type parameter"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt126OpenGenericConstraint.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt126OpenGenericConstraint.cs index e20a91f7..fea6cc7a 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt126OpenGenericConstraint.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt126OpenGenericConstraint.cs @@ -27,7 +27,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT126"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT126*").AsWildcard() .Because("Repository violates the implementation's where T : class constraint"); } @@ -52,7 +52,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT126"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT126*").AsWildcard() .Because("Order is a reference type, so it satisfies where T : class"); } @@ -80,7 +80,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT126"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT126*").AsWildcard() .Because("a constructed constraint mentioning the type parameter (IComparable) is satisfied after substitution"); } @@ -110,9 +110,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT126"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT126*").AsWildcard() .Because("the implementation's self-referential constraint where T : IComparable is violated by NotComparable after substitution"); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the constraint violation is the single root cause; the consumer's now-unregistered IRepository must not also raise AWT101"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt127OpenGenericNotUnbound.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt127OpenGenericNotUnbound.cs index 0766bdb0..3c441a79 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt127OpenGenericNotUnbound.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt127OpenGenericNotUnbound.cs @@ -24,7 +24,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT127"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT127*").AsWildcard() .Because("a closed generic in the typeof-ctor form would silently drop its type arguments; the generic attribute form registers closed types"); } @@ -45,7 +45,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT127"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT127*").AsWildcard() .Because("a non-generic type matches no closed service through the open generic path; the generic attribute form registers it"); } @@ -70,7 +70,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT127"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT127*").AsWildcard() .Because("typeof(Repository<>) is the intended unbound open generic form"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt128OpenGenericRemapped.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt128OpenGenericRemapped.cs index f8c6b85e..c8fdf01c 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt128OpenGenericRemapped.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt128OpenGenericRemapped.cs @@ -27,7 +27,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT128"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT128*").AsWildcard() .Because("the implementation does not expose the service with its type parameters in declaration order"); } @@ -52,7 +52,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT128"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT128*").AsWildcard() .Because("Repository : IRepository maps its single type parameter onto the service in order"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt129OpenGenericRecursion.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt129OpenGenericRecursion.cs index ea1ac29a..d10b4125 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt129OpenGenericRecursion.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt129OpenGenericRecursion.cs @@ -30,7 +30,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT129"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT129*").AsWildcard() .Because("the open registration recurses into an ever-larger closed generic, so expansion is bounded and reported"); } @@ -59,7 +59,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT129"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT129*").AsWildcard() .Because("a finite closed-generic chain converges, so no depth limit is reached"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt130Composite.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt130Composite.cs index 8c12dda4..7832bf16 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt130Composite.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt130Composite.cs @@ -27,7 +27,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT130"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT130*").AsWildcard() .Because("a composite with no collection parameter of the composed service has nothing to fan out to"); } @@ -53,7 +53,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT130"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT130*").AsWildcard() .Because("the collection parameter must be of the composed service for the composite to fan out over it"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt131Composite.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt131Composite.cs index a6b69729..79638cd6 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt131Composite.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt131Composite.cs @@ -28,7 +28,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT131"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT131*").AsWildcard() .Because("the composite is also registered as a bare member of its own service, which has no effect"); } @@ -54,7 +54,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT102*").AsWildcard() .Because("dropping the redundant membership keeps the composite out of its own collection, so there is no self-edge cycle"); } @@ -82,7 +82,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT131"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT131*").AsWildcard() .Because("the composite is a member of a different service, not the one it composes"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt132Composite.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt132Composite.cs index 2c01c421..c2268ac3 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt132Composite.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt132Composite.cs @@ -29,7 +29,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT132"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT132*").AsWildcard() .Because("a service can have at most one composite façade"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt133Composite.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt133Composite.cs index 60ab4408..45cdc9da 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt133Composite.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt133Composite.cs @@ -30,9 +30,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT133"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT133*").AsWildcard() .Because("a collection of a base type would fan out over a different collection than the composed service"); - await That(result.Diagnostics.Any(d => d.Contains("AWT130"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT130*").AsWildcard() .Because("the composite has a collection parameter, it is of the wrong element type, not missing"); } @@ -60,7 +60,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT133"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT133*").AsWildcard() .Because("an exact collection of the composed service satisfies the composite regardless of other collection parameters"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt136Awt137PropertyInjection.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt136Awt137PropertyInjection.cs index 8147cbf6..2a4dbed1 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt136Awt137PropertyInjection.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt136Awt137PropertyInjection.cs @@ -29,7 +29,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT136"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT136*").AsWildcard() .Because("an [Inject] property must have a set or init accessor the container can assign through"); } @@ -56,9 +56,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT136"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT136*").AsWildcard() .Because("a protected setter cannot be assigned from the container's object initializer, so it must surface as AWT136 rather than an inaccessible-setter error in generated code"); - await That(result.Diagnostics.Any(d => d.Contains("CS0272"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*CS0272*").AsWildcard() .Because("AWT136 must be reported instead of leaking a compile error into the generated container"); } @@ -83,7 +83,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT137"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT137*").AsWildcard() .Because("runtime arguments are supplied only to constructor parameters, never to an injected property"); } @@ -108,7 +108,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("an injected property needs a registration to satisfy it, exactly like a constructor parameter"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt138ScanMatchedNothing.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt138ScanMatchedNothing.cs index 43c8748d..a60f2752 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt138ScanMatchedNothing.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt138ScanMatchedNothing.cs @@ -47,7 +47,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT138"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT138*").AsWildcard() .Because("the scan matched a concrete type, so it contributes a registration"); } @@ -70,7 +70,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT138"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT138*").AsWildcard() .Because("an overridden match still means the scan found something"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt139ScanNoImplementedInterfaces.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt139ScanNoImplementedInterfaces.cs index 62b5ef94..61c118a4 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt139ScanNoImplementedInterfaces.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt139ScanNoImplementedInterfaces.cs @@ -49,7 +49,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT139"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT139*").AsWildcard() .Because("the Self flag still registers the match as its own concrete type"); } @@ -71,7 +71,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT139"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT139*").AsWildcard() .Because("the match implements the marker interface, so it is registered under it"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt140ScanAssemblyHasNoCandidates.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt140ScanAssemblyHasNoCandidates.cs index a02d8ebd..db3945f4 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt140ScanAssemblyHasNoCandidates.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt140ScanAssemblyHasNoCandidates.cs @@ -45,7 +45,7 @@ public static partial class MyContainer } """, typeof(global::Awaiten.Tests.Support.ICrossAssemblyPlugin)); - await That(result.Diagnostics.Any(d => d.Contains("AWT140"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT140*").AsWildcard() .Because("the referenced assembly has concrete plugins assignable to the marker"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt141ScanMatchSkipped.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt141ScanMatchSkipped.cs index 1ea900cc..b5888d24 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt141ScanMatchSkipped.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt141ScanMatchSkipped.cs @@ -30,7 +30,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT141*NeedsName*").AsWildcard() .Because("the opted-in scan degrades an unconstructable match to a skip-with-warning"); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the skipped match is not also reported as a missing dependency"); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; @@ -98,7 +98,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("without the opt-in, an unconstructable scan match stays a hard error"); - await That(result.Diagnostics.Any(d => d.Contains("AWT141"))).IsFalse(); + await That(result.Diagnostics).DoesNotContain("*AWT141*").AsWildcard(); } [Fact] @@ -125,7 +125,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("asking for the type by name makes its missing dependency a real fault again"); - await That(result.Diagnostics.Any(d => d.Contains("AWT141"))).IsFalse(); + await That(result.Diagnostics).DoesNotContain("*AWT141*").AsWildcard(); } [Fact] @@ -153,7 +153,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("the scan without the opt-in pins the shared match to error semantics"); - await That(result.Diagnostics.Any(d => d.Contains("AWT141"))).IsFalse(); + await That(result.Diagnostics).DoesNotContain("*AWT141*").AsWildcard(); } [Fact] @@ -186,7 +186,7 @@ public static partial class MyContainer // (with its own warning) rather than leaving an AWT101. await That(result.Diagnostics).Contains("*AWT141*NeedsName*").AsWildcard() .And.Contains("*AWT141*NeedsNeedsName*").AsWildcard(); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse(); + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard(); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; await That(source).Contains("new global::MyCode.OkPlugin()"); diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt142ScanLifetimeConflict.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt142ScanLifetimeConflict.cs index 14ce4e39..2c6e3925 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt142ScanLifetimeConflict.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt142ScanLifetimeConflict.cs @@ -50,7 +50,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT142"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT142*").AsWildcard() .Because("agreeing scans coalesce without contradiction"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt143ScanAssembliesEmpty.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt143ScanAssembliesEmpty.cs index 6ad24dd4..48947ec4 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt143ScanAssembliesEmpty.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt143ScanAssembliesEmpty.cs @@ -27,7 +27,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*error AWT143*").AsWildcard() .Because("an empty InAssembliesOf is a malformed scan, not a mere empty result, and must fail the build"); - await That(result.Diagnostics.Any(d => d.Contains("AWT138"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT138*").AsWildcard() .Because("the empty assembly list is the one root cause; the scan matching nothing follows from it"); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; @@ -76,7 +76,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT143"))).IsFalse(); + await That(result.Diagnostics).DoesNotContain("*AWT143*").AsWildcard(); } } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt144Awt145Awt146DeferredProperty.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt144Awt145Awt146DeferredProperty.cs index 3b85f0a1..28de26c4 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt144Awt145Awt146DeferredProperty.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt144Awt145Awt146DeferredProperty.cs @@ -29,7 +29,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT144"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT144*").AsWildcard() .Because("a deferred property is assigned after construction, so it needs a set accessor - an init-only accessor can only be assigned in an object initializer"); } @@ -57,7 +57,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT144"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT144*").AsWildcard() .Because("a required member can only be satisfied inside an object initializer, which is exactly the construction-time path a deferred property must avoid - it deserves the targeted diagnostic, not CS9035 in generated code"); } @@ -81,7 +81,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT145"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT145*").AsWildcard() .Because("a deferred property breaks a cycle only when the owning instance is cached; a transient is rebuilt on each resolve, so the cycle would recurse forever"); } @@ -104,7 +104,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT145"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT145*").AsWildcard() .Because("a self-referential deferred property on a transient is a one-node cycle with nothing cached, so it cannot terminate"); } @@ -153,7 +153,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT145"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT145*").AsWildcard() .Because("a deferred collection member is materialized eagerly, so a transient cycle closed through it recurses forever exactly like a direct member"); } @@ -177,7 +177,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT145") || d.Contains("AWT146"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT145*").AsWildcard() + .Because("a synchronous singleton (or scoped) deferred cycle is cached before it is wired, so it terminates and is supported"); + await That(result.Diagnostics).DoesNotContain("*AWT146*").AsWildcard() .Because("a synchronous singleton (or scoped) deferred cycle is cached before it is wired, so it terminates and is supported"); } @@ -204,7 +206,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT145"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT145*").AsWildcard() .Because("a cached singleton participant breaks the recursion, so a mixed-lifetime deferred cycle terminates and is not the all-transient AWT145 fault"); await That(result.Diagnostics).IsEmpty() .Because("the mixed cycle is supported: no AWT102 (deferred edges are absent from the construction graph), AWT146 (nothing async) or AWT147 (no construction edge) either"); @@ -241,9 +243,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT146"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT146*").AsWildcard() .Because("a deferred property cannot break a cycle through an async service - its memoized task is published only after the re-entrant resolve returns, so the cycle cannot terminate"); - await That(result.Diagnostics.Any(d => d.Contains("AWT145"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT145*").AsWildcard() .Because("both participants are singletons, so the fault is the async one (AWT146), not the transient one (AWT145)"); } @@ -277,7 +279,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT146"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT146*").AsWildcard() .Because("a deferred member is only rejected when it closes a cycle through an async service, not for any async deferred member"); } @@ -303,9 +305,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT147"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT147*").AsWildcard() .Because("a deferred property breaks a cycle only when every edge is deferred; a surviving constructor edge re-enters an uncached participant, so the cycle is only partly broken"); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT102*").AsWildcard() .Because("the deferred edge is absent from the construction graph, so AWT102 does not fire - AWT147 is the diagnostic that catches this"); } @@ -331,9 +333,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT147"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT147*").AsWildcard() .Because("a mixed cycle through a plain [Inject] property still traverses a construction-time edge, so a deferred property cannot break it"); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT102*").AsWildcard() .Because("the deferred edge keeps the cycle out of the construction graph, so AWT102 does not fire"); } @@ -359,9 +361,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT147"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT147*").AsWildcard() .Because("a bare Owned resolves its target at construction time, so it is a construction edge that leaves the deferred cycle only partly broken"); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT102*").AsWildcard() .Because("the construction graph has only the Right -> Left edge (the deferred Left -> Right edge is absent), so it holds no cycle for AWT102"); } @@ -396,9 +398,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT147"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT147*").AsWildcard() .Because("the construction edge Beta -> Gamma survives in a cycle with deferred edges, so resolving Beta re-enters it before it is cached and constructs a duplicate singleton - even though the same component also contains a supported all-deferred cycle"); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT102*").AsWildcard() .Because("the construction graph holds only Beta -> Gamma, which is acyclic, so AWT102 stays silent - AWT147 is the diagnostic that must catch this"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt148AmbiguousDefault.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt148AmbiguousDefault.cs index d8c49a09..f5675692 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt148AmbiguousDefault.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt148AmbiguousDefault.cs @@ -68,7 +68,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT148"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT148*").AsWildcard() .Because("a strong registration overrides both defaults, so which default would have won is moot"); } @@ -100,7 +100,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT148"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT148*").AsWildcard() .Because("Fallback.Silent opts out of the ambiguity warning: the first contributor simply wins"); } @@ -132,7 +132,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT148"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT148*").AsWildcard() .Because("the earlier Fallback.Silent wins silently; AWT148 requires the current winner to be a Fallback.Warn"); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; await That(source).Contains("global::MyCode.ClockA") @@ -207,7 +207,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT148"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT148*").AsWildcard() .Because("defaults under different keys claim different service slots and do not collide"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt149Awt150Awt151ModuleImport.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt149Awt150Awt151ModuleImport.cs index ebaa9722..394d0efd 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt149Awt150Awt151ModuleImport.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt149Awt150Awt151ModuleImport.cs @@ -81,7 +81,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT149"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT149*").AsWildcard() .Because("a [Module] is a valid import target"); } } @@ -142,7 +142,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT150"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT150*").AsWildcard() .Because("a module with no [Import] of its own has nothing to follow"); } } @@ -193,7 +193,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT151"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT151*").AsWildcard() .Because("a module with registrations contributes something"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt152NonStaticModule.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt152NonStaticModule.cs index 7ff7b132..714c0479 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt152NonStaticModule.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt152NonStaticModule.cs @@ -57,7 +57,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the module is still imported, so its registrations do not additionally cascade as missing dependencies"); } @@ -82,7 +82,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT152"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT152*").AsWildcard() .Because("a static module satisfies the requirement"); } @@ -106,7 +106,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT152"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT152*").AsWildcard() .Because("a non-module import is rejected by AWT149 before the static requirement applies"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt154ScanOnModule.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt154ScanOnModule.cs index 98b27bef..9c9c8218 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt154ScanOnModule.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt154ScanOnModule.cs @@ -63,9 +63,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the module's lifetime registrations are still imported"); - await That(result.Diagnostics.Any(d => d.Contains("AWT151"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT151*").AsWildcard() .Because("the module declares a lifetime registration, so it is not empty"); } @@ -120,7 +120,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT154"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT154*").AsWildcard() .Because("[Scan] on the container is the supported placement"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt155CrossModuleDuplicate.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt155CrossModuleDuplicate.cs index d024cbb6..f53eb591 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt155CrossModuleDuplicate.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt155CrossModuleDuplicate.cs @@ -110,7 +110,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT155"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT155*").AsWildcard() .Because("an explicit registration beating another module's expanded template is deterministic regardless of [Import] order, so the collision is not ambiguous"); } @@ -138,7 +138,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT155"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT155*").AsWildcard() .Because("the container overriding a module is the intended override mechanism"); } @@ -169,7 +169,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT155"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT155*").AsWildcard() .Because("the same implementation coalesces into one instance; there is no ambiguity"); } @@ -201,7 +201,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT155"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT155*").AsWildcard() .Because("an overridable default yields by design; being overridden is its purpose"); } @@ -235,7 +235,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT117*").AsWildcard() .Because("a keyed duplicate is already its own error"); - await That(result.Diagnostics.Any(d => d.Contains("AWT155"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT155*").AsWildcard() .Because("AWT155 is limited to unkeyed collisions to avoid double-reporting"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt157Awt158OptionalProperty.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt157Awt158OptionalProperty.cs index 488c195e..c7b02b91 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt157Awt158OptionalProperty.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt157Awt158OptionalProperty.cs @@ -28,7 +28,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("an optional property with no registration is left unset, not reported as a missing dependency"); await That(result.Diagnostics).IsEmpty() .Because("an optional set-accessor property with no registration is well-defined and reports nothing"); @@ -83,7 +83,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT157"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT157*").AsWildcard() .Because("an optional property is omitted from the object initializer when unregistered, which a required member does not allow - the targeted AWT157 is reported rather than leaving only the opaque CS9035 the omitted required member would otherwise produce"); } @@ -110,9 +110,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT158"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT158*").AsWildcard() .Because("an optional init-only property left unset when unregistered can never be filled afterwards, so it is warned about"); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the property is still optional, so a missing registration is not the AWT101 error"); } @@ -138,7 +138,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT158"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT158*").AsWildcard() .Because("AWT158 flags the init-only optional declaration itself: if the registration is ever removed the property would silently and permanently be default"); } @@ -193,7 +193,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT158"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT158*").AsWildcard() .Because("Optional has no effect on a collection, which is always filled, so the init-only-stays-default warning does not apply"); await That(result.Diagnostics).IsEmpty() .Because("an optional init-only collection is well-defined and reports nothing"); @@ -223,7 +223,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT157"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT157*").AsWildcard() .Because("a collection is always filled and never omitted, so a required optional collection is not the AWT157 fault"); await That(result.Diagnostics).IsEmpty() .Because("an optional required collection is well-defined and reports nothing"); diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt164InvalidLifecycleHook.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt164InvalidLifecycleHook.cs index 89903d50..76326d77 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt164InvalidLifecycleHook.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt164InvalidLifecycleHook.cs @@ -24,7 +24,7 @@ private static void Missing(int wrongType) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT164*").AsWildcard() .Because("the named method does not accept the registered implementation type"); } @@ -45,7 +45,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT164*").AsWildcard() .Because("no container method carries the named release hook"); } @@ -67,7 +67,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT164*").AsWildcard() .Because("a lifecycle hook must be a void method"); } @@ -91,7 +91,7 @@ private static void Started(Settings settings, Service service) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT164*").AsWildcard() .Because("the hook's first parameter is the instance, so it must accept the implementation type"); } @@ -115,7 +115,9 @@ private static void Started(Service service, Settings settings) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164") || d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT164*").AsWildcard() + .Because("the instance parameter is first and the extra Settings parameter is registered on the graph"); + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the instance parameter is first and the extra Settings parameter is registered on the graph"); } @@ -138,7 +140,7 @@ private static void Started(Service service, Missing missing) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .Because("a lifecycle hook parameter after the instance is a graph dependency that must be registered"); } @@ -161,7 +163,7 @@ private static void Stopping(object instance) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT164"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT164*").AsWildcard() .Because("a void method accepting the implementation (or a base type) is a usable hook"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt165LifecycleHookOnInstance.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt165LifecycleHookOnInstance.cs index 6a48c3cb..9e7dadd0 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt165LifecycleHookOnInstance.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt165LifecycleHookOnInstance.cs @@ -26,7 +26,7 @@ private static void Release(Service service) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT165"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT165*").AsWildcard() .Because("the container does not own a pre-built instance, so the hook would never run"); } @@ -48,7 +48,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT165"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT165*").AsWildcard() .Because("a pre-built instance without lifecycle hooks is valid"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt167ContextualBinding.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt167ContextualBinding.cs index d57b0e4c..9b6a7aba 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt167ContextualBinding.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt167ContextualBinding.cs @@ -28,7 +28,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT167"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT167*").AsWildcard() .Because("the named consumer has no constructor dependency on the service, so the binding is dead"); } @@ -82,7 +82,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT167"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT167*").AsWildcard() .Because("the [FromKey] parameter takes precedence, so the contextual binding is never applied"); } @@ -109,7 +109,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT167"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT167*").AsWildcard() .Because("a Func-deferred dependency is not an unkeyed direct parameter, so the contextual binding is never applied"); } @@ -164,7 +164,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT168"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT168*").AsWildcard() .Because("WhenInjectedInto and Key claim the same resolution slot, so the Key is silently dropped"); } @@ -221,7 +221,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT169"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT169*").AsWildcard() .Because("both bindings claim the one contextual slot for the consumer, so the resolution is ambiguous"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt172ScanFiltersMatchedNothing.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt172ScanFiltersMatchedNothing.cs index f9393712..3b8c00c4 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt172ScanFiltersMatchedNothing.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt172ScanFiltersMatchedNothing.cs @@ -26,7 +26,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT172*").AsWildcard() .Because("the marker matched OrderPlugin but the name filter removed it"); - await That(result.Diagnostics.Any(d => d.Contains("AWT138"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT138*").AsWildcard() .Because("AWT138 is for a marker that matched nothing, distinct from a filter that removed everything"); } @@ -49,7 +49,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT172"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT172*").AsWildcard() .Because("OrderHandler still matches, so the filter did not remove everything"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt173ScanExclusionNeverMatched.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt173ScanExclusionNeverMatched.cs index f52ef2ef..6953b129 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt173ScanExclusionNeverMatched.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt173ScanExclusionNeverMatched.cs @@ -70,7 +70,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT173"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT173*").AsWildcard() .Because("DropPlugin was excluded, so the exclusion did its job"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt174ScanPatternMatchesEverything.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt174ScanPatternMatchesEverything.cs index 353f472e..8c30be6d 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt174ScanPatternMatchesEverything.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt174ScanPatternMatchesEverything.cs @@ -68,7 +68,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT174"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT174*").AsWildcard() .Because("'*Handler' does not match every candidate"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt175ContradictingExternalService.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt175ContradictingExternalService.cs index ecbd03c6..974e6342 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt175ContradictingExternalService.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt175ContradictingExternalService.cs @@ -51,7 +51,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT175"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT175*").AsWildcard() .Because("an [ImportService] type with no registration is the ordinary, contradiction-free case"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt176UnconsumedExternalService.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt176UnconsumedExternalService.cs index b1991706..a82ae1d7 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt176UnconsumedExternalService.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt176UnconsumedExternalService.cs @@ -83,7 +83,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .And.Contains("*IExternal*").AsWildcard() .Because("a relationship over the external type is not routed, so the missing registration is AWT101"); - await That(result.Diagnostics.Any(d => d.Contains("AWT176"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT176*").AsWildcard() .Because("the external type is referenced (via the relationship), so it is not a dead declaration - the AWT101 is the one signal"); } @@ -106,7 +106,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT176"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT176*").AsWildcard() .Because("a consumed [ImportService] declaration is live"); } @@ -130,7 +130,7 @@ private static void Started(Service service, ILogger logger) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT176"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT176*").AsWildcard() .Because("an [ImportService] consumed only by a lifecycle hook parameter is still live"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt177Awt178Awt179InjectProperty.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt177Awt178Awt179InjectProperty.cs index af448ccd..65fec2db 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt177Awt178Awt179InjectProperty.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt177Awt178Awt179InjectProperty.cs @@ -31,7 +31,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT177"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT177*").AsWildcard() .Because("an [InjectProperty] name must resolve to a settable property on the implementation"); } @@ -59,7 +59,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT177"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT177*").AsWildcard() .Because("a read-only (get-only) member is not a settable property, so [InjectProperty] cannot fill it"); } @@ -87,9 +87,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT178"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT178*").AsWildcard() .Because("property injection only fills a container-constructed instance; a Factory produces it whole"); - await That(result.Diagnostics.Any(d => d.Contains("AWT180"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT180*").AsWildcard() .Because("a Factory-produced implementation is registered, so it is AWT178 rather than the unmatched AWT180"); } @@ -117,7 +117,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT178"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT178*").AsWildcard() .Because("a pre-built Instance is produced whole by its source, so [InjectProperty] cannot fill it"); } @@ -146,7 +146,7 @@ public static partial class MyContainer """); // AWT179 is a warning, not an error: the graph is well-defined (the first entry wins). - await That(result.Diagnostics.Any(d => d.Contains("warning AWT179"))).IsTrue() + await That(result.Diagnostics).Contains("*warning AWT179*").AsWildcard() .Because("a property is injected once, so a duplicate [InjectProperty] entry is a suppressible warning"); } @@ -171,7 +171,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT180"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT180*").AsWildcard() .Because("an [InjectProperty] whose implementation has no container-constructed registration is never applied"); } @@ -202,7 +202,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT180"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT180*").AsWildcard() .Because("a decorator chain link is constructed (under a synthetic identity), so a decorator-type target must not be misreported as unmatched"); } @@ -230,7 +230,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT170"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT170*").AsWildcard() .Because("an [InjectProperty] Key must be a supported key constant, guarded like a registration's Key and [FromKey]"); } @@ -258,7 +258,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT181"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT181*").AsWildcard() .Because("a property named by both [Inject] and [InjectProperty] warns that the [Inject] member wins"); } @@ -286,7 +286,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT*").AsWildcard() .Because("a property named only by [InjectProperty] (no [Inject]) is filled cleanly, with no diagnostic"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt182ScanNoMatchingInterface.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt182ScanNoMatchingInterface.cs index 7c8d7d2d..ee4e29e1 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt182ScanNoMatchingInterface.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt182ScanNoMatchingInterface.cs @@ -49,7 +49,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT182"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT182*").AsWildcard() .Because("the Self flag still registers the match as its own concrete type"); } @@ -72,7 +72,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT182"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT182*").AsWildcard() .Because("a markerless scan skips a non-conforming type silently instead of warning per type"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt183MarkerlessScanInvalid.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt183MarkerlessScanInvalid.cs index b1284db0..67897c23 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt183MarkerlessScanInvalid.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt183MarkerlessScanInvalid.cs @@ -155,7 +155,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT183"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT183*").AsWildcard() .Because("a namespace pattern that names a segment positively bounds the scan"); } @@ -177,7 +177,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT183"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT183*").AsWildcard() .Because("a scoped markerless MatchingInterface scan is well-formed"); } @@ -197,7 +197,7 @@ public static partial class MyContainer } """, typeof(global::Awaiten.Tests.Support.ICrossAssemblyPlugin)); - await That(result.Diagnostics.Any(d => d.Contains("AWT183"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT183*").AsWildcard() .Because("InAssembliesOf alone is a valid scope for a markerless scan"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt184MarkerlessScanRegisteredNothing.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt184MarkerlessScanRegisteredNothing.cs index cf8b95ff..addd9c2a 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt184MarkerlessScanRegisteredNothing.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt184MarkerlessScanRegisteredNothing.cs @@ -48,7 +48,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT184"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT184*").AsWildcard() .Because("FirstWidget registers under IFirstWidget, so the scan is not empty"); } @@ -71,7 +71,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT184*").AsWildcard() .Because("the assembly holds no concrete class, so the scan registers nothing"); - await That(result.Diagnostics.Any(d => d.Contains("AWT173"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT173*").AsWildcard() .Because("a stale-exclusion hint is noise when the scan saw no candidate to filter"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt185ScanExposesNothing.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt185ScanExposesNothing.cs index 57384423..41ecf1a7 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt185ScanExposesNothing.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt185ScanExposesNothing.cs @@ -68,7 +68,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT185"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT185*").AsWildcard() .Because("an unset As keeps the Self default, which exposes the match"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt187ScanAmbiguousMatchingInterfaces.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt187ScanAmbiguousMatchingInterfaces.cs index 15087933..0ea1bed7 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt187ScanAmbiguousMatchingInterfaces.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt187ScanAmbiguousMatchingInterfaces.cs @@ -54,7 +54,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT187"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT187*").AsWildcard() .Because("the own-namespace IWorker decides the tie, so a single interface registers"); } @@ -82,7 +82,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT187"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT187*").AsWildcard() .Because("the internal A.IWorker is dropped, so only B.IWorker registers and no ambiguity remains"); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; await That(source).Contains("typeof(global::B.IWorker)"); @@ -115,7 +115,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT188*").AsWildcard() .Because("the match registers nothing, which AWT188 reports per inaccessible interface"); - await That(result.Diagnostics.Any(d => d.Contains("AWT187"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT187*").AsWildcard() .Because("claiming the match is registered under each interface would contradict AWT188"); } @@ -140,7 +140,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT187"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT187*").AsWildcard() .Because("a markerless match is never warned, like AWT139/AWT182/AWT188"); string source = result.Sources["Awaiten.MyCode.MyContainer.g.cs"]; await That(source).Contains("typeof(global::A.IWorker)") @@ -176,7 +176,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT141*").AsWildcard() .Because("the match cannot be constructed and the scan opted into skipping it"); - await That(result.Diagnostics.Any(d => d.Contains("AWT187"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT187*").AsWildcard() .Because("a skipped match is registered under nothing, so the ambiguity warning would contradict AWT141"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt188ScanInterfaceInaccessible.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt188ScanInterfaceInaccessible.cs index 1d58f57f..f9b33746 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt188ScanInterfaceInaccessible.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt188ScanInterfaceInaccessible.cs @@ -29,7 +29,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT188*IRoaster*").AsWildcard() .Because("Roaster implements IRoaster, but the internal interface cannot be referenced by the container"); - await That(result.Diagnostics.Any(d => d.Contains("AWT182"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT182*").AsWildcard() .Because("claiming the interface is not implemented would mislead; AWT188 names the real cause"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt189HookParameterIsArg.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt189HookParameterIsArg.cs index ac9ce73b..96d4f2ea 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt189HookParameterIsArg.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt189HookParameterIsArg.cs @@ -24,7 +24,7 @@ private static void Started(Service service, [Arg] int count) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT189"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT189*").AsWildcard() .Because("a runtime [Arg] cannot be supplied to a lifecycle hook - its parameters resolve from the graph"); } @@ -48,7 +48,7 @@ private static void Released(Service service, Settings settings) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT189"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT189*").AsWildcard() .Because("a hook parameter resolved from the graph is not a runtime argument"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt190AmbiguousLifecycleHook.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt190AmbiguousLifecycleHook.cs index 8761fe6b..ae829c90 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt190AmbiguousLifecycleHook.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt190AmbiguousLifecycleHook.cs @@ -27,7 +27,7 @@ private static void Started(Service service, Settings settings) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT190"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT190*").AsWildcard() .Because("two accessible methods named Started accept the instance, so the container cannot choose one"); } @@ -50,7 +50,7 @@ private static void Stopping(object instance) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT190"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT190*").AsWildcard() .Because("both the exact and the object overload accept the instance, so the release hook choice is order-dependent"); } @@ -73,7 +73,9 @@ private static void Started(int unrelated) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT190") || d.Contains("AWT164"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT190*").AsWildcard() + .Because("the int overload does not accept the instance, so there is exactly one usable hook and no ambiguity"); + await That(result.Diagnostics).DoesNotContain("*AWT164*").AsWildcard() .Because("the int overload does not accept the instance, so there is exactly one usable hook and no ambiguity"); } @@ -97,7 +99,7 @@ private static void Started(object instance) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT190"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT190*").AsWildcard() .Because("a single shared object hook is one match per registration, so neither registration is ambiguous"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt191ReleaseHookDeferredParameter.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt191ReleaseHookDeferredParameter.cs index e941f787..6ea214eb 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt191ReleaseHookDeferredParameter.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt191ReleaseHookDeferredParameter.cs @@ -34,7 +34,7 @@ private static void Released(Service service, Func tool) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT191"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT191*").AsWildcard() .Because("a Func release capture holds a resolver delegate that is dead by the time the hook runs at teardown"); } @@ -59,7 +59,7 @@ private static void Released(Service service, Lazy tool) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT191"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT191*").AsWildcard() .Because("an unmaterialized Lazy release capture defers resolution past the owner's teardown, like a Func"); } @@ -85,7 +85,7 @@ private static void Released(Service service, Func> tool) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT191"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT191*").AsWildcard() .Because("the async factory form defers resolution exactly like the synchronous Func"); } @@ -110,7 +110,7 @@ private static void Started(Service service, Func tool) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT191"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT191*").AsWildcard() .Because("an activation hook runs while the owner is alive, so its Func parameter is invokable"); } @@ -134,7 +134,7 @@ private static void Released(Service service, Pool pool) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT191"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT191*").AsWildcard() .Because("a direct release dependency is resolved at construction and captured by value, which is the supported shape"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt192SuppressDisposalOnInstance.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt192SuppressDisposalOnInstance.cs index 9b80958c..e4ea9bb1 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt192SuppressDisposalOnInstance.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.Awt192SuppressDisposalOnInstance.cs @@ -24,7 +24,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT192"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT192*").AsWildcard() .Because("the container never disposes a pre-built instance, so suppressing that disposal is a no-op"); } @@ -46,7 +46,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT192"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT192*").AsWildcard() .Because("a pre-built instance without SuppressDisposal is valid"); } @@ -70,7 +70,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT192"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT192*").AsWildcard() .Because("SuppressDisposal is meaningful on a container-constructed instance, which the container would otherwise dispose"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.HookParameterKeyMisuse.cs b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.HookParameterKeyMisuse.cs index 7850ce14..36313f27 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.HookParameterKeyMisuse.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/DiagnosticTests.HookParameterKeyMisuse.cs @@ -35,7 +35,7 @@ private static void Started(Service service, [FromKey(5)] IChannel channel) { } // int is not a supported key type for a [FromKey], and a hook parameter is classified like a constructor // parameter, so it is rejected rather than silently treated as unkeyed. - await That(result.Diagnostics.Any(d => d.Contains("AWT170"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT170*").AsWildcard() .Because("a hook parameter's [FromKey] is validated exactly like a constructor parameter's"); } @@ -63,7 +63,7 @@ private static void Started(Service service, IReadOnlyDictionary // int is neither string nor an enum, so a keyed dictionary cannot synthesize under it (AWT159), for a hook // parameter as for a constructor one. - await That(result.Diagnostics.Any(d => d.Contains("AWT159"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT159*").AsWildcard() .Because("a keyed-collection hook parameter is validated like a constructor parameter's"); } @@ -91,7 +91,7 @@ private static void Started(Service service, [FromKey("fast")] IReadOnlyDictiona // A [FromKey] cannot select within the synthesized dictionary, so it is rejected (AWT160) on a hook // parameter exactly as on a constructor one. - await That(result.Diagnostics.Any(d => d.Contains("AWT160"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT160*").AsWildcard() .Because("a [FromKey] on a synthesized keyed-collection hook parameter is rejected like a constructor parameter's"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/GeneralTests.cs b/Tests/Awaiten.SourceGenerators.Tests/GeneralTests.cs index e3741340..35f78f48 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/GeneralTests.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/GeneralTests.cs @@ -916,7 +916,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .And.Contains("*IMetrics*").AsWildcard() .Because("[ImportService] routes only the declared type; every other unresolved dependency keeps the AWT101 check"); - await That(result.Diagnostics.Any(d => d.Contains("ILogger"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*ILogger*").AsWildcard() .Because("the declared external ILogger is routed to the provider, not reported missing"); } @@ -944,7 +944,7 @@ public static partial class MyContainer await That(result.Diagnostics).Contains("*AWT101*").AsWildcard() .And.Contains("*ILogger*").AsWildcard() .Because("[ImportService] routes only the direct dependency of T; a Func/Lazy relationship over it resolves from the graph and is AWT101 when unregistered"); - await That(result.Diagnostics.Any(d => d.Contains("AWT176"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT176*").AsWildcard() .Because("the external type is still referenced through the relationship, so it is not an unconsumed (dead) declaration"); } @@ -2043,7 +2043,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT162"))).IsTrue(); + await That(result.Diagnostics).Contains("*AWT162*").AsWildcard(); } [Fact] @@ -2068,7 +2068,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT163"))).IsTrue(); + await That(result.Diagnostics).Contains("*AWT163*").AsWildcard(); } [Fact] @@ -2122,7 +2122,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT186*").AsWildcard() .Because("a Func> produces the owned handle per call, but the requesting-type factory has no owner scope to build it into"); } @@ -2149,7 +2149,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT186*").AsWildcard() .Because("a Task> still produces the owned handle, which the requesting-type factory has no owner scope to build into"); } @@ -2176,7 +2176,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT186*").AsWildcard() .Because("a Func>> still produces the owned handle, which the requesting-type factory has no owner scope to build into"); } @@ -2203,9 +2203,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT121"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT121*").AsWildcard() .Because("Lazy does not unwrap Owned, so the more specific AWT121 (Owned-through-Lazy) pre-empts this shape"); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT186*").AsWildcard() .Because("the Lazy>> form never reaches the owned emit AWT186 guards"); } @@ -2231,9 +2231,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT121"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT121*").AsWildcard() .Because("Lazy never unwraps the Owned handle, so the unregistered Owned stays the service and surfaces AWT121"); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT186*").AsWildcard() .Because("the bare Lazy> form never reaches AWT186's owned emit, exactly like Lazy>>"); } @@ -2259,7 +2259,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT186*").AsWildcard() .Because("the detection pass walks injected [Inject] members like constructor parameters"); } @@ -2286,7 +2286,7 @@ private static void Started(Alpha alpha, Owned logger) { } } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT186"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT186*").AsWildcard() .Because("the detection pass walks lifecycle hook parameters like constructor parameters"); } diff --git a/Tests/Awaiten.SourceGenerators.Tests/ModuleTests.cs b/Tests/Awaiten.SourceGenerators.Tests/ModuleTests.cs index 6e521e13..55f0b215 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/ModuleTests.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/ModuleTests.cs @@ -743,7 +743,7 @@ public static partial class MyContainer // The nested import is rejected (AWT150), but the module's own registrations still import, so they do // not cascade as AWT101 missing dependencies. await That(result.Diagnostics).Contains("*AWT150*InfrastructureModule*").AsWildcard(); - await That(result.Diagnostics.Any(d => d.Contains("AWT101"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT101*").AsWildcard() .Because("the module's own registrations are imported despite its rejected nested [Import]"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/OpenGenericDecoratorTests.cs b/Tests/Awaiten.SourceGenerators.Tests/OpenGenericDecoratorTests.cs index 8b16fb7d..61d6916c 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/OpenGenericDecoratorTests.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/OpenGenericDecoratorTests.cs @@ -66,7 +66,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT127"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT127*").AsWildcard() .Because("the typeof form must receive an unbound generic decorator such as typeof(Logging<>)"); } @@ -91,7 +91,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT125"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT125*").AsWildcard() .Because("the open decorator's arity must match the service's"); } @@ -118,9 +118,9 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("warning AWT171"))).IsTrue() + await That(result.Diagnostics).Contains("*warning AWT171*").AsWildcard() .Because("the closing IHandler cannot construct Logging under 'where T : class'"); - await That(result.Diagnostics.Any(d => d.Contains("AWT126"))).IsFalse() + await That(result.Diagnostics).DoesNotContain("*AWT126*").AsWildcard() .Because("AWT126 is the registration error; an excluded decorator closing is the separate warning AWT171"); } @@ -145,7 +145,7 @@ public static partial class MyContainer """); // Nothing requires a closed IHandler<…>, so no closing is expanded and there is nothing to decorate. - await That(result.Diagnostics.Any(d => d.Contains("AWT123"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT123*").AsWildcard() .Because("the open decorator matches no closing of the service"); } @@ -205,7 +205,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT127"))).IsTrue() + await That(result.Diagnostics).Contains("*AWT127*").AsWildcard() .Because("the typeof form must receive an unbound generic composite such as typeof(CompositeHandler<>)"); } } diff --git a/Tests/Awaiten.SourceGenerators.Tests/PropertyInjectionTests.cs b/Tests/Awaiten.SourceGenerators.Tests/PropertyInjectionTests.cs index 0f15ccca..d8852a2d 100644 --- a/Tests/Awaiten.SourceGenerators.Tests/PropertyInjectionTests.cs +++ b/Tests/Awaiten.SourceGenerators.Tests/PropertyInjectionTests.cs @@ -92,7 +92,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsTrue(); + await That(result.Diagnostics).Contains("*AWT102*").AsWildcard(); } [Fact] @@ -180,7 +180,7 @@ public static partial class MyContainer } """); - await That(result.Diagnostics.Any(d => d.Contains("AWT102"))).IsTrue(); + await That(result.Diagnostics).Contains("*AWT102*").AsWildcard(); } [Fact]