Skip to content

refactor: report partially open typeof arguments of [InjectProperty] through AWT215 and retire AWT217 - #225

Merged
vbreuss merged 2 commits into
mainfrom
refactor/share-awt215
Oct 30, 2026
Merged

vbreuss merged 2 commits into
mainfrom
refactor/share-awt215

Conversation

@vbreuss

@vbreuss vbreuss commented Oct 30, 2026

Copy link
Copy Markdown
Member

AWT217 only restated CS7003 for a partially open [InjectProperty(typeof(...), name)] target, so it could only ever appear next to a compiler error, and it missed the one case C# accepts: typeof(Outer<>.Inner), which Roslyn marks unbound with arity 0 and which [InjectProperty] silently treated as an open entry matching every closing of Outer.Inner, while [ImportService(typeof(...))] rejected it as AWT215.

Both typeof attributes now follow one rule: the argument must be a closed type or an unbound generic definition, and anything else, including null, is AWT215, which names the attribute. A partially open argument is recognised from syntax for both attributes, which also fixes [ImportService(typeof(Outer.Inner<>))]: it was accepted next to CS7003 and only reported as an unused import (AWT176).

AWT217 never shipped (it was only listed as unshipped); its descriptor, docs section and tests are removed, and the id stays reserved and is never reused.

…through AWT215 and retire AWT217

AWT217 only restated CS7003 for a partially open [InjectProperty(typeof(...), name)] target, so it could only ever appear next to a compiler error, and it missed the one case C# accepts: typeof(Outer<>.Inner), which Roslyn marks unbound with arity 0 and which [InjectProperty] silently treated as an open entry matching every closing of Outer<T>.Inner, while [ImportService(typeof(...))] rejected it as AWT215.

Both typeof attributes now follow one rule: the argument must be a closed type or an unbound generic definition, and anything else, including null, is AWT215, which names the attribute. A partially open argument is recognised from syntax for both attributes, which also fixes [ImportService(typeof(Outer<int>.Inner<>))]: it was accepted next to CS7003 and only reported as an unused import (AWT176).

AWT217 never shipped (it was only listed as unshipped); its descriptor, docs section and tests are removed, and the id stays reserved and is never reused.
@vbreuss vbreuss self-assigned this Oct 30, 2026
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Test Results

   27 files  ± 0     27 suites  ±0   1h 13m 46s ⏱️ - 35m 53s
1 673 tests + 5  1 673 ✅ + 5  0 💤 ±0  0 ❌ ±0 
8 130 runs  +15  8 130 ✅ +15  0 💤 ±0  0 ❌ ±0 

Results for commit 2ae5588. ± Comparison against base commit 460c78f.

This pull request removes 14 and adds 19 tests. Note that renamed tests count towards both.
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinition(typeof(IClock))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinition(typeof(ILog<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinition(typeof(ILog<int>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinition(typeof(Outer<>·Inner<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ ReportsANullType
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ ReportsATypeNestedInAnUnboundGeneric
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215ImportServiceTypeNotClosedOrOpen ‑ ReportsOnAnImportedModule
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt217InjectPropertyPartiallyOpen ‑ DoesNotReportAwt217ForAClosedTypeOrAnUnboundDefinition(typeof(Outer<>·Inner<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt217InjectPropertyPartiallyOpen ‑ DoesNotReportAwt217ForAClosedTypeOrAnUnboundDefinition(typeof(Outer<>·Leaf))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt217InjectPropertyPartiallyOpen ‑ DoesNotReportAwt217ForAClosedTypeOrAnUnboundDefinition(typeof(Outer<int>·Inner<string>))
…
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnImportService(typeof(IClock))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnImportService(typeof(ILog<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnImportService(typeof(ILog<int>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnImportService(typeof(Outer<>·Inner<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnInjectProperty(propertyName: "Clock", implementation: typeof(Outer<>·Inner<>))
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnInjectProperty(typeof(Outer<>·Inner<>), "Clock")
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnInjectProperty(typeof(Outer<int>·Inner<string>), "Clock")
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ DoesNotReportAClosedTypeOrAnUnboundGenericDefinitionOnInjectProperty(typeof(Outer<int>·Leaf), "Clock")
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ ReportsANullType(ImportService(null!), ImportService)
Awaiten.SourceGenerators.Tests.DiagnosticTests+Awt215TypeofArgumentNotClosedOrOpen ‑ ReportsANullType(InjectProperty(null!, "Clock"), InjectProperty)
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 2.96GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Realistic Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 305.4 ns 1.00 ns 0.89 ns 1.15 568 B 1.00
Awaiten 266.6 ns 2.90 ns 2.72 ns 1.00 568 B 1.00
MsDI 640.9 ns 6.80 ns 6.03 ns 2.40 1104 B 1.94
Autofac 6,770.6 ns 60.19 ns 56.31 ns 25.40 10784 B 18.99
Jab 188.1 ns 1.61 ns 1.42 ns 0.71 432 B 0.76
DryIoc 419.1 ns 3.62 ns 3.39 ns 1.57 944 B 1.66
SimpleInjector 749.6 ns 1.66 ns 1.47 ns 2.81 1096 B 1.93
PureDI 202.9 ns 5.51 ns 5.16 ns 0.76 632 B 1.11
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 2.81GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Resolve Size Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 8 7.050 ns 0.0091 ns 0.0071 ns 0.91 - NA
Awaiten 8 7.780 ns 0.0134 ns 0.0119 ns 1.00 - NA
MsDI 8 7.248 ns 0.0113 ns 0.0101 ns 0.93 - NA
Autofac 8 137.448 ns 2.4831 ns 2.3227 ns 17.67 656 B NA
Jab 8 3.141 ns 0.0060 ns 0.0050 ns 0.40 - NA
PureDI 8 5.432 ns 0.0092 ns 0.0081 ns 0.70 - NA
DryIoc 8 9.071 ns 0.0166 ns 0.0147 ns 1.17 - NA
SimpleInjector 8 11.303 ns 0.0325 ns 0.0272 ns 1.45 - NA
baseline* 256 8.086 ns 0.0577 ns 0.0482 ns 0.96 - NA
Awaiten 256 8.447 ns 0.0119 ns 0.0093 ns 1.00 - NA
MsDI 256 7.240 ns 0.0188 ns 0.0157 ns 0.86 - NA
Autofac 256 144.863 ns 2.3103 ns 2.0480 ns 17.15 656 B NA
Jab 256 42.768 ns 0.0825 ns 0.0732 ns 5.06 - NA
PureDI 256 8.281 ns 0.0125 ns 0.0110 ns 0.98 - NA
DryIoc 256 9.032 ns 0.0127 ns 0.0099 ns 1.07 - NA
SimpleInjector 256 14.556 ns 0.1164 ns 0.1089 ns 1.72 - NA
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 9V74 2.87GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Build Size Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 8 20.91 ns 1.053 ns 0.985 ns 1.01 208 B 1.00
Awaiten 8 20.678 ns 0.3706 ns 0.3466 ns 1.00 208 B 1.00
MsDI 8 1,519.538 ns 22.1124 ns 18.4648 ns 73.50 5688 B 27.35
Autofac 8 34,344.387 ns 84.6261 ns 79.1593 ns 1,661.34 32482 B 156.16
Jab 8 8.366 ns 0.2037 ns 0.1806 ns 0.40 96 B 0.46
PureDI 8 17.099 ns 1.3799 ns 1.2907 ns 0.83 128 B 0.62
DryIoc 8 762.690 ns 13.3069 ns 12.4473 ns 36.89 1528 B 7.35
SimpleInjector 8 11,674.368 ns 112.7413 ns 105.4583 ns 564.72 24761 B 119.04
baseline* 256 171.22 ns 13.908 ns 13.009 ns 1.25 4176 B 1.00
Awaiten 256 136.735 ns 1.5229 ns 1.4245 ns 1.00 4176 B 1.00
MsDI 256 14,103.919 ns 205.5773 ns 192.2971 ns 103.16 61016 B 14.61
Autofac 256 823,979.551 ns 3,577.4380 ns 2,987.3228 ns 6,026.70 738333 B 176.80
Jab 256 63.416 ns 1.4321 ns 1.3396 ns 0.46 2080 B 0.50
PureDI 256 70.727 ns 0.5152 ns 0.4303 ns 0.52 2112 B 0.51
DryIoc 256 47,820.950 ns 502.0500 ns 445.0542 ns 349.77 80645 B 19.31
SimpleInjector 256 362,993.393 ns 3,845.0289 ns 3,596.6424 ns 2,654.98 573092 B 137.23

baseline* rows show the corresponding Awaiten benchmark from the most recent successful main branch build with results, for regression comparison.

…exity

Reading and checking one [InjectProperty] entry (its target, AWT215 and AWT177) moves into TryReadInjectPropertyTarget, so CollectInjectProperties only collects entries and handles AWT170 and AWT179. The behaviour is unchanged; this resolves the Sonar cognitive complexity finding (17 of 15).
@vbreuss
vbreuss added this pull request to stack #227 October 30, 2026 16:44
@sonarqubecloud

Copy link
Copy Markdown

@vbreuss
vbreuss merged commit b5c8c56 into main Oct 30, 2026
16 checks passed
@vbreuss
vbreuss deleted the refactor/share-awt215 branch October 30, 2026 17:00
@github-actions

Copy link
Copy Markdown

This is addressed in release v0.8.0.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant