From aa44c88d2e63c3ffd921d1cd97966cdf4401ea29 Mon Sep 17 00:00:00 2001 From: Glenn Watson <5834289+glennawatson@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:59:14 +1000 Subject: [PATCH] perf: halve the generator's time and allocations per pass --- .editorconfig | 2537 ++++++++++++++--- .gitattributes | 55 + .github/workflows/ci-build.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/release.yml | 8 +- CLAUDE.md | 127 +- src/Directory.Build.props | 13 +- src/Directory.Packages.props | 46 +- src/Polyfills/IsExternalInit.cs | 20 + src/Splat.DI.SourceGenerator.slnx | 4 +- .../Analyzers/AnalyzerHelpers.cs | 104 +- .../Analyzers/ConstructorAnalyzer.cs | 22 +- .../Analyzers/PropertyAnalyzer.cs | 27 +- .../CodeFixes/ConstructorCodeFixProvider.cs | 78 +- .../CodeFixes/PropertyCodeFixProvider.cs | 61 +- .../Constants.cs | 11 +- .../IsExternalInit.cs | 16 - .../Splat.DependencyInjection.Analyzer.csproj | 5 + .../CodeGeneration/CodeGenerator.cs | 417 ++- .../CodeGeneration/MarkerSource.cs | 211 ++ .../CodeGeneration/PooledBuilder.cs | 65 + .../CodeGeneration/SourceWriter.cs | 207 ++ .../CodeGeneration/SourceWriterExtensions.cs | 48 + .../Constants.cs | 245 +- .../DiagnosticWarnings.cs | 36 +- .../Generator.cs | 107 +- .../IsExternalInit.cs | 16 - .../MetadataExtractor.cs | 587 ++-- .../Models/ConstructorParameter.cs | 32 +- .../Models/DependencyKind.cs | 18 + .../Models/EquatableArray.cs | 163 +- .../Models/LazySingletonRegistrationInfo.cs | 34 - .../Models/LocationInfo.cs | 36 + .../Models/PropertyInjection.cs | 24 +- .../Models/RegistrationInfo.cs | 33 +- .../Models/RegistrationKind.cs | 15 + .../Models/RegistrationSite.cs | 14 + .../Models/TransientRegistrationInfo.cs | 32 - .../RegistrationValidator.cs | 400 ++- .../RoslynHelpers.cs | 340 +-- ...DependencyInjection.SourceGenerator.csproj | 5 + .../WellKnownSymbols.cs | 61 + src/benchmarks/README.md | 117 + .../Configs/BenchmarkProfiling.cs | 20 + .../Configs/ProfilerConfig.cs | 54 + .../Corpus/CorpusBuilder.cs | 261 ++ .../GenerationBenchmarks.cs | 143 + .../Program.cs | 18 + .../Runtime/Branch.cs | 19 + .../Runtime/IBranch.cs | 12 + .../Runtime/IKeyed.cs | 12 + .../Runtime/ILazyConsumer.cs | 12 + .../Runtime/ILeaf.cs | 12 + .../Runtime/ISingleton.cs | 12 + .../Runtime/ITree.cs | 12 + .../Runtime/Keyed.cs | 19 + .../Runtime/LazyConsumer.cs | 19 + .../Runtime/Leaf.cs | 15 + .../Runtime/RuntimeBenchmarks.cs | 106 + .../Runtime/RuntimeRegistrations.cs | 24 + .../Runtime/Singleton.cs | 19 + .../Runtime/Tree.cs | 27 + ...Splat.DI.SourceGenerator.Benchmarks.csproj | 28 + src/stylecop.json | 41 - .../ConsoleLogger.cs | 25 +- .../ILogger.cs | 12 +- .../IService.cs | 12 +- .../Program.cs | 25 +- .../ServiceImplementation.cs | 15 +- .../ServiceWithDependency.cs | 39 +- .../AnalyzerHelpersTests.cs | 257 +- .../AnalyzerTestHelper.cs | 81 +- .../AttributeOverridingMethodProxy.cs | 39 + .../CodeFixTestHelper.cs | 171 +- .../ConstructorAnalyzerTests.cs | 45 +- .../ConstructorCodeFixProviderTests.cs | 626 ++-- .../NullClassAttributeData.cs | 31 + .../PropertyAnalyzerTests.cs | 44 +- .../PropertyCodeFixProviderTests.cs | 212 +- .../TestUtilities.cs | 165 +- .../AssemblySetup.cs | 6 + .../CodeGeneration/CodeGeneratorTests.cs | 222 ++ .../CodeGeneration/PooledBuilderTests.cs | 45 + .../CodeGeneration/SourceWriterTests.cs | 69 + .../CodeGeneratorTests.cs | 274 -- .../DiagnosticWarningsTests.cs | 12 +- .../EquatableArrayTests.cs | 95 - .../ExtractionTests.cs | 376 +++ .../GeneratorCodeGenerationTests.cs | 332 --- .../GeneratorRun.cs | 79 + .../GeneratorSnapshot.cs | 198 ++ .../GeneratorTests.cs | 143 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CI_Test1#Splat.DI.Reg.g.verified.cs | 23 +- .../LS.CI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CI_Test2#Splat.DI.Reg.g.verified.cs | 23 +- .../LS.CI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 22 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...eArgument_Test1#Splat.DI.Reg.g.verified.cs | 26 +- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...eArgument_Test2#Splat.DI.Reg.g.verified.cs | 26 +- ...ITypeArgument_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 25 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.CIntPI_Test1#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CIntPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.CIntPI_Test2#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CIntPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 25 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CIntSetPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CIntSetPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 25 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CMPILM_Test1_EP#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test1_EP#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ....CMPILM_Test1_N#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test1_N#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ....CMPILM_Test1_P#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test1_P#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CMPILM_Test2_EP#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test2_EP#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ....CMPILM_Test2_N#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test2_N#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ....CMPILM_Test2_P#Splat.DI.Reg.g.verified.cs | 29 +- .../LS.CMPILM_Test2_P#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ctParameter=_EP#Splat.DI.Reg.g.verified.cs | 28 +- ...ntractParameter=_EP#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...actParameter=_N#Splat.DI.Reg.g.verified.cs | 28 +- ...ontractParameter=_N#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...actParameter=_P#Splat.DI.Reg.g.verified.cs | 28 +- ...ontractParameter=_P#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CMPI_Test1#Splat.DI.Reg.g.verified.cs | 28 +- .../LS.CMPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CMPI_Test2#Splat.DI.Reg.g.verified.cs | 28 +- .../LS.CMPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs | 27 - .../LS.CNPPIF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs | 27 - .../LS.CNPPIF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs | 27 - .../LS.CNPPSetIF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs | 27 - .../LS.CNPPSetIF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CPI_Test1#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../LS.CPI_Test2#Splat.DI.Reg.g.verified.cs | 26 +- .../LS.CPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 25 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...DependencyF_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...pendencyF_Test1#Splat.DI.Reg.g.verified.cs | 43 +- ...arDependencyF_Test1#Splat.DI.g.verified.cs | 194 -- .../LS.CircularDependencyF_Test1.verified.txt | 42 - ...DependencyF_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...pendencyF_Test2#Splat.DI.Reg.g.verified.cs | 43 +- ...arDependencyF_Test2#Splat.DI.g.verified.cs | 194 -- .../LS.CircularDependencyF_Test2.verified.txt | 42 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 33 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...ependencyF_contractParameter=.verified.txt | 42 - ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...nstructor_Test1#Splat.DI.Reg.g.verified.cs | 10 +- ....EConstructor_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...nstructor_Test2#Splat.DI.Reg.g.verified.cs | 10 +- ....EConstructor_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 10 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...nLSingleton_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...Singleton_Test1#Splat.DI.Reg.g.verified.cs | 12 +- ...yInLSingleton_Test1#Splat.DI.g.verified.cs | 194 -- ...eDependencyInLSingleton_Test1.verified.txt | 44 - ...nLSingleton_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...Singleton_Test2#Splat.DI.Reg.g.verified.cs | 12 +- ...yInLSingleton_Test2#Splat.DI.g.verified.cs | 194 -- ...eDependencyInLSingleton_Test2.verified.txt | 44 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 12 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...LSingleton_contractParameter=.verified.txt | 44 - .../LS.IRegMx_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.IRegMx_Test1#Splat.DI.Reg.g.verified.cs | 18 +- .../LS.IRegMx_Test1#Splat.DI.g.verified.cs | 194 -- .../LS.IRegMx_Test1.verified.txt | 44 - .../LS.IRegMx_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...LS.IRegMx_Test2#Splat.DI.Reg.g.verified.cs | 18 +- .../LS.IRegMx_Test2#Splat.DI.g.verified.cs | 194 -- .../LS.IRegMx_Test2.verified.txt | 44 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 18 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- .../LS.IRegMx_contractParameter=.verified.txt | 44 - ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...S.LPmRegL_Test1#Splat.DI.Reg.g.verified.cs | 31 +- .../LS.LPmRegL_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...S.LPmRegL_Test2#Splat.DI.Reg.g.verified.cs | 31 +- .../LS.LPmRegL_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 29 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...orNoAttrF_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...ructorNoAttrF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...orNoAttrF_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...ructorNoAttrF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...rNoAttrNonDIP_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...rNoAttrNonDIP_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...rWithAttr_Test1#Splat.DI.Reg.g.verified.cs | 22 +- ...uctorWithAttr_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...rWithAttr_Test2#Splat.DI.Reg.g.verified.cs | 22 +- ...uctorWithAttr_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 21 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...thMAttrsF_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...orWithMAttrsF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...thMAttrsF_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...orWithMAttrsF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...strations_Test1#Splat.DI.Reg.g.verified.cs | 45 +- ...Registrations_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...strations_Test2#Splat.DI.Reg.g.verified.cs | 45 +- ...Registrations_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 44 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...on_TestContract#Splat.DI.Reg.g.verified.cs | 26 +- ...gleton_TestContract#Splat.DI.g.verified.cs | 194 -- .../MetadataExtractorTests.cs | 771 ----- .../Models/ConstructorParameterTests.cs | 110 - .../Models/EquatableArrayTests.cs | 283 +- .../Models/LocationInfoTests.cs | 46 + .../Models/PropertyInjectionTests.cs | 74 - .../Models/RegistrationInfoTests.cs | 269 -- .../ModuleInitializer.cs | 25 - ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CI_Test1#Splat.DI.Reg.g.verified.cs | 18 +- .../R.CI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CI_Test2#Splat.DI.Reg.g.verified.cs | 18 +- .../R.CI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 16 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...eArgument_Test1#Splat.DI.Reg.g.verified.cs | 21 +- ...ITypeArgument_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...eArgument_Test2#Splat.DI.Reg.g.verified.cs | 21 +- ...ITypeArgument_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 19 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CIntPI_Test1#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CIntPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CIntPI_Test2#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CIntPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 19 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CIntSetPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CIntSetPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 19 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CMPI_Test1#Splat.DI.Reg.g.verified.cs | 23 +- .../R.CMPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CMPI_Test2#Splat.DI.Reg.g.verified.cs | 23 +- .../R.CMPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 21 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs | 27 - .../R.CNPPIF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs | 27 - .../R.CNPPIF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs | 27 - .../R.CNPPSetIF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs | 27 - .../R.CNPPSetIF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CPI_Test1#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CPI_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.CPI_Test2#Splat.DI.Reg.g.verified.cs | 21 +- .../R.CPI_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 19 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...DependencyF_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...pendencyF_Test1#Splat.DI.Reg.g.verified.cs | 32 +- ...arDependencyF_Test1#Splat.DI.g.verified.cs | 194 -- .../R.CircularDependencyF_Test1.verified.txt | 42 - ...DependencyF_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...pendencyF_Test2#Splat.DI.Reg.g.verified.cs | 32 +- ...arDependencyF_Test2#Splat.DI.g.verified.cs | 194 -- .../R.CircularDependencyF_Test2.verified.txt | 42 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 21 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...ependencyF_contractParameter=.verified.txt | 42 - ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ld_MyServiceKey#Splat.DI.Reg.g.verified.cs | 2 +- ...tField_MyServiceKey#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...SimpleName_Key1#Splat.DI.Reg.g.verified.cs | 2 +- ...WithSimpleName_Key1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tNamespace_Key1#Splat.DI.Reg.g.verified.cs | 2 +- ...erentNamespace_Key1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...on_MethodResult#Splat.DI.Reg.g.verified.cs | 2 +- ...cation_MethodResult#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ce_ContractName#Splat.DI.Reg.g.verified.cs | 2 +- ...espace_ContractName#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...nstructor_Test1#Splat.DI.Reg.g.verified.cs | 2 +- ....EConstructor_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...nstructor_Test2#Splat.DI.Reg.g.verified.cs | 2 +- ....EConstructor_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 2 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ..._MTypePms_Test1#Splat.DI.Reg.g.verified.cs | 2 +- ...Type_MTypePms_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ..._MTypePms_Test2#Splat.DI.Reg.g.verified.cs | 2 +- ...Type_MTypePms_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 2 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...edGeneric_Test1#Splat.DI.Reg.g.verified.cs | 2 +- ...NestedGeneric_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...edGeneric_Test2#Splat.DI.Reg.g.verified.cs | 2 +- ...NestedGeneric_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 2 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...gleTypePm_Test1#Splat.DI.Reg.g.verified.cs | 17 +- ..._SingleTypePm_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...gleTypePm_Test2#Splat.DI.Reg.g.verified.cs | 17 +- ..._SingleTypePm_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 15 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...eDependency_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ependency_Test1#Splat.DI.Reg.g.verified.cs | 7 +- ...bleDependency_Test1#Splat.DI.g.verified.cs | 194 -- ...R.IEnumerableDependency_Test1.verified.txt | 44 - ...eDependency_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ependency_Test2#Splat.DI.Reg.g.verified.cs | 7 +- ...bleDependency_Test2#Splat.DI.g.verified.cs | 194 -- ...R.IEnumerableDependency_Test2.verified.txt | 44 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 6 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...Dependency_contractParameter=.verified.txt | 44 - .../R.IRegMx_Test1#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.IRegMx_Test1#Splat.DI.Reg.g.verified.cs | 2 +- .../R.IRegMx_Test1#Splat.DI.g.verified.cs | 194 -- .../R.IRegMx_Test1.verified.txt | 44 - .../R.IRegMx_Test2#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - .../R.IRegMx_Test2#Splat.DI.Reg.g.verified.cs | 2 +- .../R.IRegMx_Test2#Splat.DI.g.verified.cs | 194 -- .../R.IRegMx_Test2.verified.txt | 44 - ...ontractParameter=#Diagnostics.verified.txt | 2 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 2 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- .../R.IRegMx_contractParameter=.verified.txt | 44 - ...antNotRegLF_Test1#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tNotRegLF_Test1#Splat.DI.Reg.g.verified.cs | 17 +- ...stantNotRegLF_Test1#Splat.DI.g.verified.cs | 194 -- .../R.LPmConstantNotRegLF_Test1.verified.txt | 23 - ...antNotRegLF_Test2#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tNotRegLF_Test2#Splat.DI.Reg.g.verified.cs | 17 +- ...stantNotRegLF_Test2#Splat.DI.g.verified.cs | 194 -- .../R.LPmConstantNotRegLF_Test2.verified.txt | 23 - ...ontractParameter=#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 15 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...ntNotRegLF_contractParameter=.verified.txt | 23 - ...LPmNotRegLF_Test1#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...mNotRegLF_Test1#Splat.DI.Reg.g.verified.cs | 23 +- ...R.LPmNotRegLF_Test1#Splat.DI.g.verified.cs | 194 -- .../R.LPmNotRegLF_Test1.verified.txt | 23 - ...LPmNotRegLF_Test2#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...mNotRegLF_Test2#Splat.DI.Reg.g.verified.cs | 23 +- ...R.LPmNotRegLF_Test2#Splat.DI.g.verified.cs | 194 -- .../R.LPmNotRegLF_Test2.verified.txt | 23 - ...ontractParameter=#Diagnostics.verified.txt | 1 + ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 21 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...PmNotRegLF_contractParameter=.verified.txt | 23 - ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...orNoAttrF_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...ructorNoAttrF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...orNoAttrF_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...ructorNoAttrF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...rNoAttrNonDIP_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...rNoAttrNonDIP_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...rWithAttr_Test1#Splat.DI.Reg.g.verified.cs | 17 +- ...uctorWithAttr_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...rWithAttr_Test2#Splat.DI.Reg.g.verified.cs | 17 +- ...uctorWithAttr_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 15 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...thMAttrsF_Test1#Splat.DI.Reg.g.verified.cs | 27 - ...orWithMAttrsF_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...thMAttrsF_Test2#Splat.DI.Reg.g.verified.cs | 27 - ...orWithMAttrsF_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 27 - ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...strations_Test1#Splat.DI.Reg.g.verified.cs | 30 +- ...Registrations_Test1#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...strations_Test2#Splat.DI.Reg.g.verified.cs | 30 +- ...Registrations_Test2#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...tractParameter=#Splat.DI.Reg.g.verified.cs | 26 +- ..._contractParameter=#Splat.DI.g.verified.cs | 194 -- ...deAnalysis.EmbeddedAttribute.g.verified.cs | 18 - ...ct_TestContract#Splat.DI.Reg.g.verified.cs | 20 +- ...ntract_TestContract#Splat.DI.g.verified.cs | 194 -- .../RegisterLazySingletonTests.cs | 39 +- .../RegisterTests.cs | 51 +- .../RegistrationValidatorTests.cs | 114 + .../RoslynHelpersTests.cs | 1285 --------- ...CodeAnalysis.EmbeddedAttribute.verified.cs | 7 + ...WritesFixedSources#Splat.DI.g.verified.cs} | 2 +- .../SnapshotTests.cs | 48 + ...encyInjection.SourceGenerator.Tests.csproj | 18 +- .../TestBase.cs | 133 +- .../TestHelper.cs | 400 ++- 564 files changed, 9505 insertions(+), 37608 deletions(-) create mode 100644 .gitattributes create mode 100644 src/Polyfills/IsExternalInit.cs delete mode 100644 src/Splat.DependencyInjection.Analyzer/IsExternalInit.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/MarkerSource.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/PooledBuilder.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriter.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriterExtensions.cs delete mode 100644 src/Splat.DependencyInjection.SourceGenerator/IsExternalInit.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/DependencyKind.cs delete mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/LazySingletonRegistrationInfo.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/LocationInfo.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationKind.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationSite.cs delete mode 100644 src/Splat.DependencyInjection.SourceGenerator/Models/TransientRegistrationInfo.cs create mode 100644 src/Splat.DependencyInjection.SourceGenerator/WellKnownSymbols.cs create mode 100644 src/benchmarks/README.md create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/BenchmarkProfiling.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/ProfilerConfig.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Corpus/CorpusBuilder.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/GenerationBenchmarks.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Program.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Branch.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IBranch.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IKeyed.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILazyConsumer.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILeaf.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ISingleton.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ITree.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Keyed.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/LazyConsumer.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Leaf.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeBenchmarks.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeRegistrations.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Singleton.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Tree.cs create mode 100644 src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Splat.DI.SourceGenerator.Benchmarks.csproj delete mode 100644 src/stylecop.json create mode 100644 src/tests/Splat.DependencyInjection.Analyzer.Tests/AttributeOverridingMethodProxy.cs create mode 100644 src/tests/Splat.DependencyInjection.Analyzer.Tests/NullClassAttributeData.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/AssemblySetup.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/CodeGeneratorTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/PooledBuilderTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/SourceWriterTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneratorTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/EquatableArrayTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ExtractionTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorCodeGenerationTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorRun.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorSnapshot.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.g.verified.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.g.verified.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/MetadataExtractorTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/ConstructorParameterTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/LocationInfoTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/PropertyInjectionTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/RegistrationInfoTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ModuleInitializer.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.g.verified.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.g.verified.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2.verified.txt create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Diagnostics.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=.verified.txt delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.g.verified.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegistrationValidatorTests.cs delete mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RoslynHelpersTests.cs create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Microsoft.CodeAnalysis.EmbeddedAttribute.verified.cs rename src/tests/Splat.DependencyInjection.SourceGenerator.Tests/{LS.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs => SnapshotTests.WritesFixedSources#Splat.DI.g.verified.cs} (99%) create mode 100644 src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.cs diff --git a/.editorconfig b/.editorconfig index 77a6c401..db7d37e9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,8 @@ root = true # Default settings ############################################# [*] +charset = utf-8 +end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 @@ -78,8 +80,15 @@ dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Local constants should be PascalCase +dotnet_naming_rule.local_constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_constants_should_be_pascal_case.symbols = local_constants +dotnet_naming_rule.local_constants_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.required_modifiers = const + # Static fields should have s_ prefix -dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +dotnet_naming_rule.static_fields_should_have_prefix.severity = none dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style dotnet_naming_symbols.static_fields.applicable_kinds = field @@ -105,31 +114,20 @@ dotnet_sort_system_directives_first = true csharp_prefer_braces = true:silent csharp_preserve_single_line_blocks = true:none csharp_preserve_single_line_statements = false:none -csharp_prefer_static_local_function = true:suggestion -csharp_prefer_simple_using_statement = false:none -csharp_style_prefer_switch_expression = true:suggestion ################### # Code quality ################### -dotnet_style_readonly_field = true:suggestion dotnet_code_quality_unused_parameters = non_public:suggestion ################### # Expression-level preferences ################### -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_auto_properties = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -csharp_prefer_simple_default_expression = true:suggestion ################### # Expression-bodied members @@ -143,19 +141,6 @@ csharp_style_expression_bodied_accessors = true:suggestion csharp_style_expression_bodied_lambdas = true:suggestion csharp_style_expression_bodied_local_functions = true:suggestion -################### -# Pattern matching -################### -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion - -################### -# Null checking preferences -################### -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion - ################### # Other features ################### @@ -201,18 +186,49 @@ dotnet_diagnostic.AvoidAsyncVoid.severity = suggestion ################### # Microsoft .NET Analyzers (CA) - Design Rules ################### -dotnet_diagnostic.CA1000.severity = none # Do not declare static members on generic types +dotnet_diagnostic.CA1000.severity = none # Do not declare static members on generic types — common factory pattern dotnet_diagnostic.CA1001.severity = error # Types that own disposable fields should be disposable +dotnet_diagnostic.CA1002.severity = none # Do not expose generic lists — we deliberately expose List; interface-based collections are an older convention we don't follow +dotnet_diagnostic.CA1003.severity = error # Use generic event handler instances +dotnet_diagnostic.CA1005.severity = error # Avoid excessive parameters on generic types +dotnet_diagnostic.CA1008.severity = error # Enums should have zero value +dotnet_diagnostic.CA1010.severity = none # Collections should implement generic interface — we deliberately expose concrete collection types; interface-based collections are an older convention we don't follow +dotnet_diagnostic.CA1012.severity = error # Abstract types should not have public constructors +dotnet_diagnostic.CA1014.severity = none # Mark assemblies with CLSCompliantAttribute — we don't ship CLS-compliant assemblies dotnet_diagnostic.CA1016.severity = error # Mark assemblies with AssemblyVersionAttribute +dotnet_diagnostic.CA1017.severity = none # Mark assemblies with ComVisibleAttribute — we don't ship COM-visible assemblies +dotnet_diagnostic.CA1018.severity = error # Mark attributes with AttributeUsageAttribute +dotnet_diagnostic.CA1019.severity = error # Define accessors for attribute arguments +dotnet_diagnostic.CA1021.severity = none # Avoid out parameters - disabled - needed for the zero-allocation idiom in Try/Find APIs and other performance-critical paths +dotnet_diagnostic.CA1024.severity = error # Use properties where appropriate dotnet_diagnostic.CA1027.severity = error # Mark enums with FlagsAttribute -dotnet_diagnostic.CA1030.severity = none # Use events where appropriate -dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types -dotnet_diagnostic.CA1033.severity = none # Interface methods should be callable by child types -dotnet_diagnostic.CA1036.severity = none # Override methods on comparable types +dotnet_diagnostic.CA1028.severity = error # Enum storage should be Int32 +dotnet_diagnostic.CA1030.severity = none # Use events where appropriate — we use Rx observables instead of CLR events +dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types — required at logging/dispose/IO boundaries +dotnet_diagnostic.CA1032.severity = error # Implement standard exception constructors +dotnet_diagnostic.CA1033.severity = none # Interface methods should be callable by child types — explicit interface implementations are a deliberate design choice +dotnet_diagnostic.CA1034.severity = none # Nested types should not be visible — public nested types are sometimes the cleanest API (e.g. interface-scoped exception helpers) +dotnet_diagnostic.CA1036.severity = none # Override methods on comparable types — relational operators rarely meaningful for our types +dotnet_diagnostic.CA1040.severity = error # Avoid empty interfaces +dotnet_diagnostic.CA1041.severity = error # Provide ObsoleteAttribute message +dotnet_diagnostic.CA1043.severity = error # Use integral or string argument for indexers +dotnet_diagnostic.CA1044.severity = error # Properties should not be write only +dotnet_diagnostic.CA1045.severity = error # Do not pass types by reference +dotnet_diagnostic.CA1046.severity = error # Do not overload operator equals on reference types +dotnet_diagnostic.CA1047.severity = error # Do not declare protected member in sealed type +dotnet_diagnostic.CA1048.severity = error # Do not declare virtual members in sealed types +dotnet_diagnostic.CA1050.severity = error # Declare types in namespaces +dotnet_diagnostic.CA1051.severity = error # Do not declare visible instance fields +dotnet_diagnostic.CA1052.severity = error # Static holder types should be sealed +dotnet_diagnostic.CA1053.severity = error # Static holder types should not have constructors +dotnet_diagnostic.CA1054.severity = suggestion # URI parameters should not be strings +dotnet_diagnostic.CA1055.severity = suggestion # URI return values should not be strings dotnet_diagnostic.CA1056.severity = suggestion # URI properties should not be strings +dotnet_diagnostic.CA1058.severity = error # Types should not extend certain base types +dotnet_diagnostic.CA1059.severity = error # Members should not expose certain concrete types dotnet_diagnostic.CA1060.severity = error # Move P/Invokes to NativeMethods class dotnet_diagnostic.CA1061.severity = error # Do not hide base class methods -dotnet_diagnostic.CA1062.severity = error # Validate arguments of public methods +dotnet_diagnostic.CA1062.severity = none # Validate arguments of public methods - Nullable=enable + we own every consumer, so the compiler already guarantees non-null params dotnet_diagnostic.CA1063.severity = error # Implement IDisposable correctly dotnet_diagnostic.CA1064.severity = error # Exceptions should be public dotnet_diagnostic.CA1065.severity = error # Do not raise exceptions in unexpected locations @@ -220,30 +236,13 @@ dotnet_diagnostic.CA1066.severity = error # Implement IEquatable when overriding dotnet_diagnostic.CA1067.severity = error # Override Equals when implementing IEquatable dotnet_diagnostic.CA1068.severity = error # CancellationToken parameters must come last dotnet_diagnostic.CA1069.severity = error # Enums should not have duplicate values -dotnet_diagnostic.CA2000.severity = suggestion # Dispose objects before losing scope -dotnet_diagnostic.CA2002.severity = error # Do not lock on objects with weak identity -dotnet_diagnostic.CA2011.severity = error # Do not assign property within its setter -dotnet_diagnostic.CA2012.severity = error # Use ValueTasks correctly -dotnet_diagnostic.CA2013.severity = error # Do not use ReferenceEquals with value types -dotnet_diagnostic.CA2014.severity = error # Do not use stackalloc in loops -dotnet_diagnostic.CA2015.severity = error # Do not define finalizers for types derived from MemoryManager -dotnet_diagnostic.CA2016.severity = error # Forward the CancellationToken parameter to methods that take one -dotnet_diagnostic.CA2200.severity = error # Rethrow to preserve stack details -dotnet_diagnostic.CA2213.severity = error # Disposable fields should be disposed -dotnet_diagnostic.CA2214.severity = error # Do not call overridable methods in constructors -dotnet_diagnostic.CA2216.severity = error # Disposable types should declare finalizer -dotnet_diagnostic.CA2229.severity = error # Implement serialization constructors -dotnet_diagnostic.CA2231.severity = error # Overload operator equals on overriding ValueType.Equals -dotnet_diagnostic.CA2235.severity = error # Mark all non-serializable fields -dotnet_diagnostic.CA2237.severity = error # Mark ISerializable types with SerializableAttribute -dotnet_diagnostic.CA2241.severity = error # Provide correct arguments to formatting methods -dotnet_diagnostic.CA2242.severity = error # Test for NaN correctly +dotnet_diagnostic.CA1070.severity = error # Do not declare event fields as virtual ################### # Microsoft .NET Analyzers (CA) - Globalization Rules ################### -dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters -dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters — we don't ship localized resources +dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase — ToLowerInvariant is correct for filesystem path / cache key normalization ################### # Microsoft .NET Analyzers (CA) - Interoperability Rules @@ -253,44 +252,178 @@ dotnet_diagnostic.CA1401.severity = error # P/Invokes should not be visible ################### # Microsoft .NET Analyzers (CA) - Maintainability Rules ################### +dotnet_diagnostic.CA1500.severity = error # Variable names should not match field names +dotnet_diagnostic.CA1501.severity = none # Avoid excessive inheritance — disabled because the analyzer noticeably slows down the build +dotnet_diagnostic.CA1502.severity = none # Avoid excessive complexity — disabled because the analyzer noticeably slows down the build +dotnet_diagnostic.CA1505.severity = error # Avoid unmaintainable code +dotnet_diagnostic.CA1506.severity = none # Avoid excessive class coupling — adds little signal here, mostly trips on legitimate orchestration code dotnet_diagnostic.CA1507.severity = error # Use nameof in place of string +dotnet_diagnostic.CA1508.severity = error # Avoid dead conditional code +dotnet_diagnostic.CA1509.severity = error # Invalid entry in code metrics configuration file +dotnet_diagnostic.CA1510.severity = none # Use ArgumentNullException throw helper — disabled because we target older TFMs and use ArgumentExceptionHelper for cross-platform parity +dotnet_diagnostic.CA1511.severity = none # Use ArgumentException throw helper — disabled because we target older TFMs and use ArgumentExceptionHelper for cross-platform parity +dotnet_diagnostic.CA1512.severity = none # Use ArgumentOutOfRangeException throw helper — disabled because we target older TFMs and use ArgumentExceptionHelper for cross-platform parity +dotnet_diagnostic.CA1513.severity = none # Use ObjectDisposedException throw helper — disabled because we target older TFMs and use ArgumentExceptionHelper for cross-platform parity +dotnet_diagnostic.CA1514.severity = error # Avoid redundant length argument +dotnet_diagnostic.CA1515.severity = none # Consider making public types internal — interferes with tests and reflection-discovered types (BenchmarkDotNet, TUnit, etc.) +dotnet_diagnostic.CA1516.severity = error # Use cross-platform intrinsics ################### # Microsoft .NET Analyzers (CA) - Naming Rules ################### dotnet_diagnostic.CA1710.severity = suggestion # Identifiers should have correct suffix -dotnet_diagnostic.CA1724.severity = none # Type Names Should Not Match Namespaces +dotnet_diagnostic.CA1724.severity = none # Type Names Should Not Match Namespaces — namespace/type name overlap is intentional API surface ################### # Microsoft .NET Analyzers (CA) - Performance Rules ################### -dotnet_diagnostic.CA1802.severity = error # Use Literals Where Appropriate +dotnet_diagnostic.CA1802.severity = error # Use literals where appropriate dotnet_diagnostic.CA1805.severity = error # Do not initialize unnecessarily -dotnet_diagnostic.CA1810.severity = none # Initialize reference type static fields inline +dotnet_diagnostic.CA1806.severity = error # Do not ignore method results +dotnet_diagnostic.CA1810.severity = none # Initialize reference type static fields inline — explicit static constructors are deliberate in some types dotnet_diagnostic.CA1812.severity = error # Avoid uninstantiated internal classes dotnet_diagnostic.CA1813.severity = error # Avoid unsealed attributes dotnet_diagnostic.CA1814.severity = error # Prefer jagged arrays over multidimensional dotnet_diagnostic.CA1815.severity = error # Override equals and operator equals on value types +dotnet_diagnostic.CA1819.severity = none # Properties should not return arrays — incompatible with the RxUI/sqlite-net mapping style we use throughout the codebase +dotnet_diagnostic.CA1820.severity = error # Test for empty strings using string length dotnet_diagnostic.CA1821.severity = error # Remove empty finalizers dotnet_diagnostic.CA1822.severity = error # Mark members as static +dotnet_diagnostic.CA1823.severity = error # Avoid unused private fields +dotnet_diagnostic.CA1824.severity = error # Mark assemblies with NeutralResourcesLanguageAttribute dotnet_diagnostic.CA1825.severity = error # Avoid zero-length array allocations dotnet_diagnostic.CA1826.severity = error # Use property instead of Linq Enumerable method dotnet_diagnostic.CA1827.severity = error # Do not use Count/LongCount when Any can be used dotnet_diagnostic.CA1828.severity = error # Do not use CountAsync/LongCountAsync when AnyAsync can be used dotnet_diagnostic.CA1829.severity = error # Use Length/Count property instead of Enumerable.Count method dotnet_diagnostic.CA1830.severity = error # Prefer strongly-typed Append and Insert method overloads on StringBuilder -dotnet_diagnostic.CA1831.severity = error # Use AsSpan instead of Range-based indexers for string -dotnet_diagnostic.CA1832.severity = error # Use AsSpan or AsMemory instead of Range-based indexers for ReadOnlySpan/Memory -dotnet_diagnostic.CA1833.severity = error # Use AsSpan or AsMemory instead of Range-based indexers for Span/Memory +dotnet_diagnostic.CA1831.severity = error # Use AsSpan instead of Range-based indexers for string when appropriate +dotnet_diagnostic.CA1832.severity = error # Use AsSpan or AsMemory instead of Range-based indexers for getting ReadOnlySpan or ReadOnlyMemory portion of an array +dotnet_diagnostic.CA1833.severity = error # Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array dotnet_diagnostic.CA1834.severity = error # Use StringBuilder.Append(char) for single character strings -dotnet_diagnostic.CA1835.severity = error # Prefer Memory-based overloads for ReadAsync and WriteAsync +dotnet_diagnostic.CA1835.severity = error # Prefer the memory-based overloads of ReadAsync/WriteAsync methods in stream-based classes dotnet_diagnostic.CA1836.severity = error # Prefer IsEmpty over Count when available dotnet_diagnostic.CA1837.severity = error # Use Environment.ProcessId instead of Process.GetCurrentProcess().Id dotnet_diagnostic.CA1838.severity = error # Avoid StringBuilder parameters for P/Invokes -dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task +dotnet_diagnostic.CA1839.severity = error # Use Environment.ProcessPath instead of Process.GetCurrentProcess().MainModule.FileName +dotnet_diagnostic.CA1840.severity = error # Use Environment.CurrentManagedThreadId instead of Thread.CurrentThread.ManagedThreadId +dotnet_diagnostic.CA1841.severity = error # Prefer Dictionary.Contains methods +dotnet_diagnostic.CA1842.severity = error # Do not use 'WhenAll' with a single task +dotnet_diagnostic.CA1843.severity = error # Do not use 'WaitAll' with a single task +dotnet_diagnostic.CA1844.severity = error # Provide memory-based overrides of async methods when subclassing 'Stream' +dotnet_diagnostic.CA1845.severity = error # Use span-based 'string.Concat' +dotnet_diagnostic.CA1846.severity = error # Prefer AsSpan over Substring +dotnet_diagnostic.CA1847.severity = none # Use char literal for a single character lookup — disabled because the string.Contains(char) overload doesn't exist on .NET Framework / netstandard2.0 and we target both +dotnet_diagnostic.CA1848.severity = error # Use the LoggerMessage delegates +dotnet_diagnostic.CA1849.severity = error # Call async methods when in an async method +dotnet_diagnostic.CA1850.severity = error # Prefer static HashData method over ComputeHash +dotnet_diagnostic.CA1851.severity = error # Possible multiple enumerations of IEnumerable collection +dotnet_diagnostic.CA1852.severity = error # Seal internal types +dotnet_code_quality.CA1852.api_surface = private, internal # only flag non-public classes; public classes stay open for inheritance +dotnet_diagnostic.CA1853.severity = error # Unnecessary call to 'Dictionary.ContainsKey(key)' +dotnet_diagnostic.CA1854.severity = error # Prefer the IDictionary.TryGetValue(TKey, out TValue) method +dotnet_diagnostic.CA1855.severity = error # Prefer 'Clear' over 'Fill' +dotnet_diagnostic.CA1856.severity = error # Incorrect usage of ConstantExpected attribute +dotnet_diagnostic.CA1857.severity = error # A constant is expected for the parameter +dotnet_diagnostic.CA1858.severity = error # Use 'StartsWith' instead of 'IndexOf' +dotnet_diagnostic.CA1859.severity = error # Use concrete types when possible for improved performance +dotnet_diagnostic.CA1860.severity = error # Avoid using 'Enumerable.Any()' extension method +dotnet_diagnostic.CA1861.severity = error # Avoid constant arrays as arguments +dotnet_diagnostic.CA1862.severity = error # Use the 'StringComparison' method overloads to perform case-insensitive string comparisons +dotnet_diagnostic.CA1863.severity = error # Use 'CompositeFormat' +dotnet_diagnostic.CA1864.severity = error # Prefer the 'IDictionary.TryAdd(TKey, TValue)' method +dotnet_diagnostic.CA1865.severity = none # Use char overload (string.StartsWith) — disabled because the string.StartsWith(char) overload doesn't exist on .NET Framework / netstandard2.0 and we target both +dotnet_diagnostic.CA1866.severity = none # Use char overload (string.EndsWith) — disabled because the string.EndsWith(char) overload doesn't exist on .NET Framework / netstandard2.0 and we target both +dotnet_diagnostic.CA1867.severity = none # Use char overload (string.IndexOf / string.LastIndexOf) — disabled because the char overloads don't exist on .NET Framework / netstandard2.0 and we target both +dotnet_diagnostic.CA1868.severity = error # Unnecessary call to 'Contains' for sets +dotnet_diagnostic.CA1869.severity = error # Cache and reuse 'JsonSerializerOptions' instances +dotnet_diagnostic.CA1870.severity = error # Use a cached 'SearchValues' instance +dotnet_diagnostic.CA1871.severity = error # Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull' +dotnet_diagnostic.CA1872.severity = error # Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' +dotnet_diagnostic.CA1873.severity = error # Avoid potentially expensive evaluation of arguments to 'Debug.Assert' +dotnet_diagnostic.CA1874.severity = error # Use 'Regex.IsMatch' +dotnet_diagnostic.CA1875.severity = error # Use 'Regex.Count' +dotnet_diagnostic.CA1877.severity = error # Use 'Encoding.GetString' instead of 'Encoding.GetChars' + +################### +# Microsoft .NET Analyzers (CA) - Reliability Rules +################### +dotnet_diagnostic.CA2000.severity = suggestion # Dispose objects before losing scope +dotnet_diagnostic.CA2002.severity = error # Do not lock on objects with weak identity +dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task — Rx and library callers drive synchronization context themselves dotnet_diagnostic.CA2008.severity = error # Do not create tasks without passing a TaskScheduler dotnet_diagnostic.CA2009.severity = error # Do not call ToImmutableCollection on an ImmutableCollection value +dotnet_diagnostic.CA2011.severity = error # Do not assign property within its setter +dotnet_diagnostic.CA2012.severity = error # Use ValueTasks correctly +dotnet_diagnostic.CA2013.severity = error # Do not use ReferenceEquals with value types +dotnet_diagnostic.CA2014.severity = error # Do not use stackalloc in loops +dotnet_diagnostic.CA2015.severity = error # Do not define finalizers for types derived from MemoryManager +dotnet_diagnostic.CA2016.severity = error # Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.CA2017.severity = error # Parameter count mismatch +dotnet_diagnostic.CA2018.severity = error # The 'count' argument to 'Buffer.BlockCopy' should specify the number of bytes to copy +dotnet_diagnostic.CA2019.severity = error # Improper 'ThreadStatic' field initialization +dotnet_diagnostic.CA2020.severity = error # Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr +dotnet_diagnostic.CA2021.severity = error # Don't call Enumerable.Cast or Enumerable.OfType with incompatible types +dotnet_diagnostic.CA2022.severity = error # Avoid inexact read with 'Stream.Read' +dotnet_diagnostic.CA2023.severity = error # Invalid braces in message template +dotnet_diagnostic.CA2024.severity = error # Do not use 'StreamReader.EndOfStream' in async methods +dotnet_diagnostic.CA2025.severity = error # Do not pass 'IDisposable' instances into unawaited tasks +dotnet_diagnostic.CA2026.severity = error # Do not use methods or types annotated with [RequiresDynamicCode] in code that uses [RequiresDynamicCode] + +################### +# Microsoft .NET Analyzers (CA) - Usage Rules +################### +dotnet_diagnostic.CA1801.severity = error # Review unused parameters +dotnet_code_quality.CA1801.api_surface = private, internal # only flag non-public APIs so we don't break public signatures +dotnet_diagnostic.CA1816.severity = error # Call GC.SuppressFinalize correctly +dotnet_diagnostic.CA2200.severity = error # Rethrow to preserve stack details +dotnet_diagnostic.CA2201.severity = error # Do not raise reserved exception types dotnet_diagnostic.CA2207.severity = error # Initialize value type static fields inline +dotnet_diagnostic.CA2208.severity = none # Instantiate argument exceptions correctly — too sensitive: flags valid context-forwarding nameof(arg.Property) patterns +dotnet_diagnostic.CA2211.severity = error # Non-constant fields should not be visible +dotnet_diagnostic.CA2213.severity = error # Disposable fields should be disposed +dotnet_diagnostic.CA2214.severity = error # Do not call overridable methods in constructors +dotnet_diagnostic.CA2215.severity = error # Dispose methods should call base class dispose +dotnet_diagnostic.CA2216.severity = error # Disposable types should declare finalizer +dotnet_diagnostic.CA2217.severity = error # Do not mark enums with FlagsAttribute +dotnet_diagnostic.CA2218.severity = error # Override GetHashCode on overriding Equals +dotnet_diagnostic.CA2219.severity = error # Do not raise exceptions in finally clauses +dotnet_diagnostic.CA2224.severity = error # Override Equals on overloading operator equals +dotnet_diagnostic.CA2225.severity = error # Operator overloads have named alternates +dotnet_diagnostic.CA2226.severity = error # Operators should have symmetrical overloads +dotnet_diagnostic.CA2227.severity = none # Collection properties should be read only — settable collection properties are common in our DTOs and config types +dotnet_diagnostic.CA2231.severity = error # Overload operator equals on overriding ValueType.Equals +dotnet_diagnostic.CA2234.severity = error # Pass System.Uri objects instead of strings +dotnet_diagnostic.CA2241.severity = error # Provide correct arguments to formatting methods +dotnet_diagnostic.CA2242.severity = error # Test for NaN correctly +dotnet_diagnostic.CA2243.severity = error # Attribute string literals should parse correctly +dotnet_diagnostic.CA2244.severity = error # Do not duplicate indexed element initializations +dotnet_diagnostic.CA2245.severity = error # Do not assign a property to itself +dotnet_diagnostic.CA2246.severity = error # Do not assign a symbol and its member in the same statement +dotnet_diagnostic.CA2247.severity = error # Argument passed to TaskCompletionSource constructor should be TaskCreationOptions enum +dotnet_diagnostic.CA2248.severity = error # Provide correct enum argument to Enum.HasFlag +dotnet_diagnostic.CA2249.severity = error # Use String.Contains instead of String.IndexOf for substring checks +dotnet_diagnostic.CA2250.severity = error # Use ThrowIfCancellationRequested +dotnet_diagnostic.CA2251.severity = error # Use String.Equals over String.Compare +dotnet_diagnostic.CA2252.severity = error # Opt in to preview features before using them +dotnet_diagnostic.CA2253.severity = error # Named placeholders should not be numeric values +dotnet_diagnostic.CA2254.severity = error # Template should be a static expression +dotnet_diagnostic.CA2255.severity = error # The 'ModuleInitializer' attribute should not be used in libraries +dotnet_diagnostic.CA2256.severity = error # All members declared in parent interfaces must have an implementation in a 'DynamicInterfaceCastableImplementation' interface +dotnet_diagnostic.CA2257.severity = error # Members defined in a type with the 'DynamicInterfaceCastableImplementationAttribute' should be 'static' +dotnet_diagnostic.CA2258.severity = error # Providing a 'DynamicInterfaceCastableImplementation' interface in Visual Basic is unsupported +dotnet_diagnostic.CA2259.severity = error # 'ThreadStatic' only affects static fields +dotnet_diagnostic.CA2260.severity = error # Implement generic math interfaces correctly +dotnet_diagnostic.CA2261.severity = error # Do not use 'ConfigureAwaitOptions.SuppressThrowing' with 'Task' +dotnet_diagnostic.CA2262.severity = error # Set 'MaxResponseHeadersLength' properly +dotnet_diagnostic.CA2263.severity = error # Prefer generic overload when type is known +dotnet_diagnostic.CA2264.severity = error # Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull' +dotnet_diagnostic.CA2265.severity = error # Do not compare Span to 'null' or 'default' +dotnet_diagnostic.CA2266.severity = error # Do not consume the result of 'Span.Enumerator.MoveNext()' more than once +dotnet_diagnostic.CA2267.severity = error # Member should not be marked with 'StaticAttribute' +dotnet_diagnostic.CA2268.severity = error # Use 'string.Equals(string, string, StringComparison)' instead of the implicit ordinal overload +# Skipped (deprecated ISerializable formatter): CA2229 Implement serialization constructors, +# CA2235 Mark all non-serializable fields, CA2237 Mark ISerializable types with SerializableAttribute. ################### # Microsoft .NET Analyzers (CA) - Security Rules @@ -345,25 +478,35 @@ dotnet_diagnostic.CA5362.severity = error # Potential reference cycle in deseria dotnet_diagnostic.CA5350.severity = error # Do not use weak cryptographic algorithms (SHA1, RIPEMD160, TripleDES) dotnet_diagnostic.CA5351.severity = error # Do not use broken cryptographic algorithms (MD5, DES, RC2) dotnet_diagnostic.CA5358.severity = error # Do not use unsafe cipher modes (ECB, OFB, CFB) +dotnet_diagnostic.CA5373.severity = error # Do not use obsolete key derivation function +dotnet_diagnostic.CA5379.severity = error # Ensure key derivation function algorithm is sufficiently strong dotnet_diagnostic.CA5384.severity = error # Do not use Digital Signature Algorithm (DSA) dotnet_diagnostic.CA5385.severity = error # Use RSA algorithm with sufficient key size (>= 2048 bits) +dotnet_diagnostic.CA5387.severity = error # Do not use weak key derivation function with insufficient iteration count +dotnet_diagnostic.CA5388.severity = error # Ensure sufficient iteration count when using weak key derivation function dotnet_diagnostic.CA5390.severity = error # Do not hard-code encryption key dotnet_diagnostic.CA5394.severity = error # Do not use insecure randomness (use RNGCryptoServiceProvider) dotnet_diagnostic.CA5401.severity = error # Do not use CreateEncryptor with non-default IV +dotnet_diagnostic.CA5402.severity = error # Use CreateEncryptor with the default IV dotnet_diagnostic.CA5403.severity = error # Do not hard-code certificate -dotnet_diagnostic.CA5373.severity = error # Do not use obsolete key derivation function # TLS/SSL Protocol Security dotnet_diagnostic.CA5359.severity = error # Do not disable certificate validation dotnet_diagnostic.CA5361.severity = error # Do not disable SChannel use of strong crypto dotnet_diagnostic.CA5364.severity = error # Do not use deprecated security protocols (TLS 1.0, TLS 1.1, SSL3) dotnet_diagnostic.CA5378.severity = error # Do not disable ServicePointManagerSecurityProtocols +dotnet_diagnostic.CA5380.severity = error # Do not add certificates to root store +dotnet_diagnostic.CA5381.severity = error # Ensure certificates are not added to root store dotnet_diagnostic.CA5386.severity = error # Avoid hardcoding SecurityProtocolType value dotnet_diagnostic.CA5397.severity = error # Do not use deprecated SslProtocols values dotnet_diagnostic.CA5398.severity = error # Avoid hardcoded SslProtocols values dotnet_diagnostic.CA5399.severity = error # Definitely disable HttpClient certificate revocation list check -dotnet_diagnostic.CA5380.severity = error # Do not add certificates to root store -dotnet_diagnostic.CA5381.severity = error # Ensure certificates are not added to root store +dotnet_diagnostic.CA5400.severity = error # Ensure HttpClient certificate revocation list check is not disabled + +# Azure Storage / Shared Access Signature +dotnet_diagnostic.CA5375.severity = error # Do not use account shared access signature +dotnet_diagnostic.CA5376.severity = error # Use SharedAccessProtocol HttpsOnly +dotnet_diagnostic.CA5377.severity = error # Use container level access policy # XML Security dotnet_diagnostic.CA3061.severity = error # Do not add schema by URL @@ -382,9 +525,15 @@ dotnet_diagnostic.CA3147.severity = error # Mark verb handlers with ValidateAnti dotnet_diagnostic.CA5363.severity = error # Do not disable request validation dotnet_diagnostic.CA5365.severity = error # Do not disable HTTP header checking dotnet_diagnostic.CA5368.severity = error # Set ViewStateUserKey for classes derived from Page +dotnet_diagnostic.CA5382.severity = error # Use secure cookies in ASP.NET Core +dotnet_diagnostic.CA5383.severity = error # Ensure use of secure cookies in ASP.NET Core +dotnet_diagnostic.CA5391.severity = error # Use antiforgery tokens in ASP.NET Core MVC controllers +dotnet_diagnostic.CA5395.severity = error # Miss HttpVerb attribute for action methods +dotnet_diagnostic.CA5396.severity = error # Set HttpOnly to true for HttpCookie # P/Invoke & DLL Security dotnet_diagnostic.CA2101.severity = error # Specify marshalling for P/Invoke string arguments +dotnet_diagnostic.CA5392.severity = error # Use DefaultDllImportSearchPaths attribute for P/Invokes dotnet_diagnostic.CA5393.severity = error # Do not use unsafe DllImportSearchPath value # Archive & File Security @@ -401,404 +550,1713 @@ dotnet_diagnostic.CA2153.severity = error # Do not catch corrupted state excepti dotnet_diagnostic.CA5367.severity = error # Do not serialize types with pointer fields ################### -# Microsoft .NET Analyzers (CA) - Reliability Rules (Additional) -################### -dotnet_diagnostic.CA2017.severity = error # Parameter count mismatch in logging -dotnet_diagnostic.CA2018.severity = error # Buffer.BlockCopy count argument -dotnet_diagnostic.CA2019.severity = error # ThreadStatic fields should not use inline initialization -dotnet_diagnostic.CA2020.severity = error # Prevent behavioral change with IntPtr/UIntPtr -dotnet_diagnostic.CA2021.severity = error # Don't call Cast/OfType with incompatible types -dotnet_diagnostic.CA2022.severity = error # Avoid inexact read with Stream.Read -dotnet_diagnostic.CA2023.severity = error # Invalid braces in message template -dotnet_diagnostic.CA2025.severity = error # Do not pass IDisposable into unawaited tasks - -################### -# Roslynator Analyzers (RCS) - Code Simplification -################### -dotnet_diagnostic.RCS1001.severity = error # Add braces (when expression spans over multiple lines) -dotnet_diagnostic.RCS1005.severity = error # Simplify nested using statement -dotnet_diagnostic.RCS1006.severity = error # Merge 'else' with nested 'if' -dotnet_diagnostic.RCS1020.severity = error # Simplify Nullable to T? -dotnet_diagnostic.RCS1049.severity = error # Simplify boolean comparison -dotnet_diagnostic.RCS1068.severity = error # Simplify logical negation -dotnet_diagnostic.RCS1069.severity = error # Remove unnecessary case label -dotnet_diagnostic.RCS1071.severity = error # Remove redundant base constructor call -dotnet_diagnostic.RCS1073.severity = error # Convert 'if' to 'return' statement -dotnet_diagnostic.RCS1074.severity = error # Remove redundant constructor -dotnet_diagnostic.RCS1084.severity = error # Use coalesce expression instead of conditional expression -dotnet_diagnostic.RCS1128.severity = error # Use coalesce expression -dotnet_diagnostic.RCS1143.severity = error # Simplify coalesce expression -dotnet_diagnostic.RCS1171.severity = error # Simplify lazy initialization -dotnet_diagnostic.RCS1173.severity = error # Use coalesce expression instead of 'if' -dotnet_diagnostic.RCS1259.severity = error # Remove empty syntax (replaces RCS1066) -dotnet_diagnostic.RCS1264.severity = error # Use 'var' or explicit type (replaces RCS1010, RCS1176, RCS1177) - -################### -# Roslynator Analyzers (RCS) - Code Quality & Best Practices -################### -dotnet_diagnostic.RCS1018.severity = error # Add/remove accessibility modifiers -dotnet_diagnostic.RCS1037.severity = error # Remove trailing white-space -dotnet_diagnostic.RCS1055.severity = error # Unnecessary semicolon at the end of declaration -dotnet_diagnostic.RCS1078.severity = error # Use "" or 'string.Empty' -dotnet_diagnostic.RCS1085.severity = error # Use auto-implemented property -dotnet_diagnostic.RCS1090.severity = error # Add/remove 'ConfigureAwait(false)' call -dotnet_diagnostic.RCS1102.severity = error # Make class static -dotnet_diagnostic.RCS1105.severity = error # Unnecessary interpolation -dotnet_diagnostic.RCS1138.severity = error # Add summary to documentation comment -dotnet_diagnostic.RCS1139.severity = error # Add summary element to documentation comment -dotnet_diagnostic.RCS1158.severity = none # Static member in generic type should use a type parameter -dotnet_diagnostic.RCS1163.severity = none # Unused parameter -dotnet_diagnostic.RCS1166.severity = error # Value type object is never equal to null -dotnet_diagnostic.RCS1168.severity = suggestion # Parameter name differs from base name -dotnet_diagnostic.RCS1179.severity = error # Unnecessary assignment -dotnet_diagnostic.RCS1180.severity = error # Inline lazy initialization -dotnet_diagnostic.RCS1188.severity = error # Remove redundant auto-property initialization -dotnet_diagnostic.RCS1201.severity = error # Use method chaining -dotnet_diagnostic.RCS1207.severity = error # Use anonymous function or method group -dotnet_diagnostic.RCS1211.severity = error # Remove unnecessary 'else' -dotnet_diagnostic.RCS1231.severity = suggestion # Make parameter ref read-only -dotnet_diagnostic.RCS1242.severity = error # Do not pass non-read-only struct by read-only reference -dotnet_diagnostic.RCS1248.severity = error # Normalize null check -dotnet_diagnostic.RCS1256.severity = none # Invalid argument null check - -################### -# Roslynator Analyzers (RCS) - Performance & Optimization -################### -dotnet_diagnostic.RCS1058.severity = error # Use compound assignment -dotnet_diagnostic.RCS1077.severity = error # Optimize LINQ method call -dotnet_diagnostic.RCS1080.severity = error # Use 'Count/Length' property instead of 'Any' method -dotnet_diagnostic.RCS1112.severity = error # Combine 'Enumerable.Where' method chain -dotnet_diagnostic.RCS1190.severity = error # Join string expressions -dotnet_diagnostic.RCS1195.severity = error # Use ^ operator -dotnet_diagnostic.RCS1197.severity = error # Optimize StringBuilder.Append/AppendLine call -dotnet_diagnostic.RCS1198.severity = none # Avoid unnecessary boxing of value type -dotnet_diagnostic.RCS1214.severity = error # Unnecessary interpolated string -dotnet_diagnostic.RCS1235.severity = error # Optimize method call - -################### -# StyleCop Analyzers (SA) - Spacing Rules -################### -dotnet_diagnostic.SA1000.severity = error # Keywords must be spaced correctly -dotnet_diagnostic.SA1001.severity = error # Commas must be spaced correctly -dotnet_diagnostic.SA1002.severity = error # Semicolons must be spaced correctly -dotnet_diagnostic.SA1003.severity = error # Symbols must be spaced correctly -dotnet_diagnostic.SA1004.severity = error # Documentation lines must begin with single space -dotnet_diagnostic.SA1005.severity = error # Single line comments must begin with single space -dotnet_diagnostic.SA1006.severity = error # Preprocessor keywords must not be preceded by space -dotnet_diagnostic.SA1007.severity = error # Operator keyword must be followed by space -dotnet_diagnostic.SA1008.severity = error # Opening parenthesis must be spaced correctly -dotnet_diagnostic.SA1009.severity = error # Closing parenthesis must be spaced correctly -dotnet_diagnostic.SA1010.severity = none # Opening square brackets must be spaced correctly -dotnet_diagnostic.SA1011.severity = error # Closing square brackets must be spaced correctly -dotnet_diagnostic.SA1012.severity = error # Opening braces must be spaced correctly -dotnet_diagnostic.SA1013.severity = error # Closing braces must be spaced correctly -dotnet_diagnostic.SA1014.severity = error # Opening generic brackets must be spaced correctly -dotnet_diagnostic.SA1015.severity = error # Closing generic brackets must be spaced correctly -dotnet_diagnostic.SA1016.severity = error # Opening attribute brackets must be spaced correctly -dotnet_diagnostic.SA1017.severity = error # Closing attribute brackets must be spaced correctly -dotnet_diagnostic.SA1018.severity = error # Nullable type symbols must not be preceded by space -dotnet_diagnostic.SA1019.severity = error # Member access symbols must be spaced correctly -dotnet_diagnostic.SA1020.severity = error # Increment decrement symbols must be spaced correctly -dotnet_diagnostic.SA1021.severity = error # Negative signs must be spaced correctly -dotnet_diagnostic.SA1022.severity = error # Positive signs must be spaced correctly -dotnet_diagnostic.SA1023.severity = error # Dereference and access of symbols must be spaced correctly -dotnet_diagnostic.SA1024.severity = error # Colons must be spaced correctly -dotnet_diagnostic.SA1025.severity = error # Code must not contain multiple whitespace in a row -dotnet_diagnostic.SA1026.severity = error # Code must not contain space after new keyword in implicitly typed array allocation -dotnet_diagnostic.SA1027.severity = error # Use tabs correctly -dotnet_diagnostic.SA1028.severity = error # Code must not contain trailing whitespace - -################### -# StyleCop Analyzers (SA) - Readability Rules -################### -dotnet_diagnostic.SA1100.severity = error # Do not prefix calls with base unless local implementation exists -dotnet_diagnostic.SA1101.severity = none # Prefix local calls with this -dotnet_diagnostic.SA1102.severity = error # Query clause must follow previous clause -dotnet_diagnostic.SA1103.severity = error # Query clauses must be on same line or separate lines -dotnet_diagnostic.SA1104.severity = error # Query clause must begin on new line when previous clause spans multiple lines -dotnet_diagnostic.SA1105.severity = error # Query clauses spanning multiple lines must begin on own line -dotnet_diagnostic.SA1106.severity = error # Code must not contain empty statements -dotnet_diagnostic.SA1107.severity = error # Code must not contain multiple statements on one line -dotnet_diagnostic.SA1108.severity = error # Block statements must not contain embedded comments -dotnet_diagnostic.SA1110.severity = error # Opening parenthesis or bracket must be on declaration line -dotnet_diagnostic.SA1111.severity = error # Closing parenthesis must be on line of last parameter -dotnet_diagnostic.SA1112.severity = error # Closing parenthesis must be on line of opening parenthesis -dotnet_diagnostic.SA1113.severity = error # Comma must be on same line as previous parameter -dotnet_diagnostic.SA1114.severity = error # Parameter list must follow declaration -dotnet_diagnostic.SA1115.severity = error # Parameter must follow comma -dotnet_diagnostic.SA1116.severity = error # Split parameters must start on line after declaration -dotnet_diagnostic.SA1117.severity = error # Parameters must be on same line or separate lines -dotnet_diagnostic.SA1118.severity = error # Parameter must not span multiple lines -dotnet_diagnostic.SA1120.severity = error # Comments must contain text -dotnet_diagnostic.SA1121.severity = error # Use built-in type alias -dotnet_diagnostic.SA1122.severity = error # Use string.Empty for empty strings -dotnet_diagnostic.SA1123.severity = error # Do not place regions within elements -dotnet_diagnostic.SA1124.severity = error # Do not use regions -dotnet_diagnostic.SA1125.severity = error # Use shorthand for nullable types -dotnet_diagnostic.SA1127.severity = error # Generic type constraints must be on own line -dotnet_diagnostic.SA1128.severity = error # Constructor initializer must be on own line -dotnet_diagnostic.SA1129.severity = error # Do not use default value type constructor -dotnet_diagnostic.SA1130.severity = error # Use lambda syntax -dotnet_diagnostic.SA1131.severity = error # Use readable conditions -dotnet_diagnostic.SA1132.severity = error # Do not combine fields -dotnet_diagnostic.SA1133.severity = error # Do not combine attributes -dotnet_diagnostic.SA1134.severity = error # Attributes must not share line -dotnet_diagnostic.SA1135.severity = error # Using directives must be qualified -dotnet_diagnostic.SA1136.severity = error # Enum values should be on separate lines -dotnet_diagnostic.SA1137.severity = error # Elements should have the same indentation -dotnet_diagnostic.SA1139.severity = error # Use literal suffix notation instead of casting - -################### -# StyleCop Analyzers (SA) - Ordering Rules -################### -dotnet_diagnostic.SA1200.severity = none # Using directives must be placed correctly -dotnet_diagnostic.SA1201.severity = error # Elements must appear in the correct order -dotnet_diagnostic.SA1202.severity = error # Elements must be ordered by access -dotnet_diagnostic.SA1203.severity = error # Constants must appear before fields -dotnet_diagnostic.SA1204.severity = error # Static elements must appear before instance elements -dotnet_diagnostic.SA1205.severity = error # Partial elements must declare access -dotnet_diagnostic.SA1206.severity = error # Declaration keywords must follow order -dotnet_diagnostic.SA1207.severity = error # Protected must come before internal -dotnet_diagnostic.SA1208.severity = error # System using directives must be placed before other using directives -dotnet_diagnostic.SA1209.severity = error # Using alias directives must be placed after other using directives -dotnet_diagnostic.SA1210.severity = error # Using directives must be ordered alphabetically by namespace -dotnet_diagnostic.SA1211.severity = error # Using alias directives must be ordered alphabetically by alias name -dotnet_diagnostic.SA1212.severity = error # Property accessors must follow order -dotnet_diagnostic.SA1213.severity = error # Event accessors must follow order -dotnet_diagnostic.SA1214.severity = error # Readonly elements must appear before non-readonly elements -dotnet_diagnostic.SA1216.severity = error # Using static directives must be placed at the correct location -dotnet_diagnostic.SA1217.severity = error # Using static directives must be ordered alphabetically - -################### -# StyleCop Analyzers (SA) - Naming Rules -################### -dotnet_diagnostic.SA1300.severity = error # Element must begin with upper-case letter -dotnet_diagnostic.SA1302.severity = error # Interface names must begin with I -dotnet_diagnostic.SA1303.severity = error # Const field names must begin with upper-case letter -dotnet_diagnostic.SA1304.severity = error # Non-private readonly fields must begin with upper-case letter -dotnet_diagnostic.SA1306.severity = none # Field names must begin with lower-case letter -dotnet_diagnostic.SA1307.severity = error # Accessible fields must begin with upper-case letter -dotnet_diagnostic.SA1308.severity = error # Variable names must not be prefixed -dotnet_diagnostic.SA1309.severity = none # Field names must not begin with underscore -dotnet_diagnostic.SA1310.severity = error # Field names must not contain underscore -dotnet_diagnostic.SA1311.severity = none # Static readonly fields must begin with upper-case letter -dotnet_diagnostic.SA1312.severity = error # Variable names must begin with lower-case letter -dotnet_diagnostic.SA1313.severity = error # Parameter names must begin with lower-case letter -dotnet_diagnostic.SA1314.severity = error # Type parameter names must begin with T -dotnet_diagnostic.SA1316.severity = none # Tuple element names should use correct casing - -################### -# StyleCop Analyzers (SA) - Maintainability Rules -################### -dotnet_diagnostic.SA1119.severity = error # Statement must not use unnecessary parenthesis -dotnet_diagnostic.SA1400.severity = error # Access modifier must be declared -dotnet_diagnostic.SA1401.severity = error # Fields must be private -dotnet_diagnostic.SA1402.severity = error # File may only contain a single type -dotnet_diagnostic.SA1403.severity = error # File may only contain a single namespace -dotnet_diagnostic.SA1404.severity = error # Code analysis suppression must have justification -dotnet_diagnostic.SA1405.severity = error # Debug.Assert must provide message text -dotnet_diagnostic.SA1406.severity = error # Debug.Fail must provide message text -dotnet_diagnostic.SA1407.severity = error # Arithmetic expressions must declare precedence -dotnet_diagnostic.SA1408.severity = error # Conditional expressions must declare precedence -dotnet_diagnostic.SA1410.severity = error # Remove delegate parenthesis when possible -dotnet_diagnostic.SA1411.severity = error # Attribute constructor must not use unnecessary parenthesis -dotnet_diagnostic.SA1413.severity = none # Use trailing commas in multi-line initializers - -################### -# StyleCop Analyzers (SA) - Layout Rules -################### -dotnet_diagnostic.SA1500.severity = error # Braces for multi-line statements must not share line -dotnet_diagnostic.SA1501.severity = error # Statement must not be on single line -dotnet_diagnostic.SA1502.severity = error # Element must not be on single line -dotnet_diagnostic.SA1503.severity = error # Braces must not be omitted -dotnet_diagnostic.SA1504.severity = error # All accessors must be single-line or multi-line -dotnet_diagnostic.SA1505.severity = none # Opening braces must not be followed by blank line -dotnet_diagnostic.SA1506.severity = error # Element documentation headers must not be followed by blank line -dotnet_diagnostic.SA1507.severity = error # Code must not contain multiple blank lines in a row -dotnet_diagnostic.SA1508.severity = error # Closing braces must not be preceded by blank line -dotnet_diagnostic.SA1509.severity = error # Opening braces must not be preceded by blank line -dotnet_diagnostic.SA1510.severity = error # Chained statement blocks must not be preceded by blank line -dotnet_diagnostic.SA1511.severity = error # While-do footer must not be preceded by blank line -dotnet_diagnostic.SA1512.severity = error # Single-line comments must not be followed by blank line -dotnet_diagnostic.SA1513.severity = error # Closing brace must be followed by blank line -dotnet_diagnostic.SA1514.severity = none # Element documentation header must be preceded by blank line -dotnet_diagnostic.SA1515.severity = error # Single-line comment must be preceded by blank line -dotnet_diagnostic.SA1516.severity = error # Elements must be separated by blank line -dotnet_diagnostic.SA1517.severity = error # Code must not contain blank lines at start of file -dotnet_diagnostic.SA1518.severity = error # Use line endings correctly at end of file -dotnet_diagnostic.SA1519.severity = error # Braces must not be omitted from multi-line child statement -dotnet_diagnostic.SA1520.severity = error # Use braces consistently - -################### -# StyleCop Analyzers (SA) - Documentation Rules -################### -dotnet_diagnostic.SA1600.severity = error # Elements must be documented -dotnet_diagnostic.SA1601.severity = error # Partial elements must be documented -dotnet_diagnostic.SA1602.severity = error # Enumeration items must be documented -dotnet_diagnostic.SA1604.severity = error # Element documentation must have summary -dotnet_diagnostic.SA1605.severity = error # Partial element documentation must have summary -dotnet_diagnostic.SA1606.severity = error # Element documentation must have summary text -dotnet_diagnostic.SA1607.severity = error # Partial element documentation must have summary text -dotnet_diagnostic.SA1608.severity = error # Element documentation must not have default summary -dotnet_diagnostic.SA1610.severity = error # Property documentation must have value text -dotnet_diagnostic.SA1611.severity = error # Element parameters must be documented -dotnet_diagnostic.SA1612.severity = error # Element parameter documentation must match element parameters -dotnet_diagnostic.SA1613.severity = error # Element parameter documentation must declare parameter name -dotnet_diagnostic.SA1614.severity = error # Element parameter documentation must have text -dotnet_diagnostic.SA1615.severity = error # Element return value must be documented -dotnet_diagnostic.SA1616.severity = error # Element return value documentation must have text -dotnet_diagnostic.SA1617.severity = error # Void return value must not be documented -dotnet_diagnostic.SA1618.severity = error # Generic type parameters must be documented -dotnet_diagnostic.SA1619.severity = error # Generic type parameters must be documented partial class -dotnet_diagnostic.SA1620.severity = error # Generic type parameter documentation must match type parameters -dotnet_diagnostic.SA1621.severity = error # Generic type parameter documentation must declare parameter name -dotnet_diagnostic.SA1622.severity = error # Generic type parameter documentation must have text -dotnet_diagnostic.SA1623.severity = error # Property summary documentation must match accessors -dotnet_diagnostic.SA1624.severity = error # Property summary documentation must omit set accessor with restricted access -dotnet_diagnostic.SA1625.severity = error # Element documentation must not be copied and pasted -dotnet_diagnostic.SA1626.severity = error # Single-line comments must not use documentation style slashes -dotnet_diagnostic.SA1627.severity = error # Documentation text must not be empty -dotnet_diagnostic.SA1629.severity = error # Documentation text must end with a period -dotnet_diagnostic.SA1633.severity = error # File must have header -dotnet_diagnostic.SA1634.severity = error # File header must show copyright -dotnet_diagnostic.SA1635.severity = error # File header must have copyright text -dotnet_diagnostic.SA1636.severity = error # File header copyright text must match -dotnet_diagnostic.SA1637.severity = none # File header must contain file name -dotnet_diagnostic.SA1638.severity = none # File header file name documentation must match file name -dotnet_diagnostic.SA1640.severity = error # File header must have valid company text -dotnet_diagnostic.SA1641.severity = error # File header company name text must match -dotnet_diagnostic.SA1642.severity = error # Constructor summary documentation must begin with standard text -dotnet_diagnostic.SA1643.severity = error # Destructor summary documentation must begin with standard text -dotnet_diagnostic.SA1649.severity = error # File name must match type name -dotnet_diagnostic.SA1651.severity = error # Do not use placeholder elements - -################### -# StyleCop Alternative Analyzers (SX) - Alternative Rules -################### -dotnet_diagnostic.SX1101.severity = error # Do not prefix local members with this -dotnet_diagnostic.SX1309.severity = error # Field names must begin with underscore -dotnet_diagnostic.SX1623.severity = none # Property summary documentation must match accessors (alternative) - -############################################# -# NUnit Analyzers -############################################# -[*.{cs,vb}] - -################### -# NUnit Analyzers - Structure Rules (NUnit1001 - NUnit1999) -################### -dotnet_diagnostic.NUnit1001.severity = error # TestCase args must match parameter types -dotnet_diagnostic.NUnit1002.severity = error # TestCaseSource should use nameof -dotnet_diagnostic.NUnit1003.severity = error # TestCase provided too few arguments -dotnet_diagnostic.NUnit1004.severity = error # TestCase provided too many arguments -dotnet_diagnostic.NUnit1005.severity = error # ExpectedResult type must match return type -dotnet_diagnostic.NUnit1006.severity = error # ExpectedResult must not be used on void methods -dotnet_diagnostic.NUnit1007.severity = error # Non-void method but no ExpectedResult provided -dotnet_diagnostic.NUnit1008.severity = error # ParallelScope.Self at assembly level has no effect -dotnet_diagnostic.NUnit1009.severity = error # ParallelScope.Children on non-parameterized test -dotnet_diagnostic.NUnit1010.severity = error # ParallelScope.Fixtures on a test method -dotnet_diagnostic.NUnit1011.severity = error # TestCaseSource member does not exist -dotnet_diagnostic.NUnit1012.severity = error # async test method must have non-void return type -dotnet_diagnostic.NUnit1013.severity = error # async method must use non-generic Task when no result -dotnet_diagnostic.NUnit1014.severity = error # async method must use Task when result expected -dotnet_diagnostic.NUnit1015.severity = error # Source type does not implement I(Async)Enumerable -dotnet_diagnostic.NUnit1016.severity = error # Source type lacks default constructor -dotnet_diagnostic.NUnit1017.severity = error # Specified source is not static -dotnet_diagnostic.NUnit1018.severity = error # TestCaseSource param count mismatch (target method) -dotnet_diagnostic.NUnit1019.severity = error # Source does not return I(Async)Enumerable -dotnet_diagnostic.NUnit1020.severity = error # Parameters provided to field/property source -dotnet_diagnostic.NUnit1021.severity = error # ValueSource should use nameof -dotnet_diagnostic.NUnit1022.severity = error # Specified ValueSource is not static -dotnet_diagnostic.NUnit1023.severity = error # ValueSource cannot supply required parameters -dotnet_diagnostic.NUnit1024.severity = error # ValueSource does not return I(Async)Enumerable -dotnet_diagnostic.NUnit1025.severity = error # ValueSource member does not exist -dotnet_diagnostic.NUnit1026.severity = error # Test or setup/teardown method is not public -dotnet_diagnostic.NUnit1027.severity = error # Test method has parameters but no arguments supplied -dotnet_diagnostic.NUnit1028.severity = error # Non-test method is public -dotnet_diagnostic.NUnit1029.severity = error # TestCaseSource param count mismatch (Test method) -dotnet_diagnostic.NUnit1030.severity = error # TestCaseSource parameter type mismatch (Test method) -dotnet_diagnostic.NUnit1031.severity = error # ValuesAttribute args must match parameter types -dotnet_diagnostic.NUnit1032.severity = error # IDisposable field/property should be disposed in TearDown -dotnet_diagnostic.NUnit1033.severity = error # TestContext.Write methods will be obsolete -dotnet_diagnostic.NUnit1034.severity = error # Base TestFixtures should be abstract -dotnet_diagnostic.NUnit1035.severity = error # Range 'step' parameter cannot be zero -dotnet_diagnostic.NUnit1036.severity = error # Range: from < to when step is positive -dotnet_diagnostic.NUnit1037.severity = error # Range: from > to when step is negative -dotnet_diagnostic.NUnit1038.severity = error # Attribute values' types must match parameter type - -################### -# NUnit Analyzers - Assertion Rules (NUnit2001 - NUnit2999) -################### -dotnet_diagnostic.NUnit2001.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.False -dotnet_diagnostic.NUnit2002.severity = error # Prefer Assert.That(..., Is.False) over ClassicAssert.IsFalse -dotnet_diagnostic.NUnit2003.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.IsTrue -dotnet_diagnostic.NUnit2004.severity = error # Prefer Assert.That(..., Is.True) over ClassicAssert.True -dotnet_diagnostic.NUnit2005.severity = error # Prefer Is.EqualTo over AreEqual -dotnet_diagnostic.NUnit2006.severity = error # Prefer Is.Not.EqualTo over AreNotEqual -dotnet_diagnostic.NUnit2007.severity = error # Actual value should not be a constant -dotnet_diagnostic.NUnit2008.severity = error # Incorrect IgnoreCase usage -dotnet_diagnostic.NUnit2009.severity = error # Same value used for actual and expected -dotnet_diagnostic.NUnit2010.severity = error # Use EqualConstraint for better messages -dotnet_diagnostic.NUnit2011.severity = error # Use ContainsConstraint for better messages -dotnet_diagnostic.NUnit2012.severity = error # Use StartsWithConstraint for better messages -dotnet_diagnostic.NUnit2013.severity = error # Use EndsWithConstraint for better messages -dotnet_diagnostic.NUnit2014.severity = error # Use SomeItemsConstraint for better messages -dotnet_diagnostic.NUnit2015.severity = error # Prefer Is.SameAs over AreSame -dotnet_diagnostic.NUnit2016.severity = error # Prefer Is.Null over ClassicAssert.Null -dotnet_diagnostic.NUnit2017.severity = error # Prefer Is.Null over ClassicAssert.IsNull -dotnet_diagnostic.NUnit2018.severity = error # Prefer Is.Not.Null over ClassicAssert.NotNull -dotnet_diagnostic.NUnit2019.severity = error # Prefer Is.Not.Null over ClassicAssert.IsNotNull -dotnet_diagnostic.NUnit2020.severity = error # Incompatible types for SameAs constraint -dotnet_diagnostic.NUnit2021.severity = error # Incompatible types for EqualTo constraint -dotnet_diagnostic.NUnit2022.severity = error # Missing property required for constraint -dotnet_diagnostic.NUnit2023.severity = error # Invalid NullConstraint usage -dotnet_diagnostic.NUnit2024.severity = error # Wrong actual type with String constraint -dotnet_diagnostic.NUnit2025.severity = error # Wrong actual type with ContainsConstraint -dotnet_diagnostic.NUnit2026.severity = error # Wrong actual type with SomeItems+EqualConstraint -dotnet_diagnostic.NUnit2027.severity = error # Prefer Is.GreaterThan over ClassicAssert.Greater -dotnet_diagnostic.NUnit2028.severity = error # Prefer Is.GreaterThanOrEqualTo over GreaterOrEqual -dotnet_diagnostic.NUnit2029.severity = error # Prefer Is.LessThan over ClassicAssert.Less -dotnet_diagnostic.NUnit2030.severity = error # Prefer Is.LessThanOrEqualTo over LessOrEqual -dotnet_diagnostic.NUnit2031.severity = error # Prefer Is.Not.SameAs over AreNotSame -dotnet_diagnostic.NUnit2032.severity = error # Prefer Is.Zero over ClassicAssert.Zero -dotnet_diagnostic.NUnit2033.severity = error # Prefer Is.Not.Zero over ClassicAssert.NotZero -dotnet_diagnostic.NUnit2034.severity = error # Prefer Is.NaN over ClassicAssert.IsNaN -dotnet_diagnostic.NUnit2035.severity = error # Prefer Is.Empty over ClassicAssert.IsEmpty -dotnet_diagnostic.NUnit2036.severity = error # Prefer Is.Not.Empty over ClassicAssert.IsNotEmpty -dotnet_diagnostic.NUnit2037.severity = error # Prefer Does.Contain over ClassicAssert.Contains -dotnet_diagnostic.NUnit2038.severity = error # Prefer Is.InstanceOf over ClassicAssert.IsInstanceOf -dotnet_diagnostic.NUnit2039.severity = error # Prefer Is.Not.InstanceOf over ClassicAssert.IsNotInstanceOf -dotnet_diagnostic.NUnit2040.severity = error # Non-reference types for SameAs constraint -dotnet_diagnostic.NUnit2041.severity = error # Incompatible types for comparison constraint -dotnet_diagnostic.NUnit2042.severity = error # Comparison constraint on object -dotnet_diagnostic.NUnit2043.severity = error # Use ComparisonConstraint for better messages -dotnet_diagnostic.NUnit2044.severity = error # Non-delegate actual parameter -dotnet_diagnostic.NUnit2045.severity = error # Use Assert.EnterMultipleScope or Assert.Multiple -dotnet_diagnostic.NUnit2046.severity = error # Use CollectionConstraint for better messages -dotnet_diagnostic.NUnit2047.severity = error # Incompatible types for Within constraint -dotnet_diagnostic.NUnit2048.severity = error # Prefer Assert.That over StringAssert -dotnet_diagnostic.NUnit2049.severity = error # Prefer Assert.That over CollectionAssert -dotnet_diagnostic.NUnit2050.severity = error # NUnit 4 no longer supports string.Format spec -dotnet_diagnostic.NUnit2051.severity = error # Prefer Is.Positive over ClassicAssert.Positive -dotnet_diagnostic.NUnit2052.severity = error # Prefer Is.Negative over ClassicAssert.Negative -dotnet_diagnostic.NUnit2053.severity = error # Prefer Is.AssignableFrom over ClassicAssert.IsAssignableFrom -dotnet_diagnostic.NUnit2054.severity = error # Prefer Is.Not.AssignableFrom over ClassicAssert.IsNotAssignableFrom -dotnet_diagnostic.NUnit2055.severity = error # Prefer Is.InstanceOf over 'is T' expression -dotnet_diagnostic.NUnit2056.severity = error # Prefer Assert.EnterMultipleScope statement over Multiple - -################### -# NUnit Analyzers - Suppressor Rules (NUnit3001 - NUnit3999) -################### -dotnet_diagnostic.NUnit3001.severity = error # Expression checked in NotNull/IsNotNull/Assert.That -dotnet_diagnostic.NUnit3002.severity = error # Field/Property initialized in SetUp/OneTimeSetUp -dotnet_diagnostic.NUnit3003.severity = error # TestFixture instantiated via reflection -dotnet_diagnostic.NUnit3004.severity = error # Field should be disposed in TearDown/OneTimeTearDown - -################### -# NUnit Analyzers - Style Rules (NUnit4001 - NUnit4999) -################### -dotnet_diagnostic.NUnit4001.severity = error # Simplify the Values attribute -dotnet_diagnostic.NUnit4002.severity = error # Use Specific constraint +# Microsoft .NET Runtime Obsoletions (SYSLIB0xxx) +################### +dotnet_diagnostic.SYSLIB0001.severity = error # The UTF-7 encoding is insecure and should not be used +dotnet_diagnostic.SYSLIB0002.severity = error # PrincipalPermissionAttribute is not honored by the runtime and must not be used +dotnet_diagnostic.SYSLIB0003.severity = error # Code Access Security (CAS) is not supported or honored by the runtime +dotnet_diagnostic.SYSLIB0004.severity = error # Constrained Execution Region (CER) feature is not supported +dotnet_diagnostic.SYSLIB0005.severity = error # Global Assembly Cache is not supported +dotnet_diagnostic.SYSLIB0006.severity = error # Thread.Abort is not supported and throws PlatformNotSupportedException +dotnet_diagnostic.SYSLIB0007.severity = error # The default implementation of this cryptography algorithm is not supported +dotnet_diagnostic.SYSLIB0008.severity = error # The CreatePdbGenerator API is not supported and throws PlatformNotSupportedException +dotnet_diagnostic.SYSLIB0009.severity = error # The AuthenticationManager Authenticate and PreAuthenticate methods are not supported +dotnet_diagnostic.SYSLIB0010.severity = error # This Remoting API is not supported and throws PlatformNotSupportedException +dotnet_diagnostic.SYSLIB0011.severity = error # BinaryFormatter serialization is obsolete +dotnet_diagnostic.SYSLIB0012.severity = error # Assembly.CodeBase and Assembly.EscapedCodeBase are obsolete +dotnet_diagnostic.SYSLIB0013.severity = error # Uri.EscapeUriString can corrupt the Uri string +dotnet_diagnostic.SYSLIB0014.severity = error # WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete — use HttpClient +dotnet_diagnostic.SYSLIB0015.severity = error # DisablePrivateReflectionAttribute is not honored +dotnet_diagnostic.SYSLIB0016.severity = error # Use Marshal.GetExceptionPointers instead +dotnet_diagnostic.SYSLIB0017.severity = error # Strong name signing is not supported on .NET Core +dotnet_diagnostic.SYSLIB0018.severity = error # ReflectionOnly loading is not supported +dotnet_diagnostic.SYSLIB0019.severity = error # RuntimeEnvironment members SystemConfigurationFile, GetSystemVersion, and FromGlobalAccessCache are not supported +dotnet_diagnostic.SYSLIB0020.severity = error # JsonSerializerOptions.IgnoreNullValues is obsolete — use DefaultIgnoreCondition +dotnet_diagnostic.SYSLIB0021.severity = error # Derived cryptographic types are obsolete — use the Create factory methods +dotnet_diagnostic.SYSLIB0022.severity = error # Rijndael types are obsolete — use Aes +dotnet_diagnostic.SYSLIB0023.severity = error # RNGCryptoServiceProvider is obsolete — use RandomNumberGenerator +dotnet_diagnostic.SYSLIB0024.severity = error # Creating and unloading AppDomains is not supported and throws an exception +dotnet_diagnostic.SYSLIB0025.severity = error # SuppressIldasmAttribute has no effect in .NET 6.0+ +dotnet_diagnostic.SYSLIB0026.severity = error # X509Certificate and X509Certificate2 parameterless constructors are obsolete +dotnet_diagnostic.SYSLIB0027.severity = error # PublicKey.Key is obsolete — use the appropriate method to get the public key +dotnet_diagnostic.SYSLIB0028.severity = error # X509Certificate2.PrivateKey is obsolete — use the appropriate method to get the private key +dotnet_diagnostic.SYSLIB0029.severity = error # ProduceLegacyHmacValues is obsolete +dotnet_diagnostic.SYSLIB0030.severity = error # HMACSHA1 always uses the algorithm implementation provided by the platform +dotnet_diagnostic.SYSLIB0031.severity = error # EncodingProvider.GetEncoding(int, EncoderFallback, DecoderFallback) is obsolete +dotnet_diagnostic.SYSLIB0032.severity = error # Recovery from corrupted process state exceptions is not supported +dotnet_diagnostic.SYSLIB0033.severity = error # Rfc2898DeriveBytes.CryptDeriveKey is obsolete +dotnet_diagnostic.SYSLIB0034.severity = error # CmsSigner has been deprecated — use a constructor that accepts a SubjectIdentifierType +dotnet_diagnostic.SYSLIB0035.severity = error # ComputeCounterSignature without specifying a CmsSigner is obsolete +dotnet_diagnostic.SYSLIB0036.severity = error # Regex.CompileToAssembly is obsolete and not supported — use the RegexGenerator source generator +dotnet_diagnostic.SYSLIB0037.severity = error # AssemblyName members HashAlgorithm, ProcessorArchitecture, and VersionCompatibility are obsolete +dotnet_diagnostic.SYSLIB0038.severity = error # SerializationFormat.Binary is obsolete +dotnet_diagnostic.SYSLIB0039.severity = error # TLS versions 1.0 and 1.1 have known vulnerabilities and are not recommended +dotnet_diagnostic.SYSLIB0040.severity = error # EncryptionPolicy.NoEncryption and AllowEncryption significantly reduce security +dotnet_diagnostic.SYSLIB0041.severity = error # The default iteration count for Rfc2898DeriveBytes parameters is outdated and insecure +dotnet_diagnostic.SYSLIB0042.severity = error # ToXmlString and FromXmlString have no implementation for ECC types +dotnet_diagnostic.SYSLIB0043.severity = error # ECDiffieHellmanPublicKey.ToByteArray() and the associated constructor do not have a consistent and interoperable implementation +dotnet_diagnostic.SYSLIB0044.severity = error # AssemblyName.CodeBase and AssemblyName.EscapedCodeBase are obsolete +dotnet_diagnostic.SYSLIB0045.severity = error # Cryptographic factory methods accepting an algorithm name are obsolete +dotnet_diagnostic.SYSLIB0046.severity = error # ControlledExecution.Run may corrupt the process and should not be used in production code +dotnet_diagnostic.SYSLIB0047.severity = error # XmlSecureResolver is obsolete +dotnet_diagnostic.SYSLIB0048.severity = error # RSA.EncryptValue and RSA.DecryptValue are not supported and throw NotSupportedException +dotnet_diagnostic.SYSLIB0049.severity = error # JsonSerializerOptions.AddContext is obsolete +dotnet_diagnostic.SYSLIB0050.severity = error # Formatter-based serialization (ISerializable, FormatterServices, etc.) is obsolete +dotnet_diagnostic.SYSLIB0051.severity = error # The Exception API ISerializable / GetObjectData formatter-based serialization is obsolete +dotnet_diagnostic.SYSLIB0052.severity = error # Members for assigning to AssemblyName.CodeBase or AssemblyName.EscapedCodeBase are obsolete +dotnet_diagnostic.SYSLIB0053.severity = error # AesGcm should indicate the required tag size for encryption and decryption +dotnet_diagnostic.SYSLIB0054.severity = error # Strong name signing is not supported and throws PlatformNotSupportedException +dotnet_diagnostic.SYSLIB0055.severity = error # 'Memory.Pin' may be incorrectly used with structures +dotnet_diagnostic.SYSLIB0056.severity = error # LoadFromHash and related members are obsolete +dotnet_diagnostic.SYSLIB0057.severity = error # Use X509CertificateLoader instead to load certificates +dotnet_diagnostic.SYSLIB0058.severity = error # KeyExchangeAlgorithm and KeyExchangeStrength are obsolete on SslStream +dotnet_diagnostic.SYSLIB0059.severity = error # SystemEvents.EventsThreadShutdown event is obsolete +dotnet_diagnostic.SYSLIB0060.severity = error # Constructors of DirectoryServices.ActiveDirectory.ConfigurationContext are obsolete +dotnet_diagnostic.SYSLIB0061.severity = error # CryptographyConfig.AddOID and AddAlgorithm methods are obsolete + +################### +# Microsoft .NET Source Generator Diagnostics (SYSLIB1xxx) +################### +# LoggerMessage source generator +dotnet_diagnostic.SYSLIB1001.severity = error # Logging method names cannot start with _ +dotnet_diagnostic.SYSLIB1002.severity = error # Don't include log level parameters as templates in the logging message +dotnet_diagnostic.SYSLIB1003.severity = error # LoggerMessage attribute log level value must be defined +dotnet_diagnostic.SYSLIB1004.severity = error # Logging class cannot be in nested types +dotnet_diagnostic.SYSLIB1005.severity = error # Could not find a required type definition +dotnet_diagnostic.SYSLIB1006.severity = error # Multiple logging methods cannot use the same event ID within a class +dotnet_diagnostic.SYSLIB1007.severity = error # Logging methods must return void +dotnet_diagnostic.SYSLIB1008.severity = error # One of the arguments to a logging method must implement ILogger +dotnet_diagnostic.SYSLIB1009.severity = error # Logging methods must be static +dotnet_diagnostic.SYSLIB1010.severity = error # Logging methods must be partial +dotnet_diagnostic.SYSLIB1011.severity = error # Logging methods cannot be generic +dotnet_diagnostic.SYSLIB1012.severity = error # Logging methods must not have a body +dotnet_diagnostic.SYSLIB1013.severity = error # Missing logger argument to logging method +dotnet_diagnostic.SYSLIB1015.severity = error # Argument is not referenced from the logging message +dotnet_diagnostic.SYSLIB1016.severity = error # Logging methods cannot have a parameter named the same as one of the template parameters +dotnet_diagnostic.SYSLIB1017.severity = error # Logging methods cannot have more than one parameter of type LogLevel +dotnet_diagnostic.SYSLIB1018.severity = error # Logging method parameter doesn't appear in template +dotnet_diagnostic.SYSLIB1019.severity = error # Couldn't find a field of type ILogger +dotnet_diagnostic.SYSLIB1020.severity = error # Found multiple fields of type ILogger +dotnet_diagnostic.SYSLIB1021.severity = error # Cannot have multiple logging methods with the same name +dotnet_diagnostic.SYSLIB1022.severity = error # Logging methods cannot have multiple template parameters with the same name +dotnet_diagnostic.SYSLIB1023.severity = error # Generating more than 6 arguments is not supported +dotnet_diagnostic.SYSLIB1024.severity = error # Logging method template name conflicts with a method parameter name +dotnet_diagnostic.SYSLIB1025.severity = error # Multiple template parameters with the same name +# Skipped SYSLIB1014 (Reserved) + +# System.Text.Json source generator +dotnet_diagnostic.SYSLIB1030.severity = error # JsonSourceGenerator did not generate serialization metadata for type +dotnet_diagnostic.SYSLIB1031.severity = error # Duplicate type registration in JsonSerializerContext +dotnet_diagnostic.SYSLIB1032.severity = error # JsonSerializerContext classes must be partial +dotnet_diagnostic.SYSLIB1033.severity = error # Serializable types must have at least one constructor +dotnet_diagnostic.SYSLIB1034.severity = error # Type uses an unsupported [JsonExtensionData] property +dotnet_diagnostic.SYSLIB1036.severity = error # Init-only properties are not supported in source generation +dotnet_diagnostic.SYSLIB1037.severity = error # Source generator does not support [JsonInclude] on inaccessible members +dotnet_diagnostic.SYSLIB1038.severity = error # JsonInclude on a non-public property is not supported +dotnet_diagnostic.SYSLIB1039.severity = error # Type with extension data of unsupported shape +dotnet_diagnostic.SYSLIB1040.severity = error # Type with cycles is not supported +dotnet_diagnostic.SYSLIB1041.severity = error # Duplicate type names registered with JsonSerializerContext +# Skipped SYSLIB1035 (Reserved) + +# GeneratedRegex source generator +dotnet_diagnostic.SYSLIB1042.severity = error # Use 'GeneratedRegexAttribute' for static regex creation +dotnet_diagnostic.SYSLIB1043.severity = error # The regex pattern is not valid +dotnet_diagnostic.SYSLIB1044.severity = error # The regex source generator failed +dotnet_diagnostic.SYSLIB1045.severity = error # Convert to 'GeneratedRegexAttribute' for compile-time regex generation +dotnet_diagnostic.SYSLIB1046.severity = error # Could not find an applicable Regex constructor +dotnet_diagnostic.SYSLIB1047.severity = error # The regex options are not valid for source generation +dotnet_diagnostic.SYSLIB1048.severity = error # GeneratedRegex source generator encountered an unhandled error +dotnet_diagnostic.SYSLIB1049.severity = error # Multiple regex source generators conflict + +# LibraryImport (P/Invoke) source generator +dotnet_diagnostic.SYSLIB1050.severity = error # Method should be marked 'LibraryImport' instead of 'DllImport' +dotnet_diagnostic.SYSLIB1051.severity = error # Specified type is not supported by source-generated P/Invokes +dotnet_diagnostic.SYSLIB1052.severity = error # Specified configuration is not supported by source-generated P/Invokes +dotnet_diagnostic.SYSLIB1053.severity = error # 'LibraryImportAttribute' requires unsafe code +dotnet_diagnostic.SYSLIB1054.severity = error # Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time +dotnet_diagnostic.SYSLIB1055.severity = error # Invalid 'CustomMarshallerAttribute' usage +dotnet_diagnostic.SYSLIB1056.severity = error # Specified marshaller type is invalid +dotnet_diagnostic.SYSLIB1057.severity = error # Marshaller type does not have the required shape +dotnet_diagnostic.SYSLIB1058.severity = error # Invalid 'NativeMarshallingAttribute' usage +dotnet_diagnostic.SYSLIB1059.severity = error # Marshaller type must be a closed generic type +dotnet_diagnostic.SYSLIB1060.severity = error # Specified native type is invalid +dotnet_diagnostic.SYSLIB1061.severity = error # Marshaller type has incompatible method signatures +dotnet_diagnostic.SYSLIB1062.severity = error # Project must be updated with 'true' +dotnet_diagnostic.SYSLIB1063.severity = error # 'CustomMarshaller' types must have an 'in' or 'ref' first parameter +dotnet_diagnostic.SYSLIB1064.severity = error # Forwarder marshaller types should not have 'GenericPlaceholder' + +# GeneratedComInterface / COM source generator +dotnet_diagnostic.SYSLIB1090.severity = error # Convert to 'GeneratedComInterface' +dotnet_diagnostic.SYSLIB1091.severity = error # Type is an invalid 'GeneratedComInterface' base interface +dotnet_diagnostic.SYSLIB1092.severity = error # 'GeneratedComInterface' must specify 'Guid' +dotnet_diagnostic.SYSLIB1093.severity = error # Method on 'GeneratedComInterface' has unsupported return type +dotnet_diagnostic.SYSLIB1094.severity = error # Method on 'GeneratedComInterface' has unsupported parameter +dotnet_diagnostic.SYSLIB1095.severity = error # Type implements 'GeneratedComInterface' but is not partial +dotnet_diagnostic.SYSLIB1096.severity = error # 'GeneratedComClassAttribute' must be applied to a partial type +dotnet_diagnostic.SYSLIB1097.severity = error # 'GeneratedComClassAttribute' type must implement at least one 'GeneratedComInterface' +dotnet_diagnostic.SYSLIB1098.severity = error # 'GeneratedComInterface' interface inheritance not supported + +# Configuration binding source generator +dotnet_diagnostic.SYSLIB1100.severity = error # Configuration binding source generator: type is not supported +dotnet_diagnostic.SYSLIB1101.severity = error # Configuration binding source generator: property on type is not supported +dotnet_diagnostic.SYSLIB1102.severity = error # Configuration binding source generator: not enabled +dotnet_diagnostic.SYSLIB1103.severity = error # Configuration binding source generator: type lacks a parameterless constructor +dotnet_diagnostic.SYSLIB1104.severity = error # Configuration binding source generator: language version is too low + +################### +# Microsoft .NET Style Rules (IDExxxx) - Language Rules +################### +# EnforceCodeStyleInBuild=true (set in Directory.Build.props) promotes these +# IDE rules into `dotnet build` so they fire at compile time, not just in the +# IDE. We enable the ones that are unambiguous wins and skip the rules that +# conflict with an existing convention (SST1117, SST1200, SST1206, SST1400, SST1633, +# etc.) so we don't double-report. + +# Bug catchers — always error. +dotnet_diagnostic.IDE0035.severity = none # Remove unreachable code +dotnet_diagnostic.IDE0043.severity = none # Format string contains invalid placeholder +dotnet_diagnostic.IDE0051.severity = none # Remove unused private member +dotnet_diagnostic.IDE0052.severity = none # Remove unread private member +dotnet_diagnostic.IDE0076.severity = none # Remove invalid global SuppressMessage attribute +dotnet_diagnostic.IDE0077.severity = none # Avoid legacy format target in global SuppressMessage attribute +dotnet_diagnostic.IDE0080.severity = none # Remove unnecessary suppression operator + +# Simplification / cleanup. +dotnet_diagnostic.IDE0001.severity = none # Simplify name +dotnet_diagnostic.IDE0002.severity = none # Simplify member access +dotnet_diagnostic.IDE0004.severity = none # Remove unnecessary cast — disabled because we deliberately keep explicit casts in Apple platform-specific paths and other reflection/marshalling sites where the analyzer's "redundant" judgement is wrong +dotnet_diagnostic.IDE0005.severity = none # Remove unnecessary import - DUPLICATE S1128 (slower: 2.364s vs 551ms) +dotnet_diagnostic.IDE0016.severity = none # Use throw expression +dotnet_diagnostic.IDE0017.severity = none # Use object initializers +dotnet_diagnostic.IDE0018.severity = none # Inline variable declaration +dotnet_diagnostic.IDE0019.severity = none # Use pattern matching to avoid 'as' followed by a 'null' check +dotnet_diagnostic.IDE0020.severity = none # Use pattern matching to avoid 'is' check followed by a cast +dotnet_diagnostic.IDE0028.severity = none # Use collection initializers +dotnet_diagnostic.IDE0029.severity = none # Null check can be simplified +dotnet_diagnostic.IDE0030.severity = none # Use coalesce expression (nullable types) +dotnet_diagnostic.IDE0031.severity = none # Use null propagation — covered by SST1196 +dotnet_diagnostic.IDE0032.severity = none # Use auto property +dotnet_diagnostic.IDE0033.severity = none # Use explicitly provided tuple name +dotnet_diagnostic.IDE0034.severity = none # Simplify default expression +dotnet_diagnostic.IDE0037.severity = none # Use inferred member name +dotnet_diagnostic.IDE0038.severity = none # Use pattern matching ('is' check without a cast) +dotnet_diagnostic.IDE0041.severity = none # Use 'is null' check +dotnet_diagnostic.IDE0042.severity = none # Deconstruct variable declaration +dotnet_diagnostic.IDE0044.severity = none # Add readonly modifier +dotnet_diagnostic.IDE0046.severity = none # Use conditional expression for return — downgraded because nested coalescing/ternary chains it produces hurt readability +dotnet_diagnostic.IDE0047.severity = none # Remove unnecessary parentheses +dotnet_diagnostic.IDE0049.severity = none # Use language keywords instead of framework type names for type references +dotnet_diagnostic.IDE0054.severity = none # Use compound assignment +dotnet_diagnostic.IDE0056.severity = none # Use index operator +dotnet_diagnostic.IDE0057.severity = none # Use range operator +dotnet_diagnostic.IDE0059.severity = none # Remove unnecessary value assignment +dotnet_diagnostic.IDE0062.severity = none # Make local function static +dotnet_diagnostic.IDE0063.severity = none # Use simple 'using' statement +dotnet_diagnostic.IDE0064.severity = none # Make struct fields writable — flag readonly-but-mutable struct fields where intent diverges from declaration +dotnet_diagnostic.IDE0066.severity = none # Use switch expression +dotnet_diagnostic.IDE0070.severity = none # Use 'System.HashCode.Combine' +dotnet_diagnostic.IDE0071.severity = none # Simplify interpolation +dotnet_diagnostic.IDE0072.severity = none # Add missing cases to switch expression - sometimes we miss switch cases dilberately. +dotnet_diagnostic.IDE0074.severity = none # Use compound assignment +dotnet_diagnostic.IDE0075.severity = none # Simplify conditional expression +dotnet_diagnostic.IDE0078.severity = none # Use pattern matching +dotnet_diagnostic.IDE0082.severity = none # Convert typeof to nameof +dotnet_diagnostic.IDE0083.severity = none # Use pattern matching ('not' operator) +dotnet_diagnostic.IDE0084.severity = none # Use pattern matching ('IsNot' operator) +dotnet_diagnostic.IDE0090.severity = none # Simplify 'new' expression +dotnet_diagnostic.IDE0100.severity = none # Remove unnecessary equality operator +dotnet_diagnostic.IDE0110.severity = none # Remove unnecessary discard +dotnet_diagnostic.IDE0120.severity = none # Simplify LINQ expression +dotnet_diagnostic.IDE0150.severity = none # Prefer 'null' check over type check +dotnet_diagnostic.IDE0161.severity = none # Use file-scoped namespace declaration +dotnet_diagnostic.IDE0170.severity = none # Simplify property pattern +dotnet_diagnostic.IDE0180.severity = none # Use tuple to swap values +dotnet_diagnostic.IDE0200.severity = none # Remove unnecessary lambda expression +dotnet_diagnostic.IDE0220.severity = none # Add explicit cast in foreach loop +dotnet_diagnostic.IDE0240.severity = none # Remove redundant nullable directive +dotnet_diagnostic.IDE0241.severity = none # Remove unnecessary nullable directive +dotnet_diagnostic.IDE0250.severity = none # Make struct 'readonly' +dotnet_diagnostic.IDE0251.severity = none # Make member 'readonly' +dotnet_diagnostic.IDE0260.severity = none # Use pattern matching +dotnet_diagnostic.IDE0270.severity = none # Use coalesce expression + +# Disabled — conflict with an existing rule or project convention. +dotnet_diagnostic.IDE0003.severity = none # Remove 'this' qualifier — SST1117 owns the qualification style +dotnet_diagnostic.IDE0007.severity = none # Use var — we don't force var in either direction +dotnet_diagnostic.IDE0008.severity = none # Use explicit type — we don't force var in either direction +dotnet_diagnostic.IDE0009.severity = none # Member access should be qualified — SST1117 owns the qualification style +dotnet_diagnostic.IDE0010.severity = none # Add missing cases to switch statement — too noisy for default/fallthrough patterns +dotnet_diagnostic.IDE0011.severity = none # Add braces +dotnet_diagnostic.IDE0021.severity = none # Use expression body for constructors — preference not enforced +dotnet_diagnostic.IDE0022.severity = none # Use expression body for methods — preference not enforced +dotnet_diagnostic.IDE0023.severity = none # Use expression body for conversion operators — preference not enforced +dotnet_diagnostic.IDE0024.severity = none # Use expression body for operators — preference not enforced +dotnet_diagnostic.IDE0025.severity = none # Use expression body for properties — preference not enforced +dotnet_diagnostic.IDE0026.severity = none # Use expression body for indexers — preference not enforced +dotnet_diagnostic.IDE0027.severity = none # Use expression body for accessors — preference not enforced +dotnet_diagnostic.IDE0036.severity = none # Order modifiers — SST1206 handles +dotnet_diagnostic.IDE0039.severity = none # Use local function — anonymous method preference not enforced +dotnet_diagnostic.IDE0040.severity = none # Add accessibility modifiers — SST1400 handles +dotnet_diagnostic.IDE0045.severity = none # Use conditional expression for assignment — preference not enforced +dotnet_diagnostic.IDE0048.severity = none # Add parentheses for clarity — preference not enforced +dotnet_diagnostic.IDE0053.severity = none # Use expression body for lambdas — preference not enforced +dotnet_diagnostic.IDE0055.severity = none # Formatting — the spacing and layout rules own formatting +dotnet_diagnostic.IDE0058.severity = none # Remove unnecessary expression value — too noisy (ignores fluent APIs) +dotnet_diagnostic.IDE0060.severity = none # Remove unused parameter — CA1801 handles (with api_surface config) +dotnet_diagnostic.IDE0061.severity = none # Use expression body for local function — preference not enforced +dotnet_diagnostic.IDE0065.severity = none # 'using' directive placement — SST1200 = none (we put usings outside file-scoped namespaces) +dotnet_diagnostic.IDE0073.severity = none # Require file header — SST1633 handles +dotnet_diagnostic.IDE0079.severity = none # Remove unnecessary suppression — can misfire on multi-TFM suppressions +dotnet_diagnostic.IDE0130.severity = none # Namespace does not match folder structure — we don't enforce strict mirror +dotnet_diagnostic.IDE0160.severity = none # Use block-scoped namespace — we use file-scoped (IDE0161) +dotnet_diagnostic.IDE0210.severity = none # Convert to top-level statements — we use Main style +dotnet_diagnostic.IDE0211.severity = none # Convert to 'Program.Main' style — we use Main style +dotnet_diagnostic.IDE0280.severity = none # Use nameof +dotnet_diagnostic.IDE0290.severity = none # Use primary constructor — subjective, not enforced +dotnet_diagnostic.IDE0300.severity = none # Use collection expression for array +dotnet_diagnostic.IDE0301.severity = none # Use collection expression for empty +dotnet_diagnostic.IDE0302.severity = none # Use collection expression for stackalloc +dotnet_diagnostic.IDE0303.severity = none # Use collection expression for Create +dotnet_diagnostic.IDE0304.severity = none # Use collection expression for builder +dotnet_diagnostic.IDE0305.severity = none # Use collection expression for fluent +dotnet_diagnostic.IDE0306.severity = none # Use collection expression for new +dotnet_diagnostic.IDE0320.severity = none # Make anonymous function static — eliminates the closure-capture display class allocation +dotnet_diagnostic.IDE0050.severity = none # Convert anonymous type to tuple +dotnet_diagnostic.IDE0230.severity = none # Use UTF-8 string literal — better hot-path encoding for byte-array constants +dotnet_diagnostic.IDE0310.severity = none # Convert lambda expression to method group — a lambda keeps the delegate target explicit +dotnet_diagnostic.IDE0370.severity = none # Remove unnecessary null-forgiving suppression — multi-TFM nullability differs +dotnet_diagnostic.IDE0380.severity = none # Remove unnecessary unsafe modifier +dotnet_diagnostic.IDE1005.severity = none # Use conditional delegate call + +################### +# Microsoft .NET Style Rules (IDE1xxx / IDE3xxx) - Naming & Miscellaneous +################### +# Naming conventions — SST1300 family already enforces PascalCase / interface +# prefix / field casing (with our _underscore convention on SST1306/1309/1311 +# deliberately disabled). Leaving IDE1006 off because configuring +# `dotnet_naming_rule.*` would duplicate what SA already enforces and could +# conflict with the _underscore convention. +dotnet_diagnostic.IDE1006.severity = none # Naming rule violation — SST1300 family handles naming +dotnet_diagnostic.IDE3000.severity = none # Disabled per project convention — not enforced + +################### +# StyleSharp Analyzers (SST) +################### +file_header_template = Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved.\nReactiveUI and Contributors licenses this file to you under the MIT license.\nSee the LICENSE file in the project root for full license information. +stylesharp.summary_single_line_max_length = 120 + +stylesharp.SST2313.allowed_enum_storage = int, uint, long, ulong # deliberately widened enums stay legal + +stylesharp.document_exposed_elements = true # Documentation coverage — every element, private members included +stylesharp.document_internal_elements = true +stylesharp.document_private_elements = true +stylesharp.document_private_fields = true +stylesharp.document_interfaces = all +stylesharp.SST1305.allowed_hungarian_prefixes = rx +stylesharp.tuple_element_naming = pascal_case # SST1316 +stylesharp.instance_member_qualification = omit_this +stylesharp.use_var = always # SST2271; matches the csharp_style_var_* preferences above +stylesharp.max_cyclomatic_complexity = 10 +stylesharp.max_cognitive_complexity = 15 +stylesharp.max_property_cognitive_complexity = 3 +stylesharp.SST1484.check_base_types = true # also report a field shadowed from a base type + +stylesharp.SST2403.allowed_escape_methods = WhenActivated, ToProperty # both hand this straight back, so nothing observes a half-built instance +stylesharp.max_line_length = 200 # SST1521 (characters) +stylesharp.max_file_lines = 1000 # SST1522 (code lines; blank lines and comments do not count) +# stylesharp.max_member_lines = 60 # SST1523 (code lines) +# stylesharp.max_switch_section_lines = 20 # SST1524 (code lines) +# stylesharp.include_internal = true # SST1499 (set false to report only fields visible outside the assembly) +# stylesharp.require_parameterless = true # SST1488 (set false where every exception must carry a message) +# stylesharp.include_non_public_types = true # SST1488 (set false to check only externally visible exceptions) +# Spacing +dotnet_diagnostic.SST1000.severity = error # A control-flow keyword is not followed by a space +dotnet_diagnostic.SST1001.severity = error # A comma is spaced incorrectly +dotnet_diagnostic.SST1002.severity = error # A semicolon is spaced incorrectly +dotnet_diagnostic.SST1003.severity = error # A binary operator is not surrounded by spaces +dotnet_diagnostic.SST1004.severity = error # A documentation comment line does not begin with a single space after the '///' +dotnet_diagnostic.SST1005.severity = error # A single-line comment does not begin with a single space +dotnet_diagnostic.SST1006.severity = error # A preprocessor keyword is preceded by a space after the '#' +dotnet_diagnostic.SST1007.severity = error # An operator keyword is not followed by a space +dotnet_diagnostic.SST1008.severity = error # An opening parenthesis is followed by a space +dotnet_diagnostic.SST1009.severity = error # A closing parenthesis is preceded by a space +dotnet_diagnostic.SST1010.severity = none # Opening square bracket has adjacent whitespace — collection expressions need it +dotnet_diagnostic.SST1011.severity = error # A closing square bracket is preceded by a space +dotnet_diagnostic.SST1012.severity = error # An opening brace is not followed by a space on a single line +dotnet_diagnostic.SST1013.severity = error # A closing brace is not preceded by a space on a single line +dotnet_diagnostic.SST1014.severity = error # An opening generic bracket is preceded or followed by a space +dotnet_diagnostic.SST1015.severity = error # A closing generic bracket is preceded by a space +dotnet_diagnostic.SST1016.severity = error # An opening attribute bracket is followed by a space +dotnet_diagnostic.SST1017.severity = error # A closing attribute bracket is preceded by a space +dotnet_diagnostic.SST1018.severity = error # A nullable type symbol is preceded by a space +dotnet_diagnostic.SST1019.severity = error # A member access symbol is surrounded by spaces +dotnet_diagnostic.SST1020.severity = error # An increment or decrement symbol is separated from its operand by a space +dotnet_diagnostic.SST1021.severity = error # A unary negative sign is followed by a space +dotnet_diagnostic.SST1022.severity = error # A unary positive sign is followed by a space +dotnet_diagnostic.SST1023.severity = error # A dereference or address-of symbol is followed by a space +dotnet_diagnostic.SST1024.severity = error # A colon is spaced incorrectly for its context +dotnet_diagnostic.SST1025.severity = error # Two or more whitespace characters appear in a row within a line +dotnet_diagnostic.SST1026.severity = error # A space follows 'new' or 'stackalloc' in an implicit array creation +dotnet_diagnostic.SST1027.severity = error # A tab character is used where the project standardises on spaces +dotnet_diagnostic.SST1028.severity = error # A line ends with trailing whitespace + +# Readability and maintainability +dotnet_diagnostic.SST1100.severity = error # A base. prefix is used where the type does not override the member +dotnet_diagnostic.SST1102.severity = error # A query clause is separated from the previous clause by a blank line +dotnet_diagnostic.SST1103.severity = error # Query clauses mix single-line and multi-line layout +dotnet_diagnostic.SST1104.severity = error # A query clause shares the last line of a multi-line previous clause +dotnet_diagnostic.SST1105.severity = error # A multi-line query clause does not begin on its own line +dotnet_diagnostic.SST1106.severity = error # A statement is empty (a stray semicolon) +dotnet_diagnostic.SST1107.severity = error # More than one statement shares a line +dotnet_diagnostic.SST1110.severity = error # An opening parenthesis or bracket does not sit on the line of the preceding code +dotnet_diagnostic.SST1111.severity = error # A closing parenthesis or bracket does not sit on the last parameter's line +dotnet_diagnostic.SST1112.severity = error # An empty parameter list's closing parenthesis is on a different line +dotnet_diagnostic.SST1113.severity = error # A comma does not sit on the previous parameter's line +dotnet_diagnostic.SST1114.severity = error # A blank line separates the declaration from its parameter list +dotnet_diagnostic.SST1115.severity = error # A blank line separates a parameter from the preceding comma +dotnet_diagnostic.SST1116.severity = error # A qualified name can be shortened without changing the symbol it binds to +dotnet_diagnostic.SST1117.severity = error # Instance member access follows the configured this. qualification style +dotnet_diagnostic.SST1118.severity = none # A parameter spanning multiple lines — collides with the 200-char line limit +dotnet_diagnostic.SST1119.severity = error # A numeric literal groups its digit separators irregularly +dotnet_diagnostic.SST1120.severity = error # A comment contains no text +dotnet_diagnostic.SST1121.severity = error # A framework type name is used instead of its built-in alias +dotnet_diagnostic.SST1122.severity = error # An empty string literal is used instead of string.Empty +dotnet_diagnostic.SST1123.severity = error # A #region is placed inside a code element body +dotnet_diagnostic.SST1124.severity = error # A #region directive is used +dotnet_diagnostic.SST1125.severity = error # A Nullable type is written in long form instead of the T? shorthand +dotnet_diagnostic.SST1127.severity = error # A generic type constraint shares a line with another constraint +dotnet_diagnostic.SST1128.severity = error # A constructor initializer shares a line with the constructor signature +dotnet_diagnostic.SST1129.severity = error # A value type is created with a parameterless constructor call instead of default +dotnet_diagnostic.SST1130.severity = error # An anonymous delegate is used where a lambda expression is clearer +dotnet_diagnostic.SST1131.severity = error # A comparison places the constant on the left ("yoda" condition) +dotnet_diagnostic.SST1132.severity = error # Several fields are declared in a single statement +dotnet_diagnostic.SST1133.severity = error # Several attributes share one bracket list +dotnet_diagnostic.SST1134.severity = error # An attribute shares a line with another attribute or the element +dotnet_diagnostic.SST1135.severity = error # A using directive names a namespace or type that is not fully qualified +dotnet_diagnostic.SST1136.severity = error # Several enum members share a line +dotnet_diagnostic.SST1137.severity = error # Sibling elements are indented differently from one another +dotnet_diagnostic.SST1138.severity = error # A free-standing block declares nothing +dotnet_diagnostic.SST1139.severity = error # A numeric literal is cast where a literal suffix would express the type +dotnet_diagnostic.SST1140.severity = error # Wrapped conditional operators should start indented continuation lines +dotnet_diagnostic.SST1141.severity = error # An explicit ValueTuple<...> is used where tuple syntax would do +dotnet_diagnostic.SST1142.severity = error # A tuple element is accessed by ItemN where it has a name +dotnet_diagnostic.SST1143.severity = error # A boolean expression is compared to a true/false literal +dotnet_diagnostic.SST1144.severity = error # Combine case labels with an or-pattern +dotnet_diagnostic.SST1145.severity = error # A wrapped conditional expression places ?/: inconsistently +dotnet_diagnostic.SST1146.severity = error # An if statement follows a closing brace on the same line +dotnet_diagnostic.SST1147.severity = error # Do not nest conditional operators +dotnet_diagnostic.SST1148.severity = error # Commented-out code should be removed +dotnet_diagnostic.SST1149.severity = error # Prefer the 'is null' pattern for null checks +dotnet_diagnostic.SST1150.severity = error # Require each constructor parameter on a unique line +dotnet_diagnostic.SST1151.severity = error # Require each method parameter on a unique line +dotnet_diagnostic.SST1152.severity = error # Require each delegate parameter on a unique line +dotnet_diagnostic.SST1153.severity = error # Require each indexer parameter on a unique line +dotnet_diagnostic.SST1154.severity = error # Require each invocation argument on a unique line +dotnet_diagnostic.SST1155.severity = error # Require each object creation argument on a unique line +dotnet_diagnostic.SST1156.severity = error # Require each element access argument on a unique line +dotnet_diagnostic.SST1157.severity = error # Require each attribute argument on a unique line +dotnet_diagnostic.SST1158.severity = error # Require each anonymous method parameter on a unique line +dotnet_diagnostic.SST1159.severity = error # Require each parenthesized lambda parameter on a unique line +dotnet_diagnostic.SST1160.severity = error # Require each record primary-constructor parameter on a unique line +dotnet_diagnostic.SST1161.severity = error # Require each class primary-constructor parameter on a unique line +dotnet_diagnostic.SST1162.severity = error # Require each struct primary-constructor parameter on a unique line +dotnet_diagnostic.SST1163.severity = error # Require each target-typed object creation argument on a unique line +dotnet_diagnostic.SST1164.severity = error # Require each constructor initializer argument on a unique line +dotnet_diagnostic.SST1165.severity = error # Require each primary-constructor base argument on a unique line +dotnet_diagnostic.SST1166.severity = error # Require each local-function parameter on a unique line +dotnet_diagnostic.SST1167.severity = error # Require each operator parameter on a unique line +dotnet_diagnostic.SST1168.severity = error # Require each conversion-operator parameter on a unique line +dotnet_diagnostic.SST1169.severity = error # Require each type parameter on a unique line +dotnet_diagnostic.SST1170.severity = error # Require each type argument on a unique line +dotnet_diagnostic.SST1171.severity = error # Require each function-pointer parameter on a unique line +dotnet_diagnostic.SST1172.severity = error # Negated comparisons should use the opposite operator +dotnet_diagnostic.SST1173.severity = error # Redundant anonymous-type member names should be omitted +dotnet_diagnostic.SST1174.severity = error # Redundant jump statements should be removed +dotnet_diagnostic.SST1175.severity = error # Unnecessary casts should be removed +dotnet_diagnostic.SST1176.severity = error # Members should not be initialized to their default value +dotnet_diagnostic.SST1177.severity = error # Redundant base types should be removed +dotnet_diagnostic.SST1178.severity = error # Redundant base constructor calls should be removed +dotnet_diagnostic.SST1179.severity = error # Redundant default switch sections should be removed +dotnet_diagnostic.SST1180.severity = error # Empty else clauses should be removed +dotnet_diagnostic.SST1181.severity = error # Redundant overriding members should be removed +dotnet_diagnostic.SST1182.severity = error # Conditional expressions should not just return boolean literals +dotnet_diagnostic.SST1183.severity = error # Interpolated strings without interpolations should be plain strings +dotnet_diagnostic.SST1184.severity = error # Verbatim string literals without escapes should be regular strings +dotnet_diagnostic.SST1185.severity = error # Use a compound assignment operator +dotnet_diagnostic.SST1186.severity = error # A literal should be on the right side of a comparison +dotnet_diagnostic.SST1187.severity = error # Assignments should not be chained +dotnet_diagnostic.SST1188.severity = error # Use the 'default' literal instead of 'default(T)' +dotnet_diagnostic.SST1189.severity = error # Variables should not be self-assigned +dotnet_diagnostic.SST1190.severity = error # Doubled negation operators should be removed +dotnet_diagnostic.SST1191.severity = error # Long numeric literals should use digit separators +dotnet_diagnostic.SST1192.severity = error # Control characters in string literals should be escaped +dotnet_diagnostic.SST1193.severity = error # Keep initial member values with construction +dotnet_diagnostic.SST1194.severity = error # Keep initial collection values with construction +dotnet_diagnostic.SST1195.severity = error # Write null fallback with ?? +dotnet_diagnostic.SST1196.severity = error # Write null-guarded access with ?. +dotnet_diagnostic.SST1197.severity = error # Collapse return-only branches into one return +dotnet_diagnostic.SST1198.severity = error # Collapse assignment-only branches into one assignment +dotnet_diagnostic.SST1199.severity = error # Prefer compile-time type names + +# Ordering +dotnet_diagnostic.SST1200.severity = error # Using directives should be placed outside the namespace +dotnet_diagnostic.SST1201.severity = error # Members should be ordered by kind +dotnet_diagnostic.SST1202.severity = error # Members should be ordered by accessibility +dotnet_diagnostic.SST1203.severity = error # Constants should appear before fields +dotnet_diagnostic.SST1204.severity = error # Static members should appear before instance members +dotnet_diagnostic.SST1205.severity = error # Partial elements should declare an access modifier +dotnet_diagnostic.SST1206.severity = error # Declaration keywords should follow the standard order +dotnet_diagnostic.SST1207.severity = error # Place protected before internal +dotnet_diagnostic.SST1208.severity = error # System using directives should appear before other usings +dotnet_diagnostic.SST1209.severity = error # Using alias directives should appear after other usings +dotnet_diagnostic.SST1210.severity = error # Regular using directives should be ordered alphabetically +dotnet_diagnostic.SST1211.severity = error # Using alias directives should be ordered alphabetically by alias +dotnet_diagnostic.SST1212.severity = error # Property accessors should be ordered with get first +dotnet_diagnostic.SST1213.severity = error # Event accessors should be ordered with add first +dotnet_diagnostic.SST1214.severity = error # Static readonly fields should appear before static non-readonly fields +dotnet_diagnostic.SST1215.severity = error # Instance readonly fields should appear before instance non-readonly fields +dotnet_diagnostic.SST1216.severity = error # Using static directives should be placed after regular usings and before aliases +dotnet_diagnostic.SST1217.severity = error # Using static directives should be ordered alphabetically +dotnet_diagnostic.SST1218.severity = error # Other members separate a method's overloads +dotnet_diagnostic.SST1219.severity = error # A switch default clause is not placed last +dotnet_diagnostic.SST1220.severity = error # An all-named argument list is not in declaration order +dotnet_diagnostic.SST1221.severity = error # where constraint clauses do not match the type-parameter order +dotnet_diagnostic.SST1222.severity = error # An enum with explicit values declares them out of ascending order + +# Naming +dotnet_diagnostic.SST1300.severity = error # Types and members should be PascalCase +dotnet_diagnostic.SST1302.severity = error # Interface names should begin with I +dotnet_diagnostic.SST1303.severity = error # Const names should be PascalCase +dotnet_diagnostic.SST1304.severity = error # Non-private readonly fields should be PascalCase +dotnet_diagnostic.SST1305.severity = error # Field names should not use Hungarian notation +dotnet_diagnostic.SST1306.severity = none # Field names should begin lower-case — private fields use _camelCase here +dotnet_diagnostic.SST1307.severity = error # Accessible fields should be PascalCase +dotnet_diagnostic.SST1308.severity = none # Field names should not use m_ or s_ prefixes — too broad for our conventions +dotnet_diagnostic.SST1309.severity = error # Private fields should be _camelCase +dotnet_diagnostic.SST1310.severity = none # Field names should not contain underscores — conflicts with _camelCase +dotnet_diagnostic.SST1311.severity = none # Static readonly fields should be PascalCase — we use _camelCase there too +dotnet_diagnostic.SST1312.severity = error # Local variables should be camelCase +dotnet_diagnostic.SST1313.severity = error # Parameters should be camelCase +dotnet_diagnostic.SST1314.severity = error # Type parameters should begin with T +dotnet_diagnostic.SST1315.severity = error # Union member names should match the configured casing +dotnet_diagnostic.SST1316.severity = error # Tuple element names should use the configured casing +dotnet_diagnostic.SST1317.severity = none # Async method names should end with 'Async' — conflicts with our Rx naming +dotnet_diagnostic.SST1318.severity = error # Overriding parameter names should match the base declaration +dotnet_diagnostic.SST1319.severity = error # An enumeration's type name is not PascalCase +dotnet_diagnostic.SST1320.severity = error # A parameter name matches its method's name +dotnet_diagnostic.SST1321.severity = none # Async naming without an awaitable return — deliberate on our public APIs + +# Maintainability +dotnet_diagnostic.SST1400.severity = error # An element does not declare an access modifier +dotnet_diagnostic.SST1401.severity = error # A non-private, non-constant field is exposed +dotnet_diagnostic.SST1402.severity = error # A file declares more than one top-level type +dotnet_diagnostic.SST1403.severity = error # A file declares more than one namespace +dotnet_diagnostic.SST1404.severity = error # A code-analysis suppression has no justification +dotnet_diagnostic.SST1405.severity = error # A Debug.Assert call provides no message +dotnet_diagnostic.SST1406.severity = error # A Debug.Fail call provides no message +dotnet_diagnostic.SST1407.severity = error # Mixed-precedence arithmetic is not parenthesized +dotnet_diagnostic.SST1408.severity = error # Mixed conditional operators are not parenthesized +dotnet_diagnostic.SST1410.severity = error # An anonymous method has an empty parameter list +dotnet_diagnostic.SST1411.severity = error # An attribute uses an empty argument list +dotnet_diagnostic.SST1412.severity = none # Store files as UTF-8 with a BOM — conflicts with SST1450 (no BOM) +dotnet_diagnostic.SST1413.severity = error # A multi-line initializer omits the trailing comma +dotnet_diagnostic.SST1414.severity = error # A tuple type in a member signature has an unnamed element +dotnet_diagnostic.SST1415.severity = error # An argument-exception constructor uses a literal instead of nameof +dotnet_diagnostic.SST1416.severity = none # Public members in a non-public type — reflection binding needs them public +dotnet_diagnostic.SST1417.severity = none # Namespace should match the folder — BCL-namespace types cannot comply +dotnet_diagnostic.SST1418.severity = error # Declare precedence when mixing the null-coalescing operator +dotnet_diagnostic.SST1419.severity = error # Remove redundant modifiers +dotnet_diagnostic.SST1420.severity = error # Trivial properties should be auto-implemented +dotnet_diagnostic.SST1421.severity = error # Write-only properties should not be used +dotnet_diagnostic.SST1422.severity = error # Private fields used only as locals should be local variables +dotnet_diagnostic.SST1423.severity = error # Switch statements should not have too many sections +dotnet_diagnostic.SST1424.severity = error # Fields that are never reassigned should be readonly +dotnet_diagnostic.SST1425.severity = error # Do not reassign captured primary-constructor parameters +dotnet_diagnostic.SST1426.severity = error # Use [SuppressMessage] instead of #pragma warning disable +dotnet_diagnostic.SST1427.severity = error # Protected members of sealed types should not be used +dotnet_diagnostic.SST1428.severity = error # Abstract types should not declare public constructors +dotnet_diagnostic.SST1429.severity = error # Empty catch clauses should not swallow the base exception +dotnet_diagnostic.SST1430.severity = error # Rethrow with 'throw;' to preserve the stack trace +dotnet_diagnostic.SST1431.severity = error # Static members of a generic type should use a type parameter +dotnet_diagnostic.SST1432.severity = error # Classes with only static members should be static +dotnet_diagnostic.SST1433.severity = error # Redundant constructors should be removed +dotnet_diagnostic.SST1435.severity = error # Empty namespace declarations should be removed +dotnet_diagnostic.SST1436.severity = error # Empty types should not be declared +dotnet_diagnostic.SST1437.severity = error # Empty interfaces should not be declared +dotnet_diagnostic.SST1438.severity = error # Methods should not be empty +dotnet_diagnostic.SST1439.severity = error # Nested code blocks should not be left empty +dotnet_diagnostic.SST1440.severity = error # Private members with no local use should be removed +dotnet_diagnostic.SST1441.severity = error # Private fields assigned but never read should be removed +dotnet_diagnostic.SST1442.severity = error # A function has too many direct branch points +dotnet_diagnostic.SST1443.severity = error # A function has too much nested control flow +dotnet_diagnostic.SST1444.severity = error # A loop cannot naturally reach a second iteration +dotnet_diagnostic.SST1445.severity = error # A using directive is unnecessary +dotnet_diagnostic.SST1446.severity = error # An inheritance chain is deeper than the configured maximum +dotnet_diagnostic.SST1447.severity = error # An equality override delegates to object reference semantics +dotnet_diagnostic.SST1448.severity = error # An argument is passed explicitly to a caller-info parameter +dotnet_diagnostic.SST1449.severity = error # Code writes directly to the console +dotnet_diagnostic.SST1450.severity = error # Store files as UTF-8 without a byte order mark +dotnet_diagnostic.SST1451.severity = error # A DateTime is created without a DateTimeKind +dotnet_diagnostic.SST1452.severity = error # A generic type parameter is never used +dotnet_diagnostic.SST1453.severity = error # Statements after an unconditional exit should be removed +dotnet_diagnostic.SST1454.severity = error # Composite format placeholders should match the supplied arguments +dotnet_diagnostic.SST1455.severity = error # Unsafe modifiers should be used only when unsafe syntax is present +dotnet_diagnostic.SST1456.severity = error # Readonly fields should not store mutable source-defined structs +dotnet_diagnostic.SST1457.severity = error # Global suppressions should point at real declarations +dotnet_diagnostic.SST1458.severity = error # Global suppression targets should use declaration ids directly +dotnet_diagnostic.SST1459.severity = error # Grouping parentheses the parent syntax already isolates +dotnet_diagnostic.SST1460.severity = error # Non-mutating struct members should be readonly +dotnet_diagnostic.SST1461.severity = error # Private parameters that are never read should be removed +dotnet_diagnostic.SST1462.severity = error # Suppressions for diagnostics already disabled by config should be removed +dotnet_diagnostic.SST1463.severity = error # Symbol-name strings should use nameof +dotnet_diagnostic.SST1464.severity = error # An else clause follows a branch that always jumps and can be unwrapped +dotnet_diagnostic.SST1465.severity = error # An else block that only wraps an if can collapse to else-if +dotnet_diagnostic.SST1466.severity = error # A case label sharing a section with default is redundant +dotnet_diagnostic.SST1467.severity = error # A hand-driven enumerator loop can use foreach +dotnet_diagnostic.SST1468.severity = error # Boolean logic should use the short-circuiting && and || operators +dotnet_diagnostic.SST1469.severity = error # A non-nullable value type is compared to null +dotnet_diagnostic.SST1470.severity = error # A trailing catch clause that only rethrows should be removed +dotnet_diagnostic.SST1471.severity = error # Magic numbers should be named constants +dotnet_diagnostic.SST1472.severity = error # Signatures should not declare too many parameters +dotnet_diagnostic.SST1473.severity = error # A floating-point value is compared for exact equality +dotnet_diagnostic.SST1474.severity = error # Both sides of an operator are the same expression +dotnet_diagnostic.SST1475.severity = error # A condition repeats an earlier one in the chain, so its branch cannot run +dotnet_diagnostic.SST1476.severity = error # Every branch of a conditional has the same body +dotnet_diagnostic.SST1477.severity = error # An integer division is widened to floating point after it has already truncated +dotnet_diagnostic.SST1478.severity = error # A shift count is zero, negative, or at least the operand's width +dotnet_diagnostic.SST1479.severity = error # A count or length is compared against a value it can never take +dotnet_diagnostic.SST1480.severity = error # An exception is constructed and then discarded +dotnet_diagnostic.SST1481.severity = error # A bitwise operation has a constant operand that makes it pointless +dotnet_diagnostic.SST1482.severity = error # GetHashCode reads mutable state +dotnet_diagnostic.SST1483.severity = error # A constructor calls an overridable member +dotnet_diagnostic.SST1484.severity = error # A declaration shadows an outer field or property (inherited fields included) +dotnet_diagnostic.SST1485.severity = error # A member that must not throw throws +dotnet_diagnostic.SST1486.severity = error # The same string literal is repeated instead of being named +dotnet_diagnostic.SST1487.severity = error # A collection element is assigned twice with nothing reading it in between +dotnet_diagnostic.SST1488.severity = error # An exception type does not declare the standard constructors +dotnet_diagnostic.SST1489.severity = error # An exception type carries obsoleted serialization members +dotnet_diagnostic.SST1490.severity = error # A base list names an interface the rest of the list already implies +dotnet_diagnostic.SST1491.severity = error # A modifier restates the declaration's default +dotnet_diagnostic.SST1492.severity = error # A value is tested against what it is then assigned, so the guard decides nothing +dotnet_diagnostic.SST1493.severity = error # A method's whole body is a constant +dotnet_diagnostic.SST1494.severity = error # A trailing argument repeats the parameter's default +dotnet_diagnostic.SST1495.severity = error # '==' compares references on a type that overrides Equals, so the two disagree +dotnet_diagnostic.SST1496.severity = error # An abstract type declares nothing abstract +dotnet_diagnostic.SST1497.severity = error # A local is declared and never read +dotnet_diagnostic.SST1498.severity = error # Only a nested type uses a private member +dotnet_diagnostic.SST1499.severity = error # A static field visible outside its type can still be changed + +# Layout +dotnet_diagnostic.SST1500.severity = error # A brace in a multi-line construct shares its line with other code +dotnet_diagnostic.SST1501.severity = error # A statement block is collapsed onto a single line +dotnet_diagnostic.SST1502.severity = error # An element body is collapsed onto a single line +dotnet_diagnostic.SST1503.severity = error # A control-flow statement omits the braces around its child statement +dotnet_diagnostic.SST1504.severity = error # The accessors of a property/event mix single-line and multi-line forms +dotnet_diagnostic.SST1505.severity = error # An opening brace is followed by a blank line +dotnet_diagnostic.SST1506.severity = error # An element documentation header is followed by a blank line +dotnet_diagnostic.SST1507.severity = error # Two or more blank lines appear in a row +dotnet_diagnostic.SST1508.severity = error # A closing brace is preceded by a blank line +dotnet_diagnostic.SST1509.severity = error # An opening brace is preceded by a blank line +dotnet_diagnostic.SST1510.severity = error # A chained block such as else/catch/finally is preceded by a blank line +dotnet_diagnostic.SST1511.severity = error # The while footer of a do/while loop is preceded by a blank line +dotnet_diagnostic.SST1512.severity = error # A single-line comment is followed by a blank line +dotnet_diagnostic.SST1513.severity = error # A closing brace is not followed by a blank line +dotnet_diagnostic.SST1514.severity = error # An element documentation header is not preceded by a blank line +dotnet_diagnostic.SST1515.severity = error # A single-line comment is not preceded by a blank line +dotnet_diagnostic.SST1516.severity = error # Adjacent members or namespace elements are not separated by a blank line +dotnet_diagnostic.SST1517.severity = error # The file begins with one or more blank lines +dotnet_diagnostic.SST1518.severity = error # The file does not end with exactly one newline +dotnet_diagnostic.SST1519.severity = error # A multi-line child statement of a control-flow keyword omits its braces +dotnet_diagnostic.SST1520.severity = error # The clauses of an if/else chain use braces inconsistently +dotnet_diagnostic.SST1521.severity = error # A line is longer than the configured maximum (default 120 characters) +dotnet_diagnostic.SST1522.severity = error # A file has more code lines than the configured maximum (default 500) +dotnet_diagnostic.SST1523.severity = error # A member has more code lines than the configured maximum (default 60) +dotnet_diagnostic.SST1524.severity = error # A switch section has more code lines than the configured maximum (default 20) +dotnet_diagnostic.SST1525.severity = error # A multi-statement switch section has no braces +dotnet_diagnostic.SST1526.severity = error # A wrapped binary expression places the operator inconsistently +dotnet_diagnostic.SST1527.severity = error # The => of an expression-bodied member wraps inconsistently +dotnet_diagnostic.SST1528.severity = error # The `=` of a wrapped initializer wraps inconsistently. Configurable. Opt-in. +dotnet_diagnostic.SST1529.severity = error # A wrapped call chain places the break inconsistently +dotnet_diagnostic.SST1530.severity = error # A newline sits between a type declaration and its base list +dotnet_diagnostic.SST1531.severity = error # A short object initializer is split across lines +dotnet_diagnostic.SST1532.severity = error # A file mixes line endings. Configurable (`lf`/`crlf`, default lf). Opt-in. +dotnet_diagnostic.SST1533.severity = none # A source file contains no code — a polyfill behind #if is empty by design +dotnet_diagnostic.SST1534.severity = none # Switch braces that scope nothing — conflicts with SST1525's braces-on policy +dotnet_diagnostic.SST1535.severity = error # A constructor initializer colon should not be followed by a blank line +dotnet_diagnostic.SST1536.severity = error # A conditional operator token should not be followed by a blank line +dotnet_diagnostic.SST1537.severity = error # An expression-body arrow should not be followed by a blank line + +# Documentation +dotnet_diagnostic.SST1600.severity = error # Externally visible members should be documented +dotnet_diagnostic.SST1601.severity = error # Partial elements should be documented +dotnet_diagnostic.SST1602.severity = error # Enumeration members should be documented +dotnet_diagnostic.SST1604.severity = error # Element documentation should contain a summary +dotnet_diagnostic.SST1605.severity = error # Partial element documentation should have a summary +dotnet_diagnostic.SST1606.severity = error # The summary should have text +dotnet_diagnostic.SST1607.severity = error # Partial element summary should have text +dotnet_diagnostic.SST1608.severity = error # Documentation should not use the default placeholder summary +dotnet_diagnostic.SST1609.severity = none # Property docs should have a value — it only restates the summary +dotnet_diagnostic.SST1610.severity = error # Property value documentation should have text +dotnet_diagnostic.SST1611.severity = error # Parameters should be documented +dotnet_diagnostic.SST1612.severity = error # Parameter documentation should match the parameters +dotnet_diagnostic.SST1613.severity = error # Parameter documentation should declare a name +dotnet_diagnostic.SST1614.severity = error # Parameter documentation should have text +dotnet_diagnostic.SST1615.severity = error # The return value should be documented + +dotnet_diagnostic.SST1616.severity = error # Return value documentation should have text +dotnet_diagnostic.SST1617.severity = error # A void return value should not be documented +dotnet_diagnostic.SST1618.severity = error # Generic type parameters should be documented +dotnet_diagnostic.SST1619.severity = error # Partial generic type parameters should be documented +dotnet_diagnostic.SST1620.severity = error # Type parameter documentation should match the type parameters +dotnet_diagnostic.SST1621.severity = error # Type parameter documentation should declare a name +dotnet_diagnostic.SST1622.severity = error # Type parameter documentation should have text +dotnet_diagnostic.SST1623.severity = error # Property summaries should describe their accessors +dotnet_diagnostic.SST1624.severity = error # Property summary should omit a restricted set accessor +dotnet_diagnostic.SST1625.severity = error # Element documentation should not be copy-pasted +dotnet_diagnostic.SST1626.severity = error # A documentation-style comment is used where it does not document an element +dotnet_diagnostic.SST1627.severity = error # Documentation text should not be empty +dotnet_diagnostic.SST1628.severity = error # Documentation text should begin with a capital letter +dotnet_diagnostic.SST1629.severity = error # Documentation text should end with a period +dotnet_diagnostic.SST1630.severity = error # Documentation text should contain whitespace +dotnet_diagnostic.SST1631.severity = error # Documentation text should be mostly letters +dotnet_diagnostic.SST1632.severity = error # Documentation text should meet a minimum length +dotnet_diagnostic.SST1633.severity = error # Files should begin with the configured header +dotnet_diagnostic.SST1642.severity = error # Constructor summaries should begin with the standard text +dotnet_diagnostic.SST1643.severity = error # Destructor summaries should begin with the standard text +dotnet_diagnostic.SST1644.severity = error # Documentation headers should not contain blank lines +dotnet_diagnostic.SST1648.severity = error # inheritdoc should be used with inheriting elements +dotnet_diagnostic.SST1649.severity = error # The file name should match the first type name +dotnet_diagnostic.SST1651.severity = error # Placeholder documentation elements should be removed +dotnet_diagnostic.SST1653.severity = error # Keep short documentation summaries on a single line +dotnet_diagnostic.SST1654.severity = error # Extension blocks should be documented with a summary +dotnet_diagnostic.SST1655.severity = error # Extension block parameters should be documented +dotnet_diagnostic.SST1656.severity = error # Extension block type parameters should be documented +dotnet_diagnostic.SST1657.severity = error # Extension block docs name an unknown parameter or type parameter +dotnet_diagnostic.SST1658.severity = error # Documentation text repeats a word +dotnet_diagnostic.SST1659.severity = error # A comment has no text at all +dotnet_diagnostic.SST1660.severity = error # The `` tags are not in parameter order. Code fix reorders them. Info. +dotnet_diagnostic.SST1661.severity = error # A snippet uses / mismatched to its content +dotnet_diagnostic.SST1662.severity = error # A thrown exception type has no documentation +dotnet_diagnostic.SST1663.severity = error # A // comment before a public member reads like a summary +dotnet_diagnostic.SST1664.severity = error # A summary separates paragraphs with blank lines instead of +dotnet_diagnostic.SST1665.severity = error # An names a type but says nothing about what triggers it +dotnet_diagnostic.SST1666.severity = error # Documentation elements are out of the conventional order + +# Concurrency and modernization +dotnet_diagnostic.SST1901.severity = error # A lock targets a field or property reachable from outside the declaring type +dotnet_diagnostic.SST1902.severity = error # Do not lock on 'this', a Type, or a string +dotnet_diagnostic.SST1903.severity = error # Do not lock on a newly-created object +dotnet_diagnostic.SST1904.severity = error # A lock targets a non-readonly field +dotnet_diagnostic.SST1905.severity = error # An async method or converted delegate returns void +dotnet_diagnostic.SST2000.severity = error # A null check plus throw should use ArgumentNullException.ThrowIfNull +dotnet_diagnostic.SST2001.severity = error # Use ArgumentException.ThrowIfNullOrEmpty +dotnet_diagnostic.SST2002.severity = error # Use ArgumentException.ThrowIfNullOrWhiteSpace +dotnet_diagnostic.SST2003.severity = error # A disposed check should use ObjectDisposedException.ThrowIf +dotnet_diagnostic.SST2004.severity = error # A range check should use an ArgumentOutOfRangeException.ThrowIf... helper +dotnet_diagnostic.SST2005.severity = error # Use the 'is' type pattern instead of comparing an 'as' cast to null +dotnet_diagnostic.SST2006.severity = error # Use the 'is not' pattern instead of negating an 'is' check +dotnet_diagnostic.SST2007.severity = error # Use declaration patterns instead of an is check followed by a cast local +dotnet_diagnostic.SST2008.severity = error # Negated pattern tests should use is-not patterns +dotnet_diagnostic.SST2009.severity = error # A catch that tests then rethrows can use a when filter +dotnet_diagnostic.SST2010.severity = error # A type reads the machine clock directly instead of through a TimeProvider +dotnet_diagnostic.SST2011.severity = error # An instant is recorded from the local clock rather than in UTC +dotnet_diagnostic.SST2012.severity = error # A GUID is constructed with the parameterless constructor instead of Guid.Empty +dotnet_diagnostic.SST2013.severity = error # An if whose entire body is another if should be merged +dotnet_diagnostic.SST2014.severity = error # A goto jumps to a label +dotnet_diagnostic.SST2015.severity = error # A ++ or -- is buried inside a larger expression +dotnet_diagnostic.SST2016.severity = error # A DateTime on a visible signature loses its offset at the boundary +dotnet_diagnostic.SST2017.severity = error # A .Date or .TimeOfDay read proves the value is only one of the two +dotnet_diagnostic.SST2018.severity = error # A redundant null check sits beside an is type pattern +dotnet_diagnostic.SST2019.severity = error # Test for null rather than for the object type + +# Modern language and library usage +dotnet_diagnostic.SST1700.severity = error # An extension block declares no members +dotnet_diagnostic.SST1701.severity = error # Two extension blocks in a type share the same receiver type +dotnet_diagnostic.SST1702.severity = error # Extension blocks in a type are separated by other members +dotnet_diagnostic.SST1703.severity = error # A classic this-parameter extension method could be an extension block +dotnet_diagnostic.SST1704.severity = error # A class declaring extension blocks is not named with an Extensions suffix +dotnet_diagnostic.SST1705.severity = error # A class mixes classic extension methods with extension blocks +dotnet_diagnostic.SST1706.severity = error # An extension block targets a broad receiver type such as object or dynamic +dotnet_diagnostic.SST1707.severity = error # Extension blocks should be ordered by receiver type +dotnet_diagnostic.SST1708.severity = error # An extension method never uses its this receiver +dotnet_diagnostic.SST1709.severity = error # A method in an *Extensions class whose first parameter lacks this +dotnet_diagnostic.SST1710.severity = error # An accessor-shaped extension method reads better as an extension indexer +dotnet_diagnostic.SST1711.severity = error # An extension block member never reads the block's receiver +dotnet_diagnostic.SST1712.severity = error # An extension block of only static members names a receiver nothing can read +dotnet_diagnostic.SST1800.severity = error # Record classes should be sealed +dotnet_diagnostic.SST1801.severity = error # A positional record parameter does not match the configured casing +dotnet_diagnostic.SST1802.severity = error # A record declares a settable rather than init-only instance property +dotnet_diagnostic.SST1803.severity = error # A record struct is not declared readonly +dotnet_diagnostic.SST1804.severity = error # A positional record has an empty { } body where ; would do +dotnet_diagnostic.SST2100.severity = error # An empty collection creation can use [] +dotnet_diagnostic.SST2101.severity = error # An explicit collection creation can use [...] +dotnet_diagnostic.SST2102.severity = error # A span-targeted stackalloc initializer can use a collection expression +dotnet_diagnostic.SST2103.severity = error # A collection-builder factory call can use a collection expression +dotnet_diagnostic.SST2104.severity = error # A short builder-local sequence can return a collection expression +dotnet_diagnostic.SST2105.severity = error # A literal array materialized with LINQ can use a collection expression +dotnet_diagnostic.SST2106.severity = error # A collection expression drops the capacity or comparer the creation carried +dotnet_diagnostic.SST2200.severity = error # A single-use backing field can use the C# 14 field keyword +dotnet_diagnostic.SST2201.severity = error # A return-only switch statement can use a switch expression +dotnet_diagnostic.SST2202.severity = error # An object creation repeats an explicit target type +dotnet_diagnostic.SST2203.severity = error # An array or string index can use from-end indexing +dotnet_diagnostic.SST2204.severity = error # A string slice can use range syntax +dotnet_diagnostic.SST2205.severity = none # Enum switch statement omits named values — deliberate; SST2206 covers these +dotnet_diagnostic.SST2206.severity = error # An enum switch expression omits named enum values +dotnet_diagnostic.SST2207.severity = error # A null guard and return can keep the throw in the returned expression +dotnet_diagnostic.SST2208.severity = error # An out variable can be declared at the call site +dotnet_diagnostic.SST2209.severity = error # A null-forgiving operator has no local effect +dotnet_diagnostic.SST2210.severity = error # A nullable directive repeats the current file-local state +dotnet_diagnostic.SST2211.severity = error # A nullable restore directive has no file-local state to restore +dotnet_diagnostic.SST2212.severity = error # Literal UTF-8 byte data can use a u8 string literal +dotnet_diagnostic.SST2213.severity = error # A typed pattern has an unnecessary discard designation +dotnet_diagnostic.SST2214.severity = error # A tuple temporary only feeds copied element locals +dotnet_diagnostic.SST2215.severity = error # A temporary local swaps two locals +dotnet_diagnostic.SST2216.severity = error # A tuple element name repeats the inferred name +dotnet_diagnostic.SST2217.severity = error # A manual hash-code expression can use System.HashCode.Combine +dotnet_diagnostic.SST2218.severity = error # Lambda parameter types can be omitted when the target already supplies them +dotnet_diagnostic.SST2219.severity = error # A single-expression property accessor can use an expression body +dotnet_diagnostic.SST2220.severity = error # An interpolation hole can carry the value and literal format directly +dotnet_diagnostic.SST2221.severity = error # An ignored expression value is assigned to the discard +dotnet_diagnostic.SST2222.severity = error # A local value is overwritten before it is read +dotnet_diagnostic.SST2223.severity = error # A null fallback assignment can use ??= +dotnet_diagnostic.SST2224.severity = error # An anonymous object can become a tuple literal for local value bundles +dotnet_diagnostic.SST2225.severity = error # A foreach loop hides an explicit element cast +dotnet_diagnostic.SST2226.severity = error # A cast hides an inner explicit conversion +dotnet_diagnostic.SST2227.severity = error # A post-assignment null fallback can be folded into the assigned expression +dotnet_diagnostic.SST2228.severity = error # A delegate local used only as a call target can be a local function +dotnet_diagnostic.SST2231.severity = error # A broad object pattern can use a direct null pattern +dotnet_diagnostic.SST2232.severity = error # nameof does not need concrete generic type arguments +dotnet_diagnostic.SST2234.severity = error # Nullable should use the T? shorthand +dotnet_diagnostic.SST2235.severity = error # Capture-free local functions should be static +dotnet_diagnostic.SST2236.severity = error # Tail-position using blocks can use using declarations +dotnet_diagnostic.SST2237.severity = error # Single block-scoped namespaces can use file-scoped syntax +dotnet_diagnostic.SST2238.severity = error # Nested property patterns can use extended property syntax +dotnet_diagnostic.SST2239.severity = error # Forwarding lambdas can use method groups +dotnet_diagnostic.SST2240.severity = error # Delegate null checks can use conditional invocation +dotnet_diagnostic.SST2241.severity = error # Constructors that only store parameters can use primary-constructor storage +dotnet_diagnostic.SST2242.severity = error # Enum switch mappings should name every value or include a catch-all +dotnet_diagnostic.SST2243.severity = error # A verbatim string with escapes or line breaks can use a raw string literal +dotnet_diagnostic.SST2244.severity = error # A numeric literal's suffix is lower case +dotnet_diagnostic.SST2245.severity = error # A for loop with only a condition should be a while loop +dotnet_diagnostic.SST2246.severity = error # A chain of conditionals against constants can be a switch expression +dotnet_diagnostic.SST2247.severity = error # Consecutive locals copying one value's members in order can be a deconstruction +dotnet_diagnostic.SST2248.severity = error # Two constant comparisons of the same value can fold into one is-pattern +dotnet_diagnostic.SST2249.severity = error # A literal string.Format or concatenation can be interpolated +dotnet_diagnostic.SST2250.severity = error # A bare local assigned by the next statement can be an initialized declaration +dotnet_diagnostic.SST2251.severity = error # A method call names type arguments that inference would supply +dotnet_diagnostic.SST2252.severity = error # A switch statement is nested inside another switch statement +dotnet_diagnostic.SST2254.severity = none # Explicit type where new() is written — counterpart to SST2202, enable one +dotnet_diagnostic.SST2255.severity = error # A hand-written null-or-empty string test. Code fix uses `string.IsNullOrEmpty`. +dotnet_diagnostic.SST2256.severity = error # An extension method called in static form +dotnet_diagnostic.SST2257.severity = error # A lambda block body that is a single return +dotnet_diagnostic.SST2258.severity = error # A redundant explicit delegate wrapper +dotnet_diagnostic.SST2259.severity = error # A stray `;` after a type declaration. Code fix removes it. Info. +dotnet_diagnostic.SST2260.severity = error # An `as` cast to a type the operand already has. Code fix removes it. Info. +dotnet_diagnostic.SST2261.severity = error # `(x && !y) +dotnet_diagnostic.SST2262.severity = error # A raw string literal whose content needs no raw syntax +dotnet_diagnostic.SST2263.severity = error # An infinite loop whose body re-derives its stop condition +dotnet_diagnostic.SST2264.severity = error # A numeric literal cast to an enum. Code fix names the member. +dotnet_diagnostic.SST2265.severity = error # Consecutive fluent calls on one receiver can fold into a chain +dotnet_diagnostic.SST2266.severity = error # A local read exactly once can be inlined into that use +dotnet_diagnostic.SST2267.severity = error # Infinite loops written in mixed `while(true)`/`for(;;)` styles. Configurable. +dotnet_diagnostic.SST2268.severity = error # Inconsistent `()` on object creation with an initializer. Configurable. +dotnet_diagnostic.SST2269.severity = error # Inconsistent parentheses around a conditional's condition. Configurable. +dotnet_diagnostic.SST2270.severity = error # Inconsistent explicit-vs-implicit array-creation type. Configurable. +dotnet_diagnostic.SST2271.severity = error # `var`-vs-explicit local type per the configured preference. Configurable. +dotnet_diagnostic.SST2272.severity = error # `[Flags]` member values written as mixed decimals and shifts. Configurable. +dotnet_diagnostic.SST2273.severity = error # A trailing if that could be an early-exit guard clause +dotnet_diagnostic.SST2274.severity = error # An 'as' assignment plus null check is one is-declaration pattern +dotnet_diagnostic.SST2275.severity = error # A method whose block body is a single statement can use => expr +dotnet_diagnostic.SST2276.severity = error # A constructor whose block body is a single statement can use => +dotnet_diagnostic.SST2277.severity = error # An operator whose block body is a single return can use => +dotnet_diagnostic.SST2278.severity = error # A conversion operator whose block body is a single return can use => +dotnet_diagnostic.SST2279.severity = error # A get-only property whose getter is a single return can use => +dotnet_diagnostic.SST2280.severity = error # A get-only indexer whose getter is a single return can use => +dotnet_diagnostic.SST2281.severity = error # A local function whose block body is a single statement can use => +dotnet_diagnostic.SST2282.severity = error # A ReferenceEquals check against null reads as an is null pattern +dotnet_diagnostic.SST2283.severity = error # A null guard before an assignment can fold into it as ?? throw +dotnet_diagnostic.SST2284.severity = error # A statement steps a value by one through a compound assignment +dotnet_diagnostic.SST2285.severity = error # A null guard is conjoined with a member read on the same value +dotnet_diagnostic.SST2286.severity = error # ToString is called on a receiver already typed as string +dotnet_diagnostic.SST2287.severity = error # A while loop owns its counter, so a for header would gather it +dotnet_diagnostic.SST2288.severity = error # A conditional expression has a boolean literal in exactly one branch +dotnet_diagnostic.SST2289.severity = error # An unsafe block no longer needs an unsafe context +# Design +dotnet_diagnostic.SST2300.severity = error # A class implements IDisposable but builds only half of the disposal pattern +dotnet_diagnostic.SST2301.severity = error # A class implementing IEquatable for itself can still be derived from +dotnet_diagnostic.SST2302.severity = error # A type overloads an operator without the rest of the set it belongs to +dotnet_diagnostic.SST2303.severity = error # A [Flags] enum's members are not distinct bit values +dotnet_diagnostic.SST2304.severity = error # An event delegate lacks the (object sender, TEventArgs e) shape +dotnet_diagnostic.SST2305.severity = error # A mutable collection property declares a caller-visible setter +dotnet_diagnostic.SST2306.severity = error # A collection-returning member hands back null +dotnet_diagnostic.SST2307.severity = error # A generic method type parameter appears in no parameter and cannot be inferred +dotnet_diagnostic.SST2308.severity = error # An [Obsolete] attribute carries no message +dotnet_diagnostic.SST2309.severity = error # An externally visible member declares an optional parameter +dotnet_diagnostic.SST2310.severity = error # Deprecated code is still here; remove it once its last caller is gone +dotnet_diagnostic.SST2311.severity = error # A visible const is copied into every assembly that reads it +dotnet_diagnostic.SST2312.severity = error # A type is declared outside any namespace +dotnet_diagnostic.SST2313.severity = error # An enum is stored as a type the project does not allow +dotnet_diagnostic.SST2314.severity = none # [Obsolete] with a message but no DiagnosticId — the property is .NET 5+ only +dotnet_diagnostic.SST2315.severity = error # A type owns a disposable field but does not implement IDisposable +dotnet_diagnostic.SST2316.severity = error # A type declares Dispose or DisposeAsync without implementing IDisposable +dotnet_diagnostic.SST2317.severity = error # A disposable type owns a raw IntPtr without a SafeHandle or finalizer +dotnet_diagnostic.SST2318.severity = error # Two members have token-identical bodies +dotnet_diagnostic.SST2319.severity = error # An overload's optional default can never be used +dotnet_diagnostic.SST2320.severity = error # An interface inherits two interfaces that declare the same member +dotnet_diagnostic.SST2321.severity = error # Environment.Exit or Environment.FailFast is called from library code +dotnet_diagnostic.SST2322.severity = error # A non-private readonly field holds a mutable collection callers can still change +dotnet_diagnostic.SST2323.severity = error # A stateless abstract class with only public abstract members +dotnet_diagnostic.SST2324.severity = error # A member is declared more accessible than its containing type +dotnet_diagnostic.SST2325.severity = error # An async method checks an argument after its first await +dotnet_diagnostic.SST2326.severity = none # Interface value narrowed to a concrete type — a deliberate fast path here +dotnet_diagnostic.SST2327.severity = error # A type tests its own runtime type instead of dispatching virtually +dotnet_diagnostic.SST2328.severity = error # A raw native pointer handle is exposed instead of a SafeHandle +dotnet_diagnostic.SST2329.severity = error # A `[Flags]` enum declares no zero-valued member. Code fix adds `None = 0`. +dotnet_diagnostic.SST2330.severity = error # A [Flags] member literal equal to a combination of other members +dotnet_diagnostic.SST2331.severity = error # An enum leaves member values implicit, so numbering follows declaration order +dotnet_diagnostic.SST2332.severity = error # An auto-property private set is only written during construction +dotnet_diagnostic.SST2333.severity = error # A generic equality contract lacks its non-generic counterpart +dotnet_diagnostic.SST2334.severity = error # A publicly visible type has no `[DebuggerDisplay]` +dotnet_diagnostic.SST2335.severity = error # Parts of a partial type disagree on the `static` modifier +dotnet_diagnostic.SST2336.severity = error # A concrete attribute type declares no [AttributeUsage] +dotnet_diagnostic.SST2337.severity = error # A hierarchy whose derivations are all known is not declared closed +dotnet_diagnostic.SST2338.severity = error # A hand-rolled discriminated type is not declared as a union + +# Correctness +dotnet_diagnostic.SST2400.severity = error # Two arguments name each other's parameters and have been transposed +dotnet_diagnostic.SST2401.severity = error # A catch targets NullReferenceException +dotnet_diagnostic.SST2402.severity = error # An instance constructor assigns a static field of its own type +dotnet_diagnostic.SST2403.severity = error # 'this' escapes from a constructor before the object is fully built +dotnet_diagnostic.SST2404.severity = error # An iterator's argument guard does not run until the first MoveNext +dotnet_diagnostic.SST2405.severity = error # A [DebuggerDisplay] string names a member the type does not have +dotnet_diagnostic.SST2406.severity = error # A loop's stop condition reads only variables the loop never writes +dotnet_diagnostic.SST2407.severity = error # A declared event is never raised +dotnet_diagnostic.SST2408.severity = error # A StringBuilder is filled and never read +dotnet_diagnostic.SST2409.severity = error # A throw constructs a general exception type +dotnet_diagnostic.SST2410.severity = error # A created disposable is never disposed and never leaves the method +dotnet_diagnostic.SST2411.severity = error # A for loop declares and tests a counter it never steps +dotnet_diagnostic.SST2412.severity = error # A for loop update moves the counter away from its stop condition +dotnet_diagnostic.SST2413.severity = error # A for loop condition can never be true on the first pass +dotnet_diagnostic.SST2414.severity = error # Two branches of a conditional share the same implementation +dotnet_diagnostic.SST2415.severity = error # A non-short-circuiting & or | evaluates a right operand that does work +dotnet_diagnostic.SST2416.severity = error # A modulus result on a signed type is compared directly to 1 +dotnet_diagnostic.SST2417.severity = error # A compound assignment operator is transposed (=+, =-, =!) +dotnet_diagnostic.SST2418.severity = error # The result of an immutable value's method is discarded +dotnet_diagnostic.SST2419.severity = error # A set or collection operation is performed against itself +dotnet_diagnostic.SST2420.severity = error # An IndexOf result is tested with > 0, skipping index 0 +dotnet_diagnostic.SST2421.severity = error # A write targets a readonly field of an unconstrained type parameter +dotnet_diagnostic.SST2422.severity = error # A property getter returns a different field than its setter writes +dotnet_diagnostic.SST2423.severity = error # A disposable created in a using statement is returned +dotnet_diagnostic.SST2424.severity = error # An override changes a parameter's default value +dotnet_diagnostic.SST2425.severity = error # An override drops an optional argument on its base call +dotnet_diagnostic.SST2426.severity = error # An override adds or removes params on a parameter +dotnet_diagnostic.SST2427.severity = error # A derived overload widens a parameter and hides the base overload +dotnet_diagnostic.SST2428.severity = error # A static initializer reads a static field declared later +dotnet_diagnostic.SST2429.severity = error # A setter, init, add, or remove accessor never reads value +dotnet_diagnostic.SST2430.severity = error # A serialization callback has the wrong signature +dotnet_diagnostic.SST2431.severity = error # A ToString override can return null +dotnet_diagnostic.SST2432.severity = error # GetType is called on a value that is already a System.Type +dotnet_diagnostic.SST2433.severity = error # A caller-info parameter is not last in the list +dotnet_diagnostic.SST2434.severity = error # An array is assigned through a covariant element type +dotnet_diagnostic.SST2435.severity = error # A non-object base's value Equals used as a reference fast path +dotnet_diagnostic.SST2436.severity = error # An event is raised with a null sender or null args +dotnet_diagnostic.SST2437.severity = error # A generic type inherits from itself recursively +dotnet_diagnostic.SST2438.severity = error # A catch that discards its exception logs at Error or Critical without it +dotnet_diagnostic.SST2439.severity = error # An exception is passed as a log template argument +dotnet_diagnostic.SST2440.severity = error # Log template arguments are transposed +dotnet_diagnostic.SST2441.severity = error # A log template has an empty or non-identifier placeholder +dotnet_diagnostic.SST2442.severity = error # A log template repeats a named placeholder +dotnet_diagnostic.SST2443.severity = error # An ILogger is injected or created with the wrong category type +dotnet_diagnostic.SST2444.severity = error # A regular expression pattern is invalid +dotnet_diagnostic.SST2445.severity = error # A culture-sensitive date or time format without an invariant culture +dotnet_diagnostic.SST2446.severity = error # A Stream.ReadAsync result is discarded through ConfigureAwait or a local +dotnet_diagnostic.SST2447.severity = error # An integer subtraction is compared against literal zero +dotnet_diagnostic.SST2448.severity = error # A combined delegate removed with -= strips only a contiguous run +dotnet_diagnostic.SST2449.severity = error # A lambda or anonymous-method handler is removed with -=, which never matches it +dotnet_diagnostic.SST2450.severity = error # A Debug.Assert condition performs a side effect +dotnet_diagnostic.SST2451.severity = error # Every constructor is private and no member ever creates an instance +dotnet_diagnostic.SST2452.severity = error # A [Pure] method returns void, Task, or ValueTask, so it has no observable result +dotnet_diagnostic.SST2453.severity = error # A ?? whose right operand is a constant null substitutes null for null +dotnet_diagnostic.SST2454.severity = error # The result of an 'as' conversion is dereferenced with no null check +dotnet_diagnostic.SST2455.severity = error # Two enum members hold the same number without saying so +dotnet_diagnostic.SST2456.severity = error # An override or new field-like event gets its own backing delegate field +dotnet_diagnostic.SST2457.severity = error # An integer Sum wrapped in unchecked still throws on overflow +dotnet_diagnostic.SST2458.severity = error # A bitwise operator is applied to an enum not declared [Flags] +dotnet_diagnostic.SST2459.severity = error # [Optional] on a ref or out parameter advertises an optionality no caller can use +dotnet_diagnostic.SST2460.severity = error # [DefaultValue] on a method or record parameter is inert +dotnet_diagnostic.SST2461.severity = error # A [Flags] member sets a bit that no member of the enum declares +dotnet_diagnostic.SST2462.severity = error # A new member is less accessible than the inherited member it hides +dotnet_diagnostic.SST2463.severity = error # A field differs from an inherited accessible field only by case +dotnet_diagnostic.SST2464.severity = error # A mutable class declares value-equality ==, so it is lost as a hash key +dotnet_diagnostic.SST2465.severity = error # A for loop body reassigns the counter or the local its condition tests +dotnet_diagnostic.SST2466.severity = error # A finally clause contains no statements +dotnet_diagnostic.SST2467.severity = error # A params overload is shadowed by a same-arity overload +dotnet_diagnostic.SST2468.severity = error # A classic partial method is declared but never implemented +dotnet_diagnostic.SST2469.severity = error # A write through an extension block's by-value struct receiver is discarded +dotnet_diagnostic.SST2470.severity = error # Two string literals concatenate with no space, fusing keywords +dotnet_diagnostic.SST2472.severity = error # A type is exported for a contract it neither implements nor inherits +dotnet_diagnostic.SST2473.severity = error # A shared export part is constructed with new, bypassing the container +dotnet_diagnostic.SST2474.severity = error # A part-creation-policy attribute is applied to a type with no [Export] +dotnet_diagnostic.SST2475.severity = error # An entity's primary key is typed DateTime or DateTimeOffset +dotnet_diagnostic.SST2479.severity = error # A loop variable captured beyond the iteration reads its final value +dotnet_diagnostic.SST2481.severity = error # A GetHashCode override folds the base identity hash into a value hash +dotnet_diagnostic.SST2484.severity = error # A handle read through DangerousGetHandle is not reference-counted +dotnet_diagnostic.SST2485.severity = error # A NotImplementedException is left in shipped code +dotnet_diagnostic.SST2486.severity = error # An assembly is loaded by path or partial name instead of Assembly.Load +dotnet_diagnostic.SST2487.severity = error # A [ConstructorArgument] does not name a constructor parameter +dotnet_diagnostic.SST2488.severity = error # An exception is logged and rethrown, duplicating the record +dotnet_diagnostic.SST2489.severity = error # A relational comparison is decided by the operand's type rather than its value +dotnet_diagnostic.SST2490.severity = error # Adjacent try statements with identical handling should be merged +dotnet_diagnostic.SST2491.severity = error # A non-async method returns an awaitable from inside using or lock +dotnet_diagnostic.SST2492.severity = error # A null-guard throws on a parameter the signature declares may be null. +dotnet_diagnostic.SST2493.severity = error # == null or != null on an unconstrained generic T +dotnet_diagnostic.SST2494.severity = error # A ?? whose left operand is a constant null +dotnet_diagnostic.SST2495.severity = error # A [Flags] combination includes bits another operand already covers +dotnet_diagnostic.SST2496.severity = error # An explicit Dispose/Close an enclosing using already performs +dotnet_diagnostic.SST2497.severity = error # A member forwards to itself, so calling it recurses until the stack is gone +dotnet_diagnostic.SST2498.severity = error # nameof on a type parameter is the constant "T" +dotnet_diagnostic.SST2499.severity = error # A process exit code is read where the exit status carries the signal + +# Testing +dotnet_diagnostic.SST2500.severity = error # A test method contains no assertion and no expected-exception check +dotnet_diagnostic.SST2501.severity = error # An equality or identity assertion compares an expression with itself +dotnet_diagnostic.SST2502.severity = error # An equality assertion has expected and actual transposed +dotnet_diagnostic.SST2503.severity = error # An equality assertion compares a value against a boolean literal +dotnet_diagnostic.SST2504.severity = error # A test fixture declares and inherits no test method +dotnet_diagnostic.SST2505.severity = error # A test method declares parameters but no data source +dotnet_diagnostic.SST2506.severity = error # A test method calls Thread.Sleep +dotnet_diagnostic.SST2507.severity = error # A test method declares its expected failure with an expected-exception attribute +dotnet_diagnostic.SST2508.severity = error # A fluent assertion is started but never completed +dotnet_diagnostic.SST2509.severity = error # A test method has a shape the runner cannot execute + +# Logging +dotnet_diagnostic.SST2600.severity = error # Output written through legacy Trace instead of a structured logger +dotnet_diagnostic.SST2601.severity = error # A logger field or property does not follow the logger naming convention + +# Frameworks +dotnet_diagnostic.SST2700.severity = error # An MVC route template contains a backslash, so the route is unreachable +dotnet_diagnostic.SST2701.severity = error # A [JSInvokable] method is not public, so interop cannot call it +dotnet_diagnostic.SST2702.severity = error # A [SupplyParameterFromQuery] property cannot bind from the query string +dotnet_diagnostic.SST2703.severity = error # A route constraint disagrees with the matching [Parameter] CLR type +dotnet_diagnostic.SST2704.severity = error # An [ApiController] action declares no HTTP-verb attribute +dotnet_diagnostic.SST2705.severity = error # A bound model member is a non-nullable value type with no required marker +dotnet_diagnostic.SST2706.severity = error # A Windows Forms entry point carries neither [STAThread] nor [MTAThread] +dotnet_diagnostic.SST2707.severity = error # A fire-and-forget Task.Run in a controller captures the request HttpContext +dotnet_diagnostic.SST2708.severity = error # A component subscribes to an event and never unsubscribes +dotnet_diagnostic.SST2709.severity = error # StateHasChanged is called while the component is being disposed +dotnet_diagnostic.SST2710.severity = error # StateHasChanged is called from a timer callback, off the dispatcher +dotnet_diagnostic.SST2711.severity = error # A component lifecycle method is overridden as async void +dotnet_diagnostic.SST2712.severity = error # An [Inject] or [CascadingParameter] property has no setter +dotnet_diagnostic.SST2713.severity = error # A DotNetObjectReference.Create(this) is passed inline and never stored + +################### +# PerformanceSharp Analyzers (PSH) +################### +performancesharp.avoid_linq_on_hot_path = true +# performancesharp.empty_string_style = pattern # PSH1204 (pattern | length | is_null_or_empty; the last two are only offered where the string is provably not null) +# performancesharp.excluded_properties = Items, Keys # PSH1017 (comma-separated; properties allowed to copy on read) +# performancesharp.include_public = false # PSH1411 (set true in an app to seal public types too; a break in a library) +dotnet_diagnostic.PSH1000.severity = error # Anonymous functions without captures should be static +dotnet_diagnostic.PSH1001.severity = error # Avoid allocating zero-length arrays +dotnet_diagnostic.PSH1002.severity = error # Empty finalizers should be removed +dotnet_diagnostic.PSH1003.severity = error # 'in' parameters should use readonly structs +dotnet_diagnostic.PSH1004.severity = error # Constant arrays passed as arguments should be hoisted +dotnet_diagnostic.PSH1005.severity = error # Structs should define equality members to avoid boxing comparisons +dotnet_diagnostic.PSH1006.severity = error # ConcurrentDictionary factories should use the lambda argument +dotnet_diagnostic.PSH1007.severity = error # Pass large readonly structs by 'in' reference +dotnet_diagnostic.PSH1008.severity = error # GC.SuppressFinalize does nothing for sealed finalizer-free types +dotnet_diagnostic.PSH1009.severity = error # Bound variable-length stackalloc with a constant guard +dotnet_diagnostic.PSH1010.severity = error # Clear reference-typed arrays when returning them to the pool +dotnet_diagnostic.PSH1011.severity = error # Pass state to callbacks through the state-taking overload +dotnet_diagnostic.PSH1012.severity = error # Compare type parameter values with EqualityComparer.Default +dotnet_diagnostic.PSH1013.severity = error # Expose constant UTF-8 data as a ReadOnlySpan property +dotnet_diagnostic.PSH1014.severity = error # Declare immutable structs as readonly +dotnet_diagnostic.PSH1015.severity = error # Avoid casting value types through object +dotnet_diagnostic.PSH1016.severity = error # Test enum flags with bitwise operators instead of Enum.HasFlag +dotnet_diagnostic.PSH1017.severity = error # A property allocates a copy of a collection on every read +dotnet_diagnostic.PSH1018.severity = error # A hand-written array is passed to a params parameter +dotnet_diagnostic.PSH1019.severity = error # The range indexer on an array allocates a copy; slice with AsSpan/AsMemory +dotnet_diagnostic.PSH1020.severity = error # Prefer a jagged array over a multidimensional one +dotnet_diagnostic.PSH1021.severity = error # An explicit GC.Collect forces collection the runtime tunes itself +dotnet_diagnostic.PSH1022.severity = error # A parameterless new EventArgs() where EventArgs.Empty would serve +dotnet_diagnostic.PSH1023.severity = error # A local anonymous type allocates where a tuple would not +dotnet_diagnostic.PSH1024.severity = error # A BitArray is built from a temporary array where a span would do +dotnet_diagnostic.PSH1025.severity = error # A union case is a value type and boxes into the union's payload +dotnet_diagnostic.PSH1100.severity = error # Hot-path code should avoid System.Linq.Enumerable calls +dotnet_diagnostic.PSH1101.severity = none # LINQ predicate simplification — production code avoids LINQ on hot paths +dotnet_diagnostic.PSH1102.severity = none # LINQ type-filter simplification — production code avoids LINQ on hot paths +dotnet_diagnostic.PSH1103.severity = error # Prefer the collection's own count over enumerating +dotnet_diagnostic.PSH1104.severity = error # Use TryGetValue instead of ContainsKey followed by an indexer read +dotnet_diagnostic.PSH1105.severity = error # Avoid double lookups on dictionaries and sets +dotnet_diagnostic.PSH1106.severity = error # Index collections directly instead of using LINQ element access +dotnet_diagnostic.PSH1107.severity = error # Filter sequences before sorting them +dotnet_diagnostic.PSH1108.severity = error # Chain secondary sorts with ThenBy +dotnet_diagnostic.PSH1109.severity = error # Merge consecutive Where calls +dotnet_diagnostic.PSH1110.severity = error # Use the collection's own predicate methods over LINQ +dotnet_diagnostic.PSH1111.severity = error # Use Contains for membership tests +dotnet_diagnostic.PSH1112.severity = error # Seed the collection through its constructor +dotnet_diagnostic.PSH1113.severity = error # Sort naturally instead of ordering by the element itself +dotnet_diagnostic.PSH1114.severity = error # Freeze static lookup collections that are never mutated +dotnet_diagnostic.PSH1115.severity = error # Insert-if-absent should probe the dictionary once +dotnet_diagnostic.PSH1116.severity = error # Probe string-keyed collections with a span through GetAlternateLookup +dotnet_diagnostic.PSH1117.severity = error # Ask the collection whether it is empty +dotnet_diagnostic.PSH1118.severity = error # Take the extreme element with Min/Max/MinBy/MaxBy instead of sorting +dotnet_diagnostic.PSH1119.severity = error # Check for elements with Any instead of counting them all +dotnet_diagnostic.PSH1120.severity = error # Do not materialize a sequence with ToList/ToArray just to enumerate it +dotnet_diagnostic.PSH1122.severity = error # Read a sorted set's extreme through its Min/Max property, not the LINQ extension +dotnet_diagnostic.PSH1124.severity = error # Read a linked list's end through its First/Last property, not the LINQ extension +dotnet_diagnostic.PSH1125.severity = error # Do not enumerate the same lazy sequence twice +dotnet_diagnostic.PSH1126.severity = error # Ask whether an async sequence has elements instead of counting them +dotnet_diagnostic.PSH1127.severity = error # Clear an array instead of filling it with its default +dotnet_diagnostic.PSH1200.severity = error # Compare strings without allocating case-converted copies +dotnet_diagnostic.PSH1201.severity = error # Use the char overload for single-character strings +dotnet_diagnostic.PSH1202.severity = error # Append characters as char, not single-character strings +dotnet_diagnostic.PSH1203.severity = error # Let StringBuilder do the formatting work +dotnet_diagnostic.PSH1204.severity = error # Test for empty strings by length +dotnet_diagnostic.PSH1205.severity = error # Remove interpolation that does no work +dotnet_diagnostic.PSH1206.severity = error # Do not build strings by concatenation in loops +dotnet_diagnostic.PSH1207.severity = error # Specify StringComparison for culture-sensitive string operations +dotnet_diagnostic.PSH1208.severity = error # Encode constant strings with u8 literals +dotnet_diagnostic.PSH1209.severity = error # Build transformed strings with string.Create +dotnet_diagnostic.PSH1210.severity = error # Compare UTF-8 bytes without decoding them +dotnet_diagnostic.PSH1211.severity = error # Pass values directly instead of ToString results +dotnet_diagnostic.PSH1212.severity = error # Slice with AsSpan when the call accepts a span +dotnet_diagnostic.PSH1213.severity = error # Probe repeated character sets through SearchValues +dotnet_diagnostic.PSH1214.severity = error # Append the parts of a concatenation separately, not the concatenated whole +dotnet_diagnostic.PSH1215.severity = error # Use string.Concat instead of string.Join with an empty separator +dotnet_diagnostic.PSH1216.severity = error # Use string.Equals instead of comparing string.Compare to zero +dotnet_diagnostic.PSH1217.severity = error # A sequence is copied to an array just to be read straight back +dotnet_diagnostic.PSH1218.severity = error # A substring is allocated only to search it; slice with AsSpan instead +dotnet_diagnostic.PSH1219.severity = error # Ask whether a string is blank without trimming it +dotnet_diagnostic.PSH1220.severity = error # A length argument spells out the run that reaches the end anyway +dotnet_diagnostic.PSH1221.severity = error # An IndexOf compared to 0 scans the whole string to answer a prefix test +dotnet_diagnostic.PSH1222.severity = error # Concatenate slices without materializing them +dotnet_diagnostic.PSH1223.severity = error # A reused composite format string is re-parsed on every call +dotnet_diagnostic.PSH1224.severity = error # Convert bytes to hex in one call, not by building the string twice +dotnet_diagnostic.PSH1225.severity = error # Decode bytes to a string in one call, without a throwaway char[] +dotnet_diagnostic.PSH1226.severity = error # A string's ToCharArray() result is only iterated +dotnet_diagnostic.PSH1227.severity = error # A cheaper equivalent exists, such as string.CompareOrdinal or Debug.Fail +dotnet_diagnostic.PSH1300.severity = error # Use System.Threading.Lock for a dedicated lock object +dotnet_diagnostic.PSH1301.severity = error # Do not wrap a single task in WhenAll or WaitAll +dotnet_diagnostic.PSH1302.severity = error # TaskCompletionSource should run continuations asynchronously +dotnet_diagnostic.PSH1303.severity = error # Do not block an async method with Thread.Sleep +dotnet_diagnostic.PSH1304.severity = error # Use PeriodicTimer instead of pacing a loop with Task.Delay +dotnet_diagnostic.PSH1305.severity = error # Enumerate a ConcurrentDictionary directly, not its Keys/Values snapshots +dotnet_diagnostic.PSH1306.severity = error # Guard one-time execution with an interlocked latch +dotnet_diagnostic.PSH1307.severity = error # Access interlocked fields with Volatile +dotnet_diagnostic.PSH1308.severity = error # Return the completed task instead of Task.FromResult +dotnet_diagnostic.PSH1309.severity = error # Register cancellation callbacks without flowing the execution context +dotnet_diagnostic.PSH1310.severity = error # Dispose IAsyncDisposable resources with await using in async code +dotnet_diagnostic.PSH1311.severity = error # Remove a pass-through async state machine and return the task directly +dotnet_diagnostic.PSH1312.severity = error # Return a completed task instead of null +dotnet_diagnostic.PSH1313.severity = error # A synchronous call where an async overload fits +dotnet_diagnostic.PSH1314.severity = error # Read and write streams through the memory-based overloads +dotnet_diagnostic.PSH1315.severity = error # A blocking wait on an awaitable that may not be done +dotnet_diagnostic.PSH1316.severity = error # A ValueTask is awaited in a loop or awaited after being copied +dotnet_diagnostic.PSH1317.severity = error # A cancellation token is not handed to the overload that accepts one +dotnet_diagnostic.PSH1318.severity = error # Options validation blocks where the async contract exists +dotnet_diagnostic.PSH1400.severity = error # Use the static HashData method for one-shot hashing +dotnet_diagnostic.PSH1401.severity = error # Attribute types should be sealed +dotnet_diagnostic.PSH1402.severity = error # Use const for compile-time constants +dotnet_diagnostic.PSH1403.severity = error # Do not initialize fields to their default value +dotnet_diagnostic.PSH1404.severity = error # Get the assembly from typeof instead of a stack walk +dotnet_diagnostic.PSH1405.severity = error # Use the direct Environment APIs +dotnet_diagnostic.PSH1406.severity = error # Ask Regex for the answer directly +dotnet_diagnostic.PSH1407.severity = error # Query the dictionary, not its Keys view +dotnet_diagnostic.PSH1408.severity = error # Measure elapsed time with Stopwatch timestamps +dotnet_diagnostic.PSH1409.severity = error # Use the built-in throw helpers for argument guards +dotnet_diagnostic.PSH1410.severity = error # Mark trivial forwarders for aggressive inlining +dotnet_diagnostic.PSH1411.severity = error # Seal non-public types nothing derives from so the JIT can devirtualize +dotnet_diagnostic.PSH1412.severity = error # Use Random.Shared instead of allocating a Random +dotnet_diagnostic.PSH1413.severity = error # Read the Unix epoch from the framework, not a hand-built DateTime +dotnet_diagnostic.PSH1414.severity = error # Mark members that do not touch instance state as static +dotnet_diagnostic.PSH1415.severity = error # Hold the concrete type when the concrete type is what you have +dotnet_diagnostic.PSH1416.severity = error # Cache the serializer options instead of building them per call +dotnet_diagnostic.PSH1417.severity = error # Do not compute an expensive argument for an assertion +dotnet_diagnostic.PSH1418.severity = error # An HttpClient is constructed on every call +dotnet_diagnostic.PSH1419.severity = error # A time zone is resolved with a platform-specific id +dotnet_diagnostic.PSH1420.severity = error # A shareable client is rebuilt on every Azure Functions invocation +dotnet_diagnostic.PSH1421.severity = error # A static Regex method is called from inside a loop body + +# ASP.NET Core — inert here, enabled so the set stays complete +dotnet_diagnostic.PSH1500.severity = error # A minimal API handler returns Results instead of TypedResults, boxing the result +dotnet_diagnostic.PSH1501.severity = error # Middleware uses the legacy nested-delegate Use overload +dotnet_diagnostic.PSH1502.severity = error # A route handler returns a sequence serialized on the request thread +dotnet_diagnostic.PSH1503.severity = error # Response caching is used where server-side output caching applies +dotnet_diagnostic.PSH1505.severity = error # Exceptions handled in an MVC filter instead of an IExceptionHandler +dotnet_diagnostic.PSH1506.severity = error # The HTTP request or response body is read or written synchronously + +# Blazor +dotnet_diagnostic.PSH1600.severity = error # A delegate captured per iteration in a render loop reallocates every render +dotnet_diagnostic.PSH1601.severity = error # A JavaScript-interop call is issued once per loop iteration +dotnet_diagnostic.PSH1602.severity = error # StateHasChanged is called unconditionally in OnAfterRender +dotnet_diagnostic.PSH1603.severity = error # A non-delegate allocation is a component parameter in a render loop + +################### +# SecuritySharp Analyzers (SES) +################### +# Every rule is error; these report local shapes only, so the taint-flow CA rules stay on. +# securitysharp.SES1003.iterations = 100000 # minimum accepted PBKDF2 iteration count +# securitysharp.SES1403.maxdepth = 64 # highest accepted System.Text.Json MaxDepth + +# Cryptography +dotnet_diagnostic.SES1001.severity = error # AEAD encryption must not use a constant or reused nonce +dotnet_diagnostic.SES1002.severity = error # Password-based key derivation must not use a constant or predictable salt +dotnet_diagnostic.SES1003.severity = error # Password-based key derivation must use a sufficient iteration count +dotnet_diagnostic.SES1004.severity = error # A secret must not be produced from Guid.NewGuid() +dotnet_diagnostic.SES1005.severity = error # Compare secret values in constant time +dotnet_diagnostic.SES1006.severity = error # A Data Protection key ring is persisted without ProtectKeysWith +dotnet_diagnostic.SES1007.severity = error # A cryptographic primitive is implemented by hand +dotnet_diagnostic.SES1008.severity = error # An XML signature is verified with the no-key CheckSignature overload +dotnet_diagnostic.SES1009.severity = error # A password is stored without a slow, salted key-derivation function +dotnet_diagnostic.SES1010.severity = error # AES key wrapping is implemented by hand + +# Transport +dotnet_diagnostic.SES1102.severity = error # Do not accept any server certificate +dotnet_diagnostic.SES1104.severity = error # Certificate-chain validation must not be deliberately weakened +dotnet_diagnostic.SES1105.severity = error # Bearer or OpenID Connect metadata is retrieved over plain HTTP +dotnet_diagnostic.SES1106.severity = error # Do not send HttpClient requests to a cleartext http URL +dotnet_diagnostic.SES1107.severity = error # A SQL connection string weakens transport security +dotnet_diagnostic.SES1108.severity = error # A certificate validation callback unconditionally returns true + +# Secrets +dotnet_diagnostic.SES1201.severity = error # Do not hard-code secrets in source +dotnet_diagnostic.SES1202.severity = error # Do not hard-code a credential value +dotnet_diagnostic.SES1203.severity = error # A connection string names a user but supplies an empty or missing password + +# Injection +dotnet_diagnostic.SES1301.severity = error # Do not build a process command line from non-constant string parts +dotnet_diagnostic.SES1302.severity = error # A shell-executed process must not use a non-constant FileName +dotnet_diagnostic.SES1303.severity = error # Regular-expression pattern must not be built from non-constant data +dotnet_diagnostic.SES1304.severity = error # An archive entry name must not build a write path without a containment check +dotnet_diagnostic.SES1305.severity = error # Do not build a storage path from an uploaded file name +dotnet_diagnostic.SES1306.severity = error # Do not compile or execute non-constant C# via the scripting API +dotnet_diagnostic.SES1307.severity = error # Path.GetTempFileName creates a predictable, world-readable temporary file +dotnet_diagnostic.SES1308.severity = error # A file or directory is created group- or world-writable +dotnet_diagnostic.SES1309.severity = error # An XSLT stylesheet is loaded with embedded script enabled +dotnet_diagnostic.SES1310.severity = error # A directory bind is performed without authenticating + +# Serialization +dotnet_diagnostic.SES1401.severity = error # A type resolved from non-constant data must not be instantiated or deserialized +dotnet_diagnostic.SES1402.severity = error # Do not load an assembly from raw bytes or a non-constant location +dotnet_diagnostic.SES1403.severity = error # JSON deserialization depth limit must stay within a safe ceiling +dotnet_diagnostic.SES1404.severity = error # A type is instantiated by name from a non-constant Activator typeName +dotnet_diagnostic.SES1405.severity = error # MessagePack typeless deserialization reconstructs the named type +dotnet_diagnostic.SES1406.severity = error # Reflection must not reach non-public members via BindingFlags.NonPublic + +# Web hardening +dotnet_diagnostic.SES1501.severity = error # A CORS policy must not allow credentials together with any origin +dotnet_diagnostic.SES1502.severity = error # A CORS origin predicate must not unconditionally allow every origin +dotnet_diagnostic.SES1503.severity = error # JWT signature verification must not be disabled on TokenValidationParameters +dotnet_diagnostic.SES1504.severity = error # A cookie with SameSite=None must be marked Secure +dotnet_diagnostic.SES1505.severity = error # The request body size limit must not be removed +dotnet_diagnostic.SES1506.severity = error # The developer exception page must be guarded by a development-environment check +dotnet_diagnostic.SES1507.severity = error # AllowAnonymous and Authorize on the same declaration conflict +dotnet_diagnostic.SES1508.severity = error # A validation method must not fail open by returning success from a catch +dotnet_diagnostic.SES1509.severity = error # A backtracking-prone regex runs without a match timeout +dotnet_diagnostic.SES1510.severity = error # A controller redirects to a non-constant URL, allowing an open redirect +dotnet_diagnostic.SES1511.severity = error # The forwarded-headers trust boundary is cleared +dotnet_diagnostic.SES1512.severity = error # Sensitive diagnostics are enabled without an environment guard +dotnet_diagnostic.SES1513.severity = error # An AuthorizeAsync result is discarded, so the guarded operation runs regardless +dotnet_diagnostic.SES1514.severity = error # OpenID Connect protections (PKCE, state, nonce) are disabled +dotnet_diagnostic.SES1515.severity = error # A Content-Security-Policy value disables its own protection + +# AI trust boundaries +dotnet_diagnostic.SES1601.severity = error # An LLM system prompt must be a constant, trusted template +dotnet_diagnostic.SES1602.severity = error # Do not route AI model output into a process, file, or raw SQL sink +dotnet_diagnostic.SES1603.severity = error # A read-only AI tool calls a state-changing API +dotnet_diagnostic.SES1604.severity = error # Prompt-template input encoding must not be disabled +dotnet_diagnostic.SES1605.severity = error # AI instrumentation must not enable sensitive-data capture +dotnet_diagnostic.SES1606.severity = error # Do not fetch model weights over cleartext HTTP + +# Web UI trust boundaries +dotnet_diagnostic.SES1701.severity = error # Raw HTML is rendered from a non-constant value — an XSS risk +dotnet_diagnostic.SES1702.severity = error # A JavaScript-interop call targets a script-evaluation primitive +dotnet_diagnostic.SES1703.severity = error # [Authorize] on a non-routable component enforces nothing +dotnet_diagnostic.SES1704.severity = error # HttpContext is used in an interactively-rendered component +dotnet_diagnostic.SES1705.severity = error # NavigateTo is called with an unverified target — open-redirect risk +dotnet_diagnostic.SES1706.severity = error # An uploaded file is read with an unbounded or client-chosen size limit +dotnet_diagnostic.SES1707.severity = error # A secret-shaped literal sits in code that downloads to the browser +dotnet_diagnostic.SES1708.severity = error # CircuitOptions.DetailedErrors ships exception detail to clients +dotnet_diagnostic.SES1709.severity = error # SerializeAllClaims exposes every claim to the client +dotnet_diagnostic.SES1710.severity = error # Antiforgery validation is disabled on a form + +################### +# Public API surface tracking (PAS) +################### +dotnet_diagnostic.PAS0001.severity = error # A public symbol is missing from the baseline for this target framework +dotnet_diagnostic.PAS0002.severity = error # A baseline entry no longer exists in the public API +dotnet_diagnostic.PAS0003.severity = error # A public symbol differs from its baseline entry +dotnet_diagnostic.PAS0004.severity = error # No public API baseline for this target framework +dotnet_diagnostic.PAS0005.severity = error # The public API baseline could not be read + +################### +# External scanner inspections +################### +dotnet_diagnostic.S100.severity = none # Methods and properties should be named in PascalCase — covered by SST1300 +dotnet_diagnostic.S101.severity = none # Types should be named in PascalCase — covered by SST1300 +dotnet_diagnostic.S103.severity = none # Lines should not be too long — covered by SST1521 +dotnet_diagnostic.S104.severity = none # Files should not have too many lines of code — covered by SST1522 +dotnet_diagnostic.S105.severity = none # Tabulation characters should not be used — covered by SST1027 +dotnet_diagnostic.S106.severity = none # Covered by SST1449 (canonical) +dotnet_diagnostic.S107.severity = none # Methods should not have too many parameters — covered by SST1472 +dotnet_diagnostic.S108.severity = none # Nested blocks of code should not be left empty — covered by SST1439 +dotnet_diagnostic.S109.severity = none # Magic numbers should not be used — covered by SST1471 +dotnet_diagnostic.S110.severity = none # Inheritance tree of classes should not be too deep — covered by SST1446 +dotnet_diagnostic.S112.severity = none # General or reserved exceptions should never be thrown — covered by SST2409 +dotnet_diagnostic.S113.severity = none # Files should end with a newline +dotnet_diagnostic.S121.severity = none # Control structures should use braces — replaced by SST1503 +dotnet_diagnostic.S122.severity = none # Statements should be on separate lines — covered by SST1107 +dotnet_diagnostic.S125.severity = none # Sections of code should not be commented out — covered by SST1148 +dotnet_diagnostic.S126.severity = none # "if ... else if" constructs should end with "else" clauses +dotnet_diagnostic.S127.severity = none # "for" loop stop conditions should be invariant — covered by SST2465 +dotnet_diagnostic.S131.severity = none # "switch/Select" statements should contain a "default/Case Else" clauses +dotnet_diagnostic.S134.severity = none # Control flow statements should not be nested too deeply +dotnet_diagnostic.S138.severity = none # Functions should not have too many lines of code — covered by SST1523 +dotnet_diagnostic.S818.severity = none # Literal suffixes should be upper case — covered by SST2244 +dotnet_diagnostic.S881.severity = none # ++ or -- mixed into a larger expression — covered by SST2015 +dotnet_diagnostic.S907.severity = none # "goto" statement should not be used — covered by SST2014 +dotnet_diagnostic.S927.severity = none # Parameter names should match the base declaration — covered by CA1725 +dotnet_diagnostic.S1006.severity = none # Method overrides should not change parameter defaults — covered by SST2424 +dotnet_diagnostic.S1048.severity = none # Finalizers should not throw exceptions — covered by SST1485 +dotnet_diagnostic.S1066.severity = none # Mergeable "if" statements should be combined — covered by SST2013 +dotnet_diagnostic.S1067.severity = none # Expressions should not be too complex +dotnet_diagnostic.S1075.severity = none # Hardcoded URI — canonical SourceLink hosts are the point +dotnet_diagnostic.S1104.severity = none # Fields should not have public accessibility - DUPLICATE CA1051 +dotnet_diagnostic.S1109.severity = none # A close brace should start its line — covered by SST1500 +dotnet_diagnostic.S1110.severity = none # Redundant pairs of parentheses should be removed — covered by SST1459 +dotnet_diagnostic.S1116.severity = none # Empty statements should be removed - DUPLICATE SA1106 +dotnet_diagnostic.S1117.severity = none # Locals shadowing fields or properties — covered by SST1484 +dotnet_diagnostic.S1118.severity = none # Utility classes should not have public constructors - DUPLICATE CA1052 +dotnet_diagnostic.S1121.severity = none # Assignments should not be made from within sub-expressions — covered by SST1187 +dotnet_diagnostic.S1123.severity = none # "Obsolete" attributes should include explanations — covered by SST2308 +dotnet_diagnostic.S1125.severity = none # Boolean literals should not be redundant — covered by SST1182 +dotnet_diagnostic.S1128.severity = none # Covered by SST1445 (canonical) +dotnet_diagnostic.S1133.severity = none # Deprecated code should be removed — covered by SST2310 +dotnet_diagnostic.S1134.severity = none # Track uses of "FIXME" tags -> off: TODO comment tracker; not enforced here +dotnet_diagnostic.S1135.severity = none # Track uses of "TODO" tags -> off: FIXME comment tracker; not enforced here +dotnet_diagnostic.S1144.severity = none # Covered by SST1440 (canonical) +dotnet_diagnostic.S1147.severity = none # Exit methods should not be called — covered by SST2321 +dotnet_diagnostic.S1151.severity = none # switch case clauses with too many lines — covered by SST1524 +dotnet_diagnostic.S1155.severity = none # "Any()" should be used to test for emptiness — covered by PSH1119 +dotnet_diagnostic.S1163.severity = none # Exceptions should not be thrown in finally blocks -> replaced by CA2219 +dotnet_diagnostic.S1168.severity = none # Empty collections should be returned over null — covered by SST2306 +dotnet_diagnostic.S1172.severity = none # Unused method parameters should be removed — covered by SST1461 +dotnet_diagnostic.S1185.severity = none # Overrides that only call the base — covered by RCS1132 +dotnet_diagnostic.S1186.severity = none # Methods should not be empty — covered by SST1438 +dotnet_diagnostic.S1192.severity = none # String literals should not be duplicated — covered by SST1486 +dotnet_diagnostic.S1199.severity = none # Nested code blocks should not be used — covered by SST1138 +dotnet_diagnostic.S1200.severity = none # Classes should not be coupled to too many other classes +dotnet_diagnostic.S1206.severity = none # Equals and GetHashCode overridden in pairs — covered by CA2218 +dotnet_diagnostic.S1210.severity = none # IComparable types should override Equals and operators — CA1036 +dotnet_diagnostic.S1215.severity = none # "GC.Collect" should not be called — covered by PSH1021 +dotnet_diagnostic.S1226.severity = none # Parameter and foreach initial values should not be ignored +dotnet_diagnostic.S1227.severity = none # break statements should not be used except for switch cases +dotnet_diagnostic.S1244.severity = none # Floating point numbers should not be tested for equality — covered by SST1473 +dotnet_diagnostic.S1264.severity = none # A "while" loop should be used instead of a "for" loop — covered by SST2245 +dotnet_diagnostic.S1301.severity = none # "switch" statements should have at least 3 "case" clauses +dotnet_diagnostic.S1309.severity = none # Track uses of in-source issue suppressions +dotnet_diagnostic.S1312.severity = none # Logger fields should be "private static readonly" +dotnet_diagnostic.S1313.severity = none # Hardcoded IP addresses — too noisy to enforce +dotnet_diagnostic.S1449.severity = none # Culture should be specified for "string" operations — covered by PSH1207 +dotnet_diagnostic.S1450.severity = none # Private fields used only as locals — covered by SST1422 +dotnet_diagnostic.S1451.severity = none # Track lack of copyright and license headers +dotnet_diagnostic.S1479.severity = none # "switch" statements with many "case" clauses — covered by SST1423 +dotnet_diagnostic.S1481.severity = none # Unused local variables should be removed — covered by SST1497 +dotnet_diagnostic.S1541.severity = none # Methods and properties should not be too complex - covered by SST1442 +dotnet_diagnostic.S1607.severity = none # Tests should not be ignored -> off: ignored-test tracker; not enforced here +dotnet_diagnostic.S1643.severity = none # Covered by PSH1206 (canonical) +dotnet_diagnostic.S1656.severity = none # Variables should not be self-assigned — covered by SST1189 +dotnet_diagnostic.S1659.severity = none # Multiple variables should not be declared on the same line — covered by SST1132 +dotnet_diagnostic.S1694.severity = none # Abstract classes need abstract and concrete methods — SST2323 +dotnet_diagnostic.S1696.severity = none # NullReferenceException should not be caught — covered by SST2401 +dotnet_diagnostic.S1698.severity = none # "==" should not be used when "Equals" is overridden — covered by SST1495 +dotnet_diagnostic.S1699.severity = none # Constructors should only call non-overridable methods — covered by SST1483 +dotnet_diagnostic.S1751.severity = none # Loops with at most one iteration should be refactored - covered by SST1444 +dotnet_diagnostic.S1764.severity = none # Identical expressions on both sides of an operator — covered by SST1474 +dotnet_diagnostic.S1821.severity = none # "switch" statements should not be nested -> replaced by SST2252 +dotnet_diagnostic.S1848.severity = none # Objects created and dropped immediately — covered by SST1480 +dotnet_diagnostic.S1854.severity = none # Unused assignments should be removed - DUPLICATE IDE0059 +dotnet_diagnostic.S1858.severity = none # "ToString()" calls should not be redundant — covered by PSH1211 +dotnet_diagnostic.S1862.severity = none # if/else if statements with the same condition — covered by SST1475 +dotnet_diagnostic.S1871.severity = none # Two branches with the same implementation — covered by SST2414 +dotnet_diagnostic.S1905.severity = none # Redundant casts should not be used - DUPLICATE IDE0004 — covered by SST1175 +dotnet_diagnostic.S1939.severity = none # Inheritance list should not be redundant — covered by SST1490 and SST1177 +dotnet_diagnostic.S1940.severity = none # Boolean checks should not be inverted — covered by SST1172 +dotnet_diagnostic.S1944.severity = none # Invalid casts should be avoided -> replaced by compiler CS0030 +dotnet_diagnostic.S1994.severity = none # A for loop increment should modify the counter — covered by SST2411 +dotnet_diagnostic.S2068.severity = none # Credentials should not be hard-coded -> replaced by SES1201 +dotnet_diagnostic.S2077.severity = none # Formatting SQL queries is security-sensitive -> replaced by CA2100 +dotnet_diagnostic.S2092.severity = none # Cookies without the secure flag — replaced by CA5382 +dotnet_diagnostic.S2094.severity = none # Classes should not be empty — covered by SST1436 +dotnet_diagnostic.S2114.severity = none # Collections passed to their own methods — covered by SST2419 +dotnet_diagnostic.S2115.severity = none # A secure database password should be used — replaced by SES1203 +dotnet_diagnostic.S2123.severity = none # Values should not be uselessly incremented -> replaced by SST2222 +dotnet_diagnostic.S2139.severity = none # Exceptions logged and rethrown — replaced by SST2488 +dotnet_diagnostic.S2148.severity = none # Underscores should be used to make large numbers readable — covered by SST1191 +dotnet_diagnostic.S2156.severity = none # "sealed" classes should not have "protected" members — covered by SST1427 +dotnet_diagnostic.S2166.severity = none # Exception-named classes should extend Exception — covered by CA1710 +dotnet_diagnostic.S2178.severity = none # Short-circuit logic should be used in boolean contexts — covered by SST2415 +dotnet_diagnostic.S2183.severity = none # Shift counts beyond the operand width — covered by SST1478 +dotnet_diagnostic.S2184.severity = none # Integer division assigned to a floating point value — SST1477 +dotnet_diagnostic.S2187.severity = none # Test classes should contain at least one test case — covered by SST2504 +dotnet_diagnostic.S2190.severity = none # Loops and recursions should not be infinite +dotnet_diagnostic.S2197.severity = none # Modulus results should not be checked for direct equality — covered by SST2416 +dotnet_diagnostic.S2198.severity = none # Unnecessary mathematical comparisons should not be made -> replaced by SST2489 +dotnet_diagnostic.S2201.severity = none # Side-effect-free return values ignored — covered by SST2418 +dotnet_diagnostic.S2219.severity = none # Runtime type checking should be simplified — covered by SST2007 +dotnet_diagnostic.S2221.severity = none # "Exception" should not be caught +dotnet_diagnostic.S2223.severity = none # Non-constant static fields should not be visible - DUPLICATE CA2211 +dotnet_diagnostic.S2225.severity = none # "ToString()" method should not return null — covered by SST2431 +dotnet_diagnostic.S2234.severity = none # Arguments passed in parameter order — replaced by SST2400 +dotnet_diagnostic.S2245.severity = none # Pseudorandom number generators are sensitive — covered by CA5394 +dotnet_diagnostic.S2251.severity = none # A for loop counter moving the wrong way — covered by SST2412 +dotnet_diagnostic.S2252.severity = none # For-loop conditions should be true at least once — covered by SST2413 +dotnet_diagnostic.S2257.severity = none # Non-standard cryptographic algorithms — replaced by SES1007 +dotnet_diagnostic.S2275.severity = none # Composite format strings — covered by CA2241 +dotnet_diagnostic.S2290.severity = none # Field-like events should not be virtual -> replaced by SST2456 +dotnet_diagnostic.S2291.severity = none # Overflow checking disabled for Enumerable.Sum — covered by SST2457 +dotnet_diagnostic.S2292.severity = none # Trivial properties should be auto-implemented — covered by SST1420 +dotnet_diagnostic.S2302.severity = none # "nameof" should be used — covered by SST1415 +dotnet_diagnostic.S2306.severity = none # async and await as identifiers — replaced by the compiler +dotnet_diagnostic.S2325.severity = none # Members not touching instance data should be static — CA1822 +dotnet_diagnostic.S2326.severity = none # Covered by SST1452 (canonical) +dotnet_diagnostic.S2327.severity = none # try statements with identical catch or finally — replaced by SST2490 +dotnet_diagnostic.S2328.severity = none # "GetHashCode" should not reference mutable fields — covered by SST1482 +dotnet_diagnostic.S2330.severity = none # Array covariance should not be used — covered by SST2434 +dotnet_diagnostic.S2333.severity = none # Redundant modifiers should not be used — covered by SST1419/SST1491 +dotnet_diagnostic.S2339.severity = none # Public constant members should not be used — covered by SST2311 +dotnet_diagnostic.S2342.severity = none # Enumeration types should comply with a naming convention — covered by SST1319 +dotnet_diagnostic.S2344.severity = none # Enum names should not end in Flags or Enum — covered by CA1711 +dotnet_diagnostic.S2345.severity = none # Flags enums should initialize all members — covered by SST2303 +dotnet_diagnostic.S2346.severity = none # Flags enumerations zero-value members should be named "None" - DUPLICATE CA1008 +dotnet_diagnostic.S2357.severity = none # Fields should be private — covered by SST1401; exposed fields are suppressed +dotnet_diagnostic.S2360.severity = none # Optional parameters should not be used — conflicts with SST2433 +dotnet_diagnostic.S2365.severity = none # Properties should not make collection or array copies — covered by PSH1017 +dotnet_diagnostic.S2368.severity = none # Public multidimensional array parameters — jagged is our layout +dotnet_diagnostic.S2372.severity = none # Exceptions should not be thrown from property getters — covered by SST1485 +dotnet_diagnostic.S2376.severity = none # Write-only properties should not be used — covered by SST1421 +dotnet_diagnostic.S2386.severity = none # Mutable fields should not be "public static" — covered by SST1499 +dotnet_diagnostic.S2387.severity = none # Child class fields should not shadow parent class fields — covered by SST1484 +dotnet_diagnostic.S2436.severity = none # Too many generic parameters — needed for the projector overload +dotnet_diagnostic.S2437.severity = none # Unnecessary bit operations should not be performed — covered by SST1481 +dotnet_diagnostic.S2445.severity = none # Blocks should be synchronized on read-only fields — covered by SST1904 +dotnet_diagnostic.S2479.severity = none # Control characters in string literals — covered by SST1192 +dotnet_diagnostic.S2486.severity = none # Generic exceptions should not be ignored — covered by SST1429 +dotnet_diagnostic.S2551.severity = none # Shared resources should not be used for locking — covered by SST1902 +dotnet_diagnostic.S2589.severity = none # Null checks are judged against nullability annotations that differ across the Roslyn slots +dotnet_diagnostic.S2612.severity = none # World-accessible file permissions — replaced by SES1308 +dotnet_diagnostic.S2629.severity = none # Logging templates should be constant -> replaced by CA2254 +dotnet_diagnostic.S2674.severity = none # The length returned from a stream read should be checked — covered by SST2446 +dotnet_diagnostic.S2681.severity = none # Multiline blocks should be enclosed in curly braces — covered by SST1503 +dotnet_diagnostic.S2688.severity = none # "NaN" should not be used in comparisons — covered by SST1473 +dotnet_diagnostic.S2692.severity = none # "IndexOf" checks should not be for positive numbers — covered by SST2420 +dotnet_diagnostic.S2696.severity = none # Instance members should not write to "static" fields -> replaced by SST2402 +dotnet_diagnostic.S2699.severity = none # Tests should include assertions -> replaced by SST2500 +dotnet_diagnostic.S2701.severity = none # Literal boolean values should not be used in assertions — covered by SST2503 +dotnet_diagnostic.S2737.severity = none # "catch" clauses should do more than rethrow — covered by SST1470 +dotnet_diagnostic.S2743.severity = none # Static fields in generic types — covered by SST1431 +dotnet_diagnostic.S2755.severity = none # XML parsers should not be vulnerable to XXE attacks -> replaced by CA3075 +dotnet_diagnostic.S2757.severity = none # Non-existent operators like "=+" should not be used — covered by SST2417 +dotnet_diagnostic.S2760.severity = none # Sequential tests should not check the same condition — covered by SST1475 +dotnet_diagnostic.S2761.severity = none # Doubled prefix operators "!!" and "~~" should not be used — covered by SST1190 +dotnet_diagnostic.S2857.severity = none # SQL keywords should be delimited by whitespace — covered by SST2470 +dotnet_diagnostic.S2925.severity = none # "Thread.Sleep" should not be used in tests — covered by SST2506 +dotnet_diagnostic.S2930.severity = none # "IDisposables" should be disposed — covered by SST2410 +dotnet_diagnostic.S2931.severity = none # Types with IDisposable members should implement IDisposable — SST2315 +dotnet_diagnostic.S2933.severity = none # Constructor-only assigned fields should be readonly — IDE0044 +dotnet_diagnostic.S2934.severity = none # Assignment to a readonly field of a type parameter — SST2421 +dotnet_diagnostic.S2952.severity = none # Dispose members from the type's own Dispose — covered by SST2315 +dotnet_diagnostic.S2953.severity = none # Methods named Dispose should implement IDisposable — SST2316 +dotnet_diagnostic.S2955.severity = none # Unconstrained generic compared to null — replaced by the compiler +dotnet_diagnostic.S2970.severity = none # Assertions should be complete -> replaced by SST2508 +dotnet_diagnostic.S2971.severity = none # LINQ expressions should be simplified — covered by PSH1101/PSH1102 +dotnet_diagnostic.S2995.severity = none # ReferenceEquals on value types — covered by CA2013 +dotnet_diagnostic.S2996.severity = none # "ThreadStatic" fields should not be initialized -> replaced by CA2019 +dotnet_diagnostic.S2997.severity = none # IDisposables created in a using should not be returned — SST2423 +dotnet_diagnostic.S3005.severity = none # "ThreadStatic" should not be used on non-static fields -> replaced by CA2259 +dotnet_diagnostic.S3010.severity = none # Static fields should not be updated in constructors — covered by SST2402 +dotnet_diagnostic.S3011.severity = none # Reflection used to increase accessibility — replaced by SES1406 +dotnet_diagnostic.S3052.severity = none # Covered by PSH1403 (canonical) +dotnet_diagnostic.S3059.severity = none # Members more visible than their containing type +dotnet_diagnostic.S3060.severity = none # "is" should not be used with "this" -> replaced by SST2327 +dotnet_diagnostic.S3063.severity = none # "StringBuilder" data should be used — covered by SST2408 +dotnet_diagnostic.S3168.severity = none # "async" methods should not return "void" — covered by SST1905 +dotnet_diagnostic.S3169.severity = none # Multiple "OrderBy" calls should not be used — covered by PSH1108 +dotnet_diagnostic.S3172.severity = none # Delegates should not be subtracted — covered by SST2448 +dotnet_diagnostic.S3215.severity = none # Interfaces cast to concrete types — unenforced, as with SST2326 +dotnet_diagnostic.S3216.severity = none # "ConfigureAwait(false)" should be used -> replaced by CA2007 +dotnet_diagnostic.S3217.severity = none # Explicit conversions in foreach loops — covered by SST2225 +dotnet_diagnostic.S3218.severity = none # Inner members shadowing outer members — covered by SST1484 +dotnet_diagnostic.S3220.severity = none # Ambiguous resolution to params overloads — covered by SST2467 +dotnet_diagnostic.S3234.severity = none # Covered by PSH1008 (canonical) +dotnet_diagnostic.S3235.severity = none # Redundant parentheses should not be used — covered by SST1459 +dotnet_diagnostic.S3236.severity = none # Covered by SST1448 (canonical) +dotnet_diagnostic.S3237.severity = none # "value" contextual keyword should be used — covered by SST2429 +dotnet_diagnostic.S3240.severity = none # The simplest possible condition syntax should be used - duplicate of SST1198 +dotnet_diagnostic.S3241.severity = none # Return values never used — needs whole-program analysis +dotnet_diagnostic.S3242.severity = none # Method parameters should be declared with base types +dotnet_diagnostic.S3244.severity = none # Anonymous delegates used to unsubscribe from events — SST2449 +dotnet_diagnostic.S3246.severity = none # Generic parameters should be co/contravariant — low precision +dotnet_diagnostic.S3247.severity = none # Duplicate casts should not be made — covered by SST1175 +dotnet_diagnostic.S3249.severity = none # Covered by SST1447 (canonical) +dotnet_diagnostic.S3251.severity = none # Implementations should be provided for "partial" methods — covered by SST2468 +dotnet_diagnostic.S3253.severity = none # Redundant constructor and destructor declarations — SST1433 +dotnet_diagnostic.S3254.severity = none # Default parameter values should not be passed as arguments — covered by SST1494 +dotnet_diagnostic.S3256.severity = none # "string.IsNullOrEmpty" should be used — covered by PSH1204 (style configurable) +dotnet_diagnostic.S3257.severity = none # Declarations should be as concise as possible — replaced by SST2202 +dotnet_diagnostic.S3260.severity = none # Non-derived private classes should be sealed — covered by PSH1411 +dotnet_diagnostic.S3261.severity = none # Namespaces should not be empty — covered by SST1435 +dotnet_diagnostic.S3262.severity = none # "params" should be used on overrides — covered by SST2426 +dotnet_diagnostic.S3263.severity = none # Static fields ordered by initialization need — covered by SST2428 +dotnet_diagnostic.S3264.severity = none # Events should be invoked — covered by SST2407 +dotnet_diagnostic.S3265.severity = none # Non-flags enums should not be used in bitwise operations — covered by SST2458 +dotnet_diagnostic.S3267.severity = none # Asks for LINQ; production code here is deliberately LINQ-free +dotnet_diagnostic.S3330.severity = none # Cookies without the HttpOnly flag — replaced by CA5383 +dotnet_diagnostic.S3343.severity = none # Caller-info parameters should come last — covered by SST2433 +dotnet_diagnostic.S3346.severity = none # Debug.Assert expressions with side effects — covered by SST2450 +dotnet_diagnostic.S3353.severity = none # Unchanged variables should be marked as "const" — covered by PSH1402 +dotnet_diagnostic.S3358.severity = none # Ternary operators should not be nested — covered by SST1147 +dotnet_diagnostic.S3363.severity = none # Date and time should not be used as a type for primary keys — covered by SST2475 +dotnet_diagnostic.S3366.severity = none # "this" should not be exposed from constructors — covered by SST2403 +dotnet_diagnostic.S3376.severity = none # Attribute and Exception type name suffixes — covered by CA1710 +dotnet_diagnostic.S3397.severity = none # base.Equals used for reference equality — covered by SST2435 +dotnet_diagnostic.S3398.severity = none # Private methods used only by inner classes — covered by SST1498 +dotnet_diagnostic.S3400.severity = none # Methods should not return constants — covered by SST1493 +dotnet_diagnostic.S3415.severity = none # Assertion arguments should be passed in the correct order — covered by SST2502 +dotnet_diagnostic.S3416.severity = none # Loggers should be named for their enclosing types — covered by SST2443 +dotnet_diagnostic.S3427.severity = none # Overlapping default parameter overloads — covered by SST2319 +dotnet_diagnostic.S3431.severity = none # "[ExpectedException]" should not be used — covered by SST2507 +dotnet_diagnostic.S3433.severity = none # Test method signatures should be correct -> replaced by SST2509 +dotnet_diagnostic.S3440.severity = none # Variables checked against the value being assigned — SST1492 +dotnet_diagnostic.S3441.severity = none # Redundant property names in anonymous types — covered by SST1173 +dotnet_diagnostic.S3442.severity = none # "abstract" classes should not have "public" constructors — covered by SST1428 +dotnet_diagnostic.S3443.severity = none # Type should not be examined on "System.Type" instances — covered by SST2432 +dotnet_diagnostic.S3444.severity = none # Interfaces inheriting colliding members — covered by SST2320 +dotnet_diagnostic.S3445.severity = none # Exceptions should not be explicitly rethrown — covered by SST1430 +dotnet_diagnostic.S3447.severity = none # [Optional] on ref or out parameters — covered by SST2459 +dotnet_diagnostic.S3449.severity = none # Right operands of shift operators should be integers -> replaced by SST1478 +dotnet_diagnostic.S3450.severity = none # [DefaultParameterValue] needs [Optional] — replaced by obsolete +dotnet_diagnostic.S3451.severity = none # [DefaultValue] where [DefaultParameterValue] is meant — SST2460 +dotnet_diagnostic.S3453.severity = none # Classes should not have only "private" constructors — covered by SST2451 +dotnet_diagnostic.S3456.severity = none # Redundant ToCharArray and ToArray calls — covered by PSH1217 +dotnet_diagnostic.S3457.severity = none # Composite format strings should be used correctly — covered by SST1454 +dotnet_diagnostic.S3458.severity = none # Empty case clauses falling through to default — covered by SST1466 +dotnet_diagnostic.S3459.severity = none # Unassigned members should be removed — the compiler reports CS0649 +dotnet_diagnostic.S3464.severity = none # Type inheritance should not be recursive — covered by SST2437 +dotnet_diagnostic.S3466.severity = none # Optional parameters should be passed to "base" calls — covered by SST2425 +dotnet_diagnostic.S3532.severity = none # Empty "default" clauses should be removed — covered by SST1179 +dotnet_diagnostic.S3597.severity = none # ServiceContract and OperationContract together — replaced by obsolete +dotnet_diagnostic.S3598.severity = none # One-way OperationContract should return void — replaced by obsolete +dotnet_diagnostic.S3600.severity = none # "params" should not be introduced on overrides — covered by SST2426 +dotnet_diagnostic.S3603.severity = none # Methods with "Pure" attribute should return a value — covered by SST2452 +dotnet_diagnostic.S3604.severity = none # Member initializer values should not be redundant — covered by PSH1403 +dotnet_diagnostic.S3610.severity = none # Nullable type comparison should not be redundant -> replaced by compiler CS0472 +dotnet_diagnostic.S3626.severity = none # Jump statements should not be redundant — covered by SST1174 +dotnet_diagnostic.S3717.severity = none # Track use of "NotImplementedException" -> replaced by SST2485 +dotnet_diagnostic.S3776.severity = none # Cognitive Complexity of methods should not be too high - covered by SST1443 +dotnet_diagnostic.S3869.severity = none # "SafeHandle.DangerousGetHandle" should not be called -> replaced by SST2484 +dotnet_diagnostic.S3871.severity = none # Exception types should be "public" -> replaced by CA1064 +dotnet_diagnostic.S3872.severity = none # Parameter names duplicating the method name — replaced by SST1320 +dotnet_diagnostic.S3874.severity = none # "out" and "ref" parameters — repo idiom is TryX(..., out T value) +dotnet_diagnostic.S3875.severity = none # "operator==" should not be overloaded on reference types -> replaced by SST2464 +dotnet_diagnostic.S3876.severity = none # Strings or integral types should be used for indexers -> replaced by CA1043 +dotnet_diagnostic.S3877.severity = none # Exceptions should not be thrown from unexpected methods — covered by SST1485 +dotnet_diagnostic.S3878.severity = none # Arrays should not be created for params parameters — covered by PSH1018 +dotnet_diagnostic.S3880.severity = none # Finalizers should not be empty — covered by PSH1002 +dotnet_diagnostic.S3881.severity = none # "IDisposable" should be implemented correctly — covered by SST2300 +dotnet_diagnostic.S3884.severity = none # CoSetProxyBlanket and CoInitializeSecurity — replaced by obsolete +dotnet_diagnostic.S3885.severity = none # "Assembly.Load" should be used -> replaced by SST2486 +dotnet_diagnostic.S3887.severity = none # Mutable, non-private fields should not be "readonly" — covered by SST2322 +dotnet_diagnostic.S3889.severity = none # Thread.Resume and Thread.Suspend — replaced by obsolete markers +dotnet_diagnostic.S3897.severity = none # Types with Equals(T) should implement IEquatable — CA1067 +dotnet_diagnostic.S3898.severity = none # Covered by PSH1005 (canonical) +dotnet_diagnostic.S3902.severity = none # Covered by PSH1404 (canonical) +dotnet_diagnostic.S3903.severity = none # Types should be defined in named namespaces — covered by SST2312 +dotnet_diagnostic.S3904.severity = none # Assemblies should have version information — the SDK supplies it +dotnet_diagnostic.S3906.severity = none # Event Handlers should have the correct signature — covered by SST2304 +dotnet_diagnostic.S3908.severity = none # Generic event handlers should be used -> replaced by SST2304 +dotnet_diagnostic.S3909.severity = none # Collections should implement the generic interface -> replaced by CA1010 +dotnet_diagnostic.S3923.severity = none # All branches with the same implementation — covered by SST1476 +dotnet_diagnostic.S3925.severity = none # ISerializable should be implemented correctly — legacy path is obsolete +dotnet_diagnostic.S3926.severity = none # Deserialization methods for OptionalField — replaced by obsolete +dotnet_diagnostic.S3927.severity = none # Serialization event handlers — covered by SST2430 +dotnet_diagnostic.S3928.severity = none # ArgumentException parameter names should exist — covered by CA2208 +dotnet_diagnostic.S3937.severity = none # Number patterns should be regular — covered by SST1119 +dotnet_diagnostic.S3956.severity = none # "Generic.List" instances should not be part of public APIs +dotnet_diagnostic.S3962.severity = none # Covered by PSH1402 (canonical) +dotnet_diagnostic.S3963.severity = none # "static" fields should be initialized inline - DUPLICATE CA1810 +dotnet_diagnostic.S3967.severity = none # Multidimensional arrays should not be used - DUPLICATE CA1814 +dotnet_diagnostic.S3971.severity = none # GC.SuppressFinalize should not be called — conflicts with PSH1008 +dotnet_diagnostic.S3972.severity = none # Conditionals should start on new lines — covered by SST1146 +dotnet_diagnostic.S3973.severity = none # A conditional single line should be indented — replaced by SST1503 +dotnet_diagnostic.S3981.severity = none # Collection size and array length comparisons — covered by SST1479 +dotnet_diagnostic.S3984.severity = none # Exceptions should not be created without being thrown — covered by SST1480 +dotnet_diagnostic.S3990.severity = none # Assemblies should be marked as CLS compliant -> replaced by CA1014 +dotnet_diagnostic.S3992.severity = none # Assemblies should explicitly specify COM visibility -> replaced by CA1017 +dotnet_diagnostic.S3993.severity = none # Custom attributes need AttributeUsage — replaced by CA1018 +dotnet_diagnostic.S3994.severity = none # URI Parameters should not be strings +dotnet_diagnostic.S3995.severity = none # URI return values should not be strings +dotnet_diagnostic.S3996.severity = none # URI properties should not be strings +dotnet_diagnostic.S3997.severity = none # String URI overloads should call Uri overloads — replaced by CA1054 +dotnet_diagnostic.S3998.severity = none # Threads should not lock on objects with weak identity -> replaced by SST1902 +dotnet_diagnostic.S4000.severity = none # Pointers to unmanaged memory should not be visible -> replaced by SST2328 +dotnet_diagnostic.S4002.severity = none # Disposable types should declare finalizers — covered by SST2317 +dotnet_diagnostic.S4004.severity = none # Collection properties should be readonly — covered by SST2305 +dotnet_diagnostic.S4005.severity = none # "System.Uri" arguments should be used instead of strings +dotnet_diagnostic.S4015.severity = none # Inherited member visibility should not be decreased — covered by SST2462 +dotnet_diagnostic.S4016.severity = none # Enumeration members should not be named "Reserved" -> replaced by CA1700 +dotnet_diagnostic.S4017.severity = none # Method signatures should not contain nested generic types +dotnet_diagnostic.S4018.severity = none # All type parameters should appear in the parameter list — SST2307 +dotnet_diagnostic.S4019.severity = none # Base class methods should not be hidden — covered by SST2427 +dotnet_diagnostic.S4022.severity = none # Enumerations should have "Int32" storage — covered by SST2313 +dotnet_diagnostic.S4023.severity = none # Interfaces should not be empty — covered by SST1437 +dotnet_diagnostic.S4025.severity = none # Child fields differing from parent only by case — covered by SST2463 +dotnet_diagnostic.S4026.severity = none # Assemblies need NeutralResourcesLanguage — replaced by CA1824 +dotnet_diagnostic.S4027.severity = none # Exceptions should provide standard constructors — covered by SST1488 +dotnet_diagnostic.S4035.severity = none # Classes implementing "IEquatable" should be sealed — covered by SST2301 +dotnet_diagnostic.S4036.severity = none # PATH-relative process spawn — benchmark only, trusted env +dotnet_diagnostic.S4039.severity = none # Interface methods should be callable by derived types - DUPLICATE CA1033 +dotnet_diagnostic.S4040.severity = none # Strings should be normalized to uppercase - DUPLICATE CA1308 +dotnet_diagnostic.S4041.severity = none # Type names should not match namespaces - DUPLICATE CA1724 +dotnet_diagnostic.S4047.severity = none # Generics should be used when appropriate — fuzzy, not enforced +dotnet_diagnostic.S4049.severity = none # Properties should be preferred - DUPLICATE CA1024 +dotnet_diagnostic.S4050.severity = none # Operators should be overloaded consistently — covered by SST2302 +dotnet_diagnostic.S4052.severity = none # Types should not extend outdated base types -> replaced by obsolete +dotnet_diagnostic.S4055.severity = none # Literals should not be passed as localized parameters +dotnet_diagnostic.S4056.severity = none # CultureInfo or IFormatProvider overloads — covered by CA1305 +dotnet_diagnostic.S4057.severity = none # Locales should be set for data types -> replaced by obsolete +dotnet_diagnostic.S4058.severity = none # Covered by PSH1207 (canonical) +dotnet_diagnostic.S4059.severity = none # Property names should not match get methods - DUPLICATE CA1721 +dotnet_diagnostic.S4060.severity = none # Non-abstract attributes should be sealed - DUPLICATE CA1813 +dotnet_diagnostic.S4061.severity = none # params should be used instead of varargs — replaced by obsolete +dotnet_diagnostic.S4069.severity = none # Operator overloads should have named alternatives - DUPLICATE CA2225 +dotnet_diagnostic.S4070.severity = none # Non-flags enums should not be marked with "FlagsAttribute" — covered by SST2303 +dotnet_diagnostic.S4136.severity = none # Method overloads should be grouped together — covered by SST1218 +dotnet_diagnostic.S4143.severity = none # Collection elements should not be replaced unconditionally — covered by SST1487 +dotnet_diagnostic.S4144.severity = none # Methods should not have identical implementations — covered by SST2318 +dotnet_diagnostic.S4159.severity = none # Classes should implement their "ExportAttribute" interfaces — covered by SST2472 +dotnet_diagnostic.S4200.severity = none # Native methods should be wrapped -> replaced by CA1401 +dotnet_diagnostic.S4201.severity = none # Null checks combined with is checks — covered by SST2018 +dotnet_diagnostic.S4210.severity = none # Windows Forms entry points need STAThread — replaced by SST2706 +dotnet_diagnostic.S4211.severity = none # Conflicting transparency annotations — replaced by obsolete +dotnet_diagnostic.S4212.severity = none # Serialization constructors should be secured — replaced by obsolete +dotnet_diagnostic.S4214.severity = none # "P/Invoke" methods should not be visible - DUPLICATE CA1401 +dotnet_diagnostic.S4220.severity = none # Events should have proper arguments — covered by SST2436 +dotnet_diagnostic.S4225.severity = none # Extension methods should not extend "object" — covered by SST1706 +dotnet_diagnostic.S4226.severity = none # Extensions should be in separate namespaces +dotnet_diagnostic.S4260.severity = none # ConstructorArgument parameters must exist — replaced by SST2487 +dotnet_diagnostic.S4261.severity = none # Methods named for their synchronicity — no Async suffix here +dotnet_diagnostic.S4275.severity = none # Getters and setters should access the expected fields — covered by SST2422 +dotnet_diagnostic.S4277.severity = none # "Shared" parts should not be created with "new" — covered by SST2473 +dotnet_diagnostic.S4423.severity = none # Weak SSL/TLS protocols should not be used -> replaced by CA5397/CA5398 +dotnet_diagnostic.S4426.severity = none # Cryptographic keys should be robust -> replaced by CA5385 (RSA) / CA5384 (DSA) +dotnet_diagnostic.S4428.severity = none # PartCreationPolicy needs Export — covered by SST2474 +dotnet_diagnostic.S4433.severity = none # LDAP connections should be authenticated -> replaced by SES1310 +dotnet_diagnostic.S4456.severity = none # Parameter validation in yielding methods should be wrapped — covered by SST2404 +dotnet_diagnostic.S4457.severity = none # Parameter validation in async methods — covered by SST2325 +dotnet_diagnostic.S4462.severity = none # Calls to "async" methods should not be blocking - covered by PSH1315 +dotnet_diagnostic.S4487.severity = none # Unread "private" fields should be removed +dotnet_diagnostic.S4502.severity = none # Disabling CSRF protections — replaced by the in-box antiforgery analyzer +dotnet_diagnostic.S4507.severity = none # Debug features in production — partly covered by SES1506 +dotnet_diagnostic.S4524.severity = none # "default" clauses should be first or last — covered by SST1219 +dotnet_diagnostic.S4545.severity = none # DebuggerDisplay should name real members — covered by SST2405 +dotnet_diagnostic.S4581.severity = none # "new Guid()" should not be used — covered by SST2012 +dotnet_diagnostic.S4583.severity = none # BeginInvoke should be paired with EndInvoke — replaced by obsolete +dotnet_diagnostic.S4586.severity = none # Non-async "Task/Task" methods should not return null — covered by PSH1312 +dotnet_diagnostic.S4635.severity = none # Start index should be used instead of calling Substring — covered by PSH1218 +dotnet_diagnostic.S4663.severity = none # Covered by SST1120 (canonical) +dotnet_diagnostic.S4790.severity = none # Using weak hashing algorithms is security-sensitive -> replaced by CA5350/CA5351 +dotnet_diagnostic.S4792.severity = none # Configuring loggers is security-sensitive — not enforced here +dotnet_diagnostic.S4830.severity = none # Server certificates should be verified — replaced by SES1102/SES1108 +dotnet_diagnostic.S5034.severity = none # "ValueTask" should be consumed correctly — covered by PSH1316 +dotnet_diagnostic.S5042.severity = none # Unbounded archive expansion — needs taint analysis, out of scope +dotnet_diagnostic.S5122.severity = none # Permissive CORS policy — replaced by SES1501 +dotnet_diagnostic.S5332.severity = none # Using clear-text protocols is security-sensitive -> replaced by SES1106 +dotnet_diagnostic.S5344.severity = none # Passwords stored with a fast hash — replaced by SES1009 +dotnet_diagnostic.S5443.severity = none # Using publicly writable directories is security-sensitive -> replaced by SES1308 +dotnet_diagnostic.S5445.severity = none # Insecure temporary file creation — replaced by SES1307 +dotnet_diagnostic.S5542.severity = none # Encryption mode and padding scheme — replaced by CA5358 +dotnet_diagnostic.S5547.severity = none # Cipher algorithms should be robust -> replaced by CA5351 +dotnet_diagnostic.S5659.severity = none # JWT signed with strong cipher algorithms — replaced by SES1503 +dotnet_diagnostic.S5693.severity = none # Excessive request content length — replaced by SES1505 +dotnet_diagnostic.S5753.severity = none # Disabling ASP.NET request validation — replaced by obsolete +dotnet_diagnostic.S5766.severity = none # Serializable objects without validation — obsolete path, unused +dotnet_diagnostic.S5856.severity = none # Regular expressions should be syntactically valid — covered by SST2444 +dotnet_diagnostic.S6354.severity = none # Use a testable date/time provider — covered by SST2010 +dotnet_diagnostic.S6377.severity = none # XML signatures should be validated securely -> replaced by SES1008 +dotnet_diagnostic.S6418.severity = none # Secrets should not be hard-coded — covered by SES1201 +dotnet_diagnostic.S6419.severity = none # Azure Functions should be stateless — not used in this library +dotnet_diagnostic.S6420.severity = none # Clients recreated per Azure Function call — covered by PSH1418 +dotnet_diagnostic.S6421.severity = none # Azure Functions structured error handling — not used in this library +dotnet_diagnostic.S6422.severity = none # Blocking async calls in Azure Functions — covered by PSH1315 +dotnet_diagnostic.S6423.severity = none # Azure Functions should log all failures — not used in this library +dotnet_diagnostic.S6424.severity = none # Durable entity interface restrictions — not used in this library +dotnet_diagnostic.S6444.severity = none # Regular expressions without a timeout — replaced by SES1509 +dotnet_diagnostic.S6507.severity = none # Blocks should not be synchronized on local variables — covered by SST1903 +dotnet_diagnostic.S6513.severity = none # ExcludeFromCodeCoverage justification — not available on net462 +dotnet_diagnostic.S6561.severity = none # DateTime.Now used for timing — covered by PSH1408 +dotnet_diagnostic.S6562.severity = none # Covered by SST1451 (canonical) +dotnet_diagnostic.S6563.severity = none # Use UTC when recording DateTime instants — covered by SST2011 +dotnet_diagnostic.S6566.severity = none # Use "DateTimeOffset" instead of "DateTime" — covered by SST2016 +dotnet_diagnostic.S6575.severity = none # FindSystemTimeZoneById conversions — replaced by PSH1419 +dotnet_diagnostic.S6580.severity = none # Use a format provider when parsing date and time - DUPLICATE CA1305 +dotnet_diagnostic.S6585.severity = none # Hardcoded date and time formats — covered by SST2445 +dotnet_diagnostic.S6588.severity = none # DateTime.UnixEpoch should be used — covered by PSH1413 +dotnet_diagnostic.S6594.severity = none # Covered by PSH1406 (canonical) +dotnet_diagnostic.S6602.severity = none # Covered by PSH1110 (canonical) +dotnet_diagnostic.S6603.severity = none # Covered by PSH1110 (canonical) +dotnet_diagnostic.S6605.severity = none # Covered by PSH1110 (canonical) +dotnet_diagnostic.S6607.severity = none # The collection should be filtered before sorting — covered by PSH1107 +dotnet_diagnostic.S6608.severity = none # Covered by PSH1106 (canonical) +dotnet_diagnostic.S6609.severity = none # Set Min/Max properties over the extensions — covered by PSH1122 +dotnet_diagnostic.S6610.severity = none # Covered by PSH1201 (canonical) +dotnet_diagnostic.S6612.severity = none # ConcurrentDictionary lambda parameter over captures — PSH1006 +dotnet_diagnostic.S6613.severity = none # LinkedList First/Last properties over the extensions — PSH1124 +dotnet_diagnostic.S6617.severity = none # Covered by PSH1111 (canonical) +dotnet_diagnostic.S6618.severity = none # string.Create over FormattableString — covered by PSH1209 +dotnet_diagnostic.S6640.severity = none # Unsafe code blocks — not enforced here +dotnet_diagnostic.S6664.severity = none # Too many logging calls in a block — fuzzy metric, not enforced +dotnet_diagnostic.S6667.severity = none # Catch-clause logging should pass the exception — covered by SST2438 +dotnet_diagnostic.S6668.severity = none # Logging arguments should be passed to the correct parameter — covered by SST2439 +dotnet_diagnostic.S6669.severity = none # Logger field naming convention — replaced by SST2601 +dotnet_diagnostic.S6670.severity = none # "Trace.Write" and "Trace.WriteLine" should not be used — covered by SST2600 +dotnet_diagnostic.S6672.severity = none # Generic logger injection should match enclosing type — covered by SST2443 +dotnet_diagnostic.S6673.severity = none # Log template placeholders in the right order — covered by SST2440 +dotnet_diagnostic.S6674.severity = none # Log message template should be syntactically correct — covered by SST2441 +dotnet_diagnostic.S6675.severity = none # Trace.WriteLineIf with TraceSwitch levels — niche, not enforced +dotnet_diagnostic.S6677.severity = none # Message template placeholders should be unique — covered by SST2442 +dotnet_diagnostic.S6678.severity = none # Use PascalCase for named placeholders -> replaced by CA1727 +dotnet_diagnostic.S6797.severity = none # Blazor query parameter type should be supported -> replaced by SST2702 +dotnet_diagnostic.S6798.severity = none # [JSInvokable] only on public methods — replaced by SST2701 +dotnet_diagnostic.S6800.severity = none # Component parameter must match the route constraint — SST2703 +dotnet_diagnostic.S6802.severity = none # Lambdas in Blazor markup loops — replaced by PSH1600 +dotnet_diagnostic.S6803.severity = none # SupplyParameterFromQuery outside routable components — no Blazor here +dotnet_diagnostic.S6930.severity = none # Backslash should be avoided in route templates -> replaced by SST2700 +dotnet_diagnostic.S6931.severity = none # Controller routes starting with / — no controllers in this library +dotnet_diagnostic.S6932.severity = none # Model binding over raw request data — no controllers in this library +dotnet_diagnostic.S6934.severity = none # Route attribute on the controller — no controllers in this library +dotnet_diagnostic.S6960.severity = none # Controllers with mixed responsibilities — no controllers here +dotnet_diagnostic.S6961.severity = none # API controllers should derive from ControllerBase — none here +dotnet_diagnostic.S6962.severity = none # You should pool HTTP connections with HttpClientFactory — covered by PSH1418 +dotnet_diagnostic.S6964.severity = none # Value-type inputs should be nullable or required — replaced by SST2705 +dotnet_diagnostic.S6965.severity = none # REST actions need an HTTP verb attribute — replaced by SST2704 +dotnet_diagnostic.S6966.severity = none # Awaitable method should be used — covered by PSH1313 +dotnet_diagnostic.S6967.severity = none # ModelState.IsValid in controller actions — no controllers here +dotnet_diagnostic.S6968.severity = none # Actions should declare ProducesResponseType — no controllers here +dotnet_diagnostic.S7039.severity = none # Content Security Policies should be restrictive -> replaced by SES1515 +dotnet_diagnostic.S8367.severity = none # Identifiers conflicting with the field keyword — the compiler reports it +dotnet_diagnostic.S8368.severity = none # Identifiers conflicting with the extension keyword — the compiler reports it +dotnet_diagnostic.S8380.severity = none # Return types named partial need @ — the compiler reports it +dotnet_diagnostic.S8381.severity = none # scoped should be escaped as an identifier — replaced by the compiler +dotnet_diagnostic.S8949.severity = none # A CancellationToken should be forwarded to the overload that takes one — covered by CA2016 +dotnet_diagnostic.S8969.severity = none # Null-forgiving operators are not portable across the Roslyn slots +dotnet_diagnostic.S8970.severity = none # Redundant null-forgiving operator — covered by SST2209 + +################### +# Experimental compiler APIs (RSEXPERIMENTAL) +################### +dotnet_diagnostic.RSEXPERIMENTAL006.severity = none # We target newer language features ################### # Trimming Analyzer Warnings (IL2001 - IL2123) @@ -932,6 +2390,158 @@ dotnet_diagnostic.IL3055.severity = error # MakeGenericType on non-supported typ dotnet_diagnostic.IL3056.severity = error # MakeGenericMethod on non-supported method requires dynamic code dotnet_diagnostic.IL3057.severity = error # Reflection access to generic parameter requires dynamic code +############################################# +# JetBrains ReSharper / Rider Inspections +############################################# +# Mirrors the CA / SST / PSH choices above for Rider and ReSharper users. Only +# inspections with a clear mapping to our Roslyn analyzer rules are listed; +# every other ReSharper inspection keeps its default severity. The goal is to +# avoid Rider double-reporting things the Roslyn analyzers already catch and +# to keep IDE severities in sync with CI-enforced severities. + +################### +# ReSharper - Layout / Formatting (covered by the spacing and layout rules) +################### +resharper_redundant_linebreak_highlighting = none # covered by SA layout rules +resharper_missing_linebreak_highlighting = none # covered by SA layout rules +resharper_bad_empty_braces_line_breaks_highlighting = none # covered by SST1500 +resharper_missing_indent_highlighting = none # covered by editorconfig indent_size +resharper_missing_blank_lines_highlighting = none # covered by SST1516 / SST1517 +resharper_wrong_indent_size_highlighting = none # covered by editorconfig indent_size +resharper_bad_indent_highlighting = none # covered by editorconfig indent_size +resharper_bad_expression_braces_line_breaks_highlighting = none # covered by SA layout rules +resharper_multiple_spaces_highlighting = none # covered by SST1025 +resharper_bad_expression_braces_indent_highlighting = none # covered by SA layout rules +resharper_bad_control_braces_indent_highlighting = none # covered by SA layout rules +resharper_bad_preprocessor_indent_highlighting = none # covered by SA layout rules +resharper_redundant_blank_lines_highlighting = none # covered by SST1516 / SST1507 +resharper_multiple_statements_on_one_line_highlighting = none # covered by SST1119 / SST1503 +resharper_bad_braces_spaces_highlighting = none # covered by SST1012 / SST1013 +resharper_outdent_is_off_prev_level_highlighting = none # editorconfig indentation +resharper_bad_symbol_spaces_highlighting = none # covered by SA spacing rules +resharper_bad_colon_spaces_highlighting = none # covered by SST1024 +resharper_bad_semicolon_spaces_highlighting = none # covered by SST1002 +resharper_bad_square_brackets_spaces_highlighting = none # covered by SST1010 / SST1011 +resharper_bad_parens_spaces_highlighting = none # covered by SST1008 / SST1009 + +################### +# ReSharper - 'this' qualifier (SST1117 owns the qualification style) +################### +resharper_redundant_this_qualifier_highlighting = none # we don't follow the this. prefix style +resharper_arrange_this_qualifier_highlighting = none # we don't follow the this. prefix style +resharper_arrange_default_access_modifier_highlighting = none # SST1400 requires explicit access modifiers — don't suggest removing them +resharper_redundant_default_access_modifier_highlighting = none # SST1400 requires explicit access modifiers — don't suggest removing them +resharper_redundant_access_modifier_highlighting = none # access modifiers are deliberate and SST1400 requires them +resharper_arrange_type_member_modifiers_highlighting = none # SST1206 handles modifier ordering; don't duplicate +resharper_redundant_empty_switch_section_highlighting = none # an empty section is how an intentionally ignored case reads + +################### +# ReSharper - Redundancies / cleanup +################### +resharper_redundant_using_directive_highlighting = error # IDE0005 may not fire at compile time reliably — keep Rider nagging +resharper_redundant_qualifier_highlighting = error # IDE0001 may not fire at compile time reliably — keep Rider nagging +resharper_redundant_name_qualifier_highlighting = error # IDE0001 may not fire at compile time reliably — keep Rider nagging +resharper_redundant_base_qualifier_highlighting = none # IDE0009 is disabled (SST1117 owns qualification) — don't nag in Rider either +resharper_redundant_cast_highlighting = error # a cast that changes nothing is dead weight +resharper_redundant_explicit_array_creation_highlighting = error # let the element type be inferred +resharper_redundant_empty_object_creation_argument_list_highlighting = none # an explicit () reads consistently next to argument-carrying calls +resharper_redundant_lambda_signature_parentheses_highlighting = error # IDE0063 may not fire at compile time reliably — keep Rider nagging +resharper_redundant_default_member_initializer_highlighting = error # the field already starts at its default +resharper_redundant_field_initializer_highlighting = error # the field already starts at its default +resharper_redundant_overriding_member_highlighting = error # an override that only calls base adds nothing +resharper_redundant_verbatim_string_prefix_highlighting = error # no escape in the literal needs the @ +resharper_redundant_string_interpolation_highlighting = error # the interpolation has no holes +resharper_redundant_to_string_call_highlighting = error # the value is already a string in this position + +################### +# ReSharper - Naming (matches SA/CA naming rules) +################### +resharper_inconsistent_naming_highlighting = error # partially handled by SST1300 family but IDE1006 isn't enabled; keep ReSharper active + +################### +# ReSharper - Unused code (matches CA1801 / CA1823 / IDE0051-0052) +################### +resharper_unused_parameter_local_highlighting = none # handled by CA1801 (private/internal surface) +resharper_unused_parameter_global_highlighting = none # public-API parameters can be unused for compat +resharper_unused_member_local_highlighting = error # IDE0051 may not fire at compile time reliably — keep Rider nagging +resharper_unused_member_global_highlighting = suggestion # public-API members may be intentionally exposed +resharper_unused_field_local_highlighting = none # handled by CA1823 +resharper_unused_field_global_highlighting = none # public-API fields may be intentionally exposed +resharper_unused_type_local_highlighting = error # IDE0052 may not fire at compile time reliably — keep Rider nagging +resharper_unused_type_global_highlighting = suggestion # public-API types may be intentionally exposed +resharper_unused_variable_highlighting = none # handled by CS0219 +resharper_unused_auto_property_accessor_local_highlighting = none # data-class setters are intentional even when unused locally +resharper_unused_auto_property_accessor_global_highlighting = none # public auto-properties may be intentionally exposed + +################### +# ReSharper - Code quality (matches the CA and PSH semantic analyzers) +################### +resharper_class_never_instantiated_local_highlighting = none # handled by CA1812 +resharper_class_never_instantiated_global_highlighting = suggestion # public types may be instantiated externally +resharper_class_cannot_be_instantiated_highlighting = none # handled by CA1052 +resharper_class_can_be_sealed_local_highlighting = none # handled by CA1852 (private/internal surface) +resharper_class_can_be_sealed_global_highlighting = none # public types stay open for inheritance +resharper_use_nameof_expression_highlighting = none # covered by CA1507 +resharper_possible_null_reference_exception_highlighting = none # handled bynullability analyzer +resharper_possible_invalid_operation_exception_highlighting = none # handled bynullability analyzer +resharper_possible_multiple_enumeration_highlighting = none # handled by CA1851 +resharper_possible_mistaken_argument_null_check_highlighting = none # handled by CA1062 +resharper_convert_to_constant_local_highlighting = none # a local that never changes is fine as a local +resharper_convert_to_static_class_highlighting = none # handled by CA1052 +resharper_convert_to_auto_property_highlighting = none # an explicit backing field is often deliberate +resharper_convert_to_auto_property_when_possible_highlighting = none # an explicit backing field is often deliberate +resharper_convert_to_auto_property_with_private_setter_highlighting = none # an explicit backing field is often deliberate +resharper_auto_property_can_be_made_get_only_local_highlighting = none # a settable property is often part of the intended contract +resharper_auto_property_can_be_made_get_only_global_highlighting = suggestion # public setters kept for API consumers +resharper_member_can_be_made_static_local_highlighting = none # handled by CA1822 (private/internal surface) +resharper_member_can_be_made_static_global_highlighting = none # public members kept virtual for inheritance +resharper_member_can_be_private_local_highlighting = none # access modifiers are deliberate — don't suggest tightening +resharper_method_has_async_overload_highlighting = none # sync call sites are intentional (e.g. test setup, disposal, sample code) +resharper_member_can_be_private_global_highlighting = none # access modifiers are deliberate — don't suggest tightening +resharper_field_can_be_made_read_only_local_highlighting = error # a field never reassigned after construction should say so +resharper_field_can_be_made_read_only_global_highlighting = error # a field never reassigned after construction should say so +resharper_merge_into_pattern_highlighting = none # the unmerged form is often the clearer read +resharper_merge_conditional_expression_highlighting = none # the unmerged form is often the clearer read +resharper_merge_sequential_checks_highlighting = none # the unmerged form is often the clearer read +resharper_simplify_conditional_ternary_expression_highlighting = none # the unmerged form is often the clearer read +resharper_simplify_linq_expression_highlighting = error # a query that collapses to one call should be written that way +resharper_string_compare_to_is_culture_specific_highlighting = none # handled by CA1310 +resharper_string_ends_with_is_culture_specific_highlighting = none # handled by CA1310 +resharper_string_index_of_is_culture_specific_1_highlighting = none # handled by CA1310 +resharper_string_index_of_is_culture_specific_2_highlighting = none # handled by CA1310 +resharper_string_index_of_is_culture_specific_3_highlighting = none # handled by CA1310 +resharper_string_last_index_of_is_culture_specific_1_highlighting = none # handled by CA1310 +resharper_string_last_index_of_is_culture_specific_2_highlighting = none # handled by CA1310 +resharper_string_last_index_of_is_culture_specific_3_highlighting = none # handled by CA1310 +resharper_string_starts_with_is_culture_specific_highlighting = none # handled by CA1310 +resharper_specify_a_culture_in_string_conversion_explicitly_highlighting = none # handled by CA1304 + +################### +# ReSharper - Control flow / nesting +################### +resharper_invert_if_highlighting = suggestion # inverting to an early return usually reads better, but not always +resharper_tail_recursive_call_highlighting = suggestion + +################### +# ReSharper - Documentation (covered by the SST1600 family) +################### +resharper_missing_xml_doc_highlighting = none # covered by SST1600 family +resharper_missing_xml_doc_global_highlighting = none # covered by SST1600 family +resharper_invalid_xml_doc_comment_highlighting = none # handled by SST1612 / SST1613 + +################### +# ReSharper - Typo / spelling (not enforced) +################### +resharper_comment_typo_highlighting = none # typo checks are out of scope +resharper_string_literal_typo_highlighting = none # typo checks are out of scope +resharper_identifier_typo_highlighting = none # typo checks are out of scope +resharper_markup_text_typo_highlighting = none # typo checks are out of scope + +############################################# +# Other Settings +############################################# +vsspell_dictionary_languages = en-US + ############################################# # C++ Files ############################################# @@ -961,9 +2571,4 @@ indent_size = 2 end_of_line = lf [*.{cmd, bat}] -end_of_line = crlf - -############################################# -# Other Settings -############################################# -vsspell_dictionary_languages = en-US +end_of_line = lf diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..2ffd36aa --- /dev/null +++ b/.gitattributes @@ -0,0 +1,55 @@ +# Auto-detect text files and normalise line endings to LF in the repository. +# Working trees check out LF on every platform (auto, no forced CRLF). +* text=auto eol=lf + +# Source code +*.cs text diff=csharp +*.xaml text +*.c text +*.h text +*.cpp text +*.hpp text + +# Projects and build +*.slnx text +*.sln text +*.csproj text +*.vcxproj text +*.props text +*.targets text +*.msbuild text +*.config text +*.json text +*.xml text +*.yml text +*.yaml text +*.runsettings text +*.editorconfig text + +# Documentation and scripts +*.md text +*.markdown text +*.txt text +*.tt text +*.sh text +*.ps1 text +*.cmd text +*.bat text + +# Binary files that should not be normalized or diffed +*.png binary +*.jpg binary +*.bmp binary +*.gif binary +*.ico binary +*.rc binary + +*.pfx binary +*.snk binary +*.dll binary +*.exe binary +*.lib binary +*.exp binary +*.pdb binary +*.sdf binary +*.7z binary diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 6adbfa66..8a7048d8 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -16,7 +16,7 @@ permissions: jobs: build: - uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@main + uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@b285525c4af878b0fe3fbb00d9f2ae862e402395 # main with: productNamespacePrefix: Splat.DependencyInjection secrets: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b7873c62..83a34862 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -16,7 +16,7 @@ permissions: jobs: codeql: - uses: reactiveui/actions-common/.github/workflows/workflow-common-codeql.yml@main + uses: reactiveui/actions-common/.github/workflows/workflow-common-codeql.yml@b285525c4af878b0fe3fbb00d9f2ae862e402395 # main with: srcFolder: src solutionFile: Splat.DI.SourceGenerator.slnx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 458b74a4..3941c027 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ permissions: jobs: release: - uses: reactiveui/actions-common/.github/workflows/workflow-common-release.yml@main + uses: reactiveui/actions-common/.github/workflows/workflow-common-release.yml@b285525c4af878b0fe3fbb00d9f2ae862e402395 # main with: solutionFile: Splat.DI.SourceGenerator.slnx minverMinimumMajorMinor: '2.3' @@ -45,12 +45,12 @@ jobs: id-token: write steps: - name: Download signed packages - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: signed-nuget - name: Setup .NET - uses: actions/setup-dotnet@v5 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 - name: NuGet login (OIDC trusted publishing) id: nuget-login @@ -67,7 +67,7 @@ jobs: create-release: needs: [release, publish-nuget] - uses: reactiveui/actions-common/.github/workflows/workflow-common-create-release.yml@main + uses: reactiveui/actions-common/.github/workflows/workflow-common-create-release.yml@b285525c4af878b0fe3fbb00d9f2ae862e402395 # main with: version: ${{ needs.release.outputs.semver2 }} tag: ${{ needs.release.outputs.tag }} diff --git a/CLAUDE.md b/CLAUDE.md index 2b0be4bf..4cc55956 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,7 +29,7 @@ dotnet restore Splat.DI.SourceGenerator.slnx # Build the solution dotnet build Splat.DI.SourceGenerator.slnx -c Release -# Build with warnings as errors (includes StyleCop violations) +# Build with warnings as errors (includes StyleSharp/PerformanceSharp/SecuritySharp violations) dotnet build Splat.DI.SourceGenerator.slnx -c Release -warnaserror # Clean the solution @@ -149,14 +149,23 @@ See https://tunit.dev/docs/reference/command-line-flags for complete TUnit flag Splat.DI.SourceGenerator is a high-performance C# source generator that produces compile-time dependency injection registrations for Splat. It eliminates runtime reflection, provides full native AOT support, and includes intelligent analyzers with automatic code fixes. **Generator Project (`Splat.DependencyInjection.SourceGenerator/`)** -- `Generator.cs` - IIncrementalGenerator entry point with CreateSyntaxProvider pipeline -- `Models/` - Value-equatable POCO records (no ISymbol/SyntaxNode references) - - `RegistrationInfo.cs` - Base record for all registration types - - `TransientRegistrationInfo.cs`, `LazySingletonRegistrationInfo.cs`, `ConstantRegistrationInfo.cs` - - `ConstructorParameter.cs`, `PropertyInjection.cs` - - `EquatableArray.cs` - Value-equatable array wrapper for pipeline caching -- `CodeGeneration/CodeGenerator.cs` - String-based code generation (not SyntaxFactory) -- `Constants.cs` - Attribute definitions with `[Embedded]` attribute +- `Generator.cs` - IIncrementalGenerator entry point: one syntax provider for both marker methods, then a split + into a code output (registrations only) and a diagnostics output (registrations with locations) +- `RoslynHelpers.cs` - The syntax predicate and small symbol helpers +- `MetadataExtractor.cs` - The transform: turns a bound marker call into a `RegistrationSite` +- `WellKnownSymbols.cs` - The symbols extraction compares against, cached per compilation in a `ConditionalWeakTable` +- `RegistrationValidator.cs` - SPLATDI005/006/007, which need the whole registration graph +- `Models/` - Value-equatable pipeline models (no ISymbol, SyntaxNode or Location) + - `RegistrationInfo.cs` - Everything the generated code needs for one registration (`RegistrationKind` says which) + - `RegistrationSite.cs` - A registration plus its `LocationInfo`, for the diagnostics + - `LocationInfo.cs` - A location held as values (path, span, line span) + - `ConstructorParameter.cs`, `PropertyInjection.cs` - `readonly record struct`s + - `EquatableArray.cs` - Value-equatable array wrapper with a cached hash, read by index +- `CodeGeneration/` - Emission through `SourceWriter` (see Writing Generated Code) + - `CodeGenerator.cs` - The registrations file + - `MarkerSource.cs` - The fixed marker methods and attributes, added in post-initialization + - `SourceWriter.cs`, `SourceWriterExtensions.cs`, `PooledBuilder.cs` - The writer and its pooled builder +- `Constants.cs` - Names matched against and file names (linked into the analyzer, so constants only) - `DiagnosticWarnings.cs` - Shared diagnostic descriptors **Analyzer Project (`Splat.DependencyInjection.Analyzer/`)** @@ -166,31 +175,67 @@ Splat.DI.SourceGenerator is a high-performance C# source generator that produces - `CodeFixes/PropertyCodeFixProvider.cs` - Fixes property setter accessibility **Test Projects** -- `Splat.DependencyInjection.SourceGenerator.Tests/` - 342 snapshot tests using Verify.SourceGenerators -- `Splat.DependencyInjection.Analyzer.Tests/` - 45 analyzer and code fix tests +- `Splat.DependencyInjection.SourceGenerator.Tests/` - Snapshot tests (`GeneratorSnapshot`) plus unit tests of + the pipeline, extraction, validation, emission and caching +- `Splat.DependencyInjection.Analyzer.Tests/` - Analyzer and code fix tests + +**Benchmarks (`benchmarks/Splat.DI.SourceGenerator.Benchmarks/`)** - see `benchmarks/README.md` ### Key Architectural Patterns **Incremental Generator Pipeline (IIncrementalGenerator)** -- **Predicate functions** - Fast syntax-only checks (e.g., `IsRegisterInvocation`) -- **Transform functions** - Semantic analysis + POCO extraction (no ISymbol in output!) -- **Generation functions** - String-based code output using StringBuilder +- **Predicate** (`RoslynHelpers.IsRegistrationInvocation`) - syntax only, allocation free. Every marker is generic + and cannot infer its type arguments, and none takes a lambda, so calls without a type argument list or with a + lambda argument (Splat's own `resolver.Register(() => ...)`) never reach the transform. +- **Transform** (`MetadataExtractor.Extract`) - binds the call. A `CreateSyntaxProvider` transform re-runs for every + matching node on every compilation change, so it turns calls away as early and cheaply as it can. +- **Outputs** - the generated file is built from `RegistrationInfo` alone, so an edit that only moves a registration + regenerates nothing. The graph diagnostics are reported from their own output, which also carries the locations. + With no registrations, no registrations file is added (the partial method is removed by the compiler). +- Steps carry tracking names (`Generator.SitesStep` and so on); `GeneratorTests` asserts what an edit re-runs. **Value-Equatable Models (Critical for Caching)** -- ALL pipeline models must implement `IEquatable` -- NEVER include ISymbol or SyntaxNode references in pipeline outputs +- Pipeline models are `sealed record` or `readonly record struct` types with value equality +- NEVER include ISymbol, SyntaxNode or `Location` in pipeline outputs; use `LocationInfo` - Use `EquatableArray` for array equality in records - Extract strings from symbols using `ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)` +- Records on netstandard2.0 need `IsExternalInit`, which is inlined in `src/Polyfills/` and linked into the + generator and analyzer projects, as elsewhere in rxui **Generic-First API (AOT Compatible)** - Generated code uses `resolver.Register()` instead of `Register(factory, typeof(T))` - Eliminates boxing for value types - Full Native AOT and trimming support -**Code Generation Strategy** -- Uses StringBuilder with raw string literals (`"""`) -- 3-5x faster than SyntaxFactory approach -- No dependency on ReactiveMarbles.RoslynHelpers or ILRepack +**What the generated code allocates** +- Resolving a service allocates the objects it constructs and nothing else from the generated code; Splat's + `GetServices` collection is Splat's. A missing dependency throws through a `ThrowNotRegistered` helper written once + per file, so factories stay small. +- A factory that needs nothing from the resolver captures nothing, so its delegate is cached once by the compiler. +- `SetupIOC` allocates one closure (for `resolver` and every lazy), one delegate per capturing registration, and for + each lazy singleton its `Lazy` and three delegates. Lazies are method-level locals (`lazy0`, `lazy1`, ...), not + locals of a block per registration: a block adds a closure object each. + +**Interceptors are not used.** The marker calls are empty methods that registration never runs through, and +`SetupIOC` is a direct call to the generated method, so there is no call to redirect. Intercepting the marker calls +would change when and on which resolver registration happens. + +### Writing Generated Code + +`SourceWriter` owns the layout of every generated file. An emitter says what it writes, and the writer decides the +indentation. + +- **The writer tracks the level.** A line is indented when its first character is written. A blank line carries no + whitespace. Every line ends with `\n`. No string literal in an emitter starts with spaces. +- **Blocks change the level.** `OpenBlock` and `CloseBlock` write the braces and move one level in and out. + `OpenContinuation`/`CloseContinuation` put the arguments of a multi-line call one level deeper. +- **Each emitter method writes at the level it is given** and leaves it as it found it; its doc comment says where + it leaves the writer. +- **C# constructs have names** in `SourceWriterExtensions` (namespaces, continuations, argument separators). Domain + shapes live in `CodeGenerator` (`AppendFactoryCall`, `AppendFactory`, `AppendService`). +- **Fixed text is written with `Lines`** from a raw string literal whose indentation is relative to column zero. +- `SourceWriter.Rent` takes its `StringBuilder` from `PooledBuilder`'s per-thread slot, and `ToStringAndReturn` + gives it back. **Analyzer Separation (Roslyn Best Practice)** - Generator focuses on code generation only @@ -213,8 +258,11 @@ Splat.DI.SourceGenerator is a high-performance C# source generator that produces ### Style Enforcement - EditorConfig rules (`.editorconfig`) - comprehensive C# formatting and naming conventions -- StyleCop Analyzers - builds fail on violations -- Roslynator Analyzers - additional code quality rules +- StyleSharp.Analyzers (SST), PerformanceSharp.Analyzers (PSH) and SecuritySharp.Analyzers (SES) - builds fail on + violations. Rule docs: https://github.com/glennawatson/RoslynCommonAnalyzers/tree/main/docs/rules +- Fix the code. Do not suppress rules, do not disable them in `.editorconfig`, and do not use + `#pragma warning disable` (the `#pragma` for obsolete members inside the generated output is part of what the + generator emits, not our source) - Analysis level: latest with enhanced .NET analyzers - **All public APIs require XML documentation comments** (including protected methods of public classes) @@ -239,7 +287,15 @@ See `.github/COPILOT_INSTRUCTIONS.md` for complete style guide. - Test projects: `Splat.DependencyInjection.Analyzer.Tests` and `Splat.DependencyInjection.SourceGenerator.Tests` - Coverage configured in `src/testconfig.json` (Cobertura format) - Parallel test execution disabled (`"parallel": false` in testconfig.json) -- Snapshot testing uses Verify.SourceGenerators with `*.verified.cs` files +- Snapshot tests compare every generated registrations file with a `*.verified.cs` snapshot beside the test class, + through `GeneratorSnapshot.cs`. A snapshot is named `{type}.{method}_{arguments}#{hint name}.verified.cs`; generator + diagnostics go to `...#Diagnostics.verified.txt`. The fixed marker source and embedded attribute are stored once, by + `SnapshotTests.WritesFixedSources`. An output that differs or has no snapshot is written beside it as `.received` + and fails the test, as does a snapshot the run no longer produces +- To accept new or changed snapshots, run the tests with `ACCEPT_SNAPSHOTS=1`, then run them again without it +- Snapshot paths must fit the Windows path limit on a CI runner (`D:\a\{repo}\{repo}\...`, under 256 characters); + `SnapshotTests.SnapshotPathsFitWindowsLimit` checks this, so keep test names and arguments short +- Line endings are LF everywhere (`.gitattributes`); the analyzers fail the build on CRLF - Always write unit tests for new features or bug fixes - Follow existing test patterns in test projects - Use `TestUtilities.AreEquivalent()` for newline-agnostic source code comparison @@ -259,9 +315,9 @@ See `.github/COPILOT_INSTRUCTIONS.md` for complete style guide. 2. **Create value-equatable POCOs** - no ISymbol/SyntaxNode references 3. Create failing tests first (snapshot tests in SourceGenerator.Tests) 4. Implement minimal functionality in Generator.cs -5. Update code generation in CodeGenerator.cs (use StringBuilder, not SyntaxFactory) +5. Update code generation in CodeGenerator.cs through `SourceWriter` (not a raw StringBuilder, not SyntaxFactory) 6. Ensure generic-first API usage: `resolver.Register()` not `typeof(T)` -7. Verify snapshots match expected output (C# 7.3 compatible) +7. Verify snapshots match expected output; a passing snapshot test also requires the generated code to compile 8. Add XML documentation to all public APIs 9. Run formatting validation before committing @@ -277,7 +333,7 @@ See `.github/COPILOT_INSTRUCTIONS.md` for complete style guide. ### Fixing Bugs -1. Create reproduction test (use Verify snapshots) +1. Create reproduction test (use snapshots) 2. Fix with minimal changes 3. Ensure pipeline still caches properly (POCOs value-equatable) 4. Verify no regression in existing tests @@ -285,19 +341,20 @@ See `.github/COPILOT_INSTRUCTIONS.md` for complete style guide. ### Updating Generated Code Format -1. Modify code generation in `CodeGeneration/CodeGenerator.cs` -2. Use raw string literals (`"""`) for multi-line code +1. Modify code generation in `CodeGeneration/CodeGenerator.cs` through `SourceWriter` +2. Write fixed multi-line text as raw string literals (`"""`) passed to `Lines` 3. Ensure generic-first API: `resolver.Register()` not `typeof(T)` -4. Run all snapshot tests - expect 342 failing tests -5. Review each `.verified.cs` diff carefully -6. Accept snapshots only if changes are correct -7. Ensure C# 7.3 compatibility (no file-scoped namespaces, no init properties) +4. Run all snapshot tests - expect every `Splat.DI.Reg.g` snapshot to fail +5. Review each received file carefully and accept (`ACCEPT_SNAPSHOTS=1`) only if the changes are correct +6. Keep file-scoped namespaces, init properties and similar newer syntax out of the generated code +7. Measure with the benchmarks (see `benchmarks/README.md`) ## What to Avoid - **ISymbol/SyntaxNode in pipeline outputs** - breaks incremental caching - **Runtime reflection** in generated code - breaks AOT compatibility -- **SyntaxFactory for code generation** - 3-5x slower than StringBuilder +- **SyntaxFactory or a raw StringBuilder for code generation** - write through `SourceWriter` +- **LINQ in the generator** - use loops; the transform runs for every marker call on every compilation change - **Type-based API** - use `resolver.Register()` not `Register(factory, typeof(T))` - **Diagnostics in generator** - use separate analyzer project instead - **Heavy dependencies** - keep generator lightweight (netstandard2.0 target) @@ -308,9 +365,9 @@ See `.github/COPILOT_INSTRUCTIONS.md` for complete style guide. - **Value-Equatable POCOs:** CRITICAL for incremental generator caching - never include ISymbol/SyntaxNode - **Generic-First API:** All generated code must use `resolver.Register()` for AOT compatibility -- **String-Based Generation:** Use StringBuilder with raw string literals, not SyntaxFactory +- **Generation:** Write through `SourceWriter`, not SyntaxFactory - **Separate Analyzer:** Diagnostics in separate project following Roslyn best practices -- **No shallow clones:** Repository requires full clone for git version information used by Nerdbank.GitVersioning +- **No shallow clones:** Repository requires full clone for git version information used by MinVer - **Required .NET SDKs:** .NET 8.0, 9.0, and 10.0 (all three required for full build) - **Snapshot Testing:** Review `.verified.cs` diffs carefully before accepting - **Comprehensive Instructions:** `.github/COPILOT_INSTRUCTIONS.md` contains detailed development guidelines diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e3959584..f239945d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,6 +5,9 @@ latest AnyCPU $(MSBuildProjectName.Contains('Tests')) + + $(MSBuildProjectName.Contains('Benchmark')) embedded Glenn Watson Copyright (c) $([System.DateTime]::Now.ToString(yyyy)) ReactiveUI Association Inc @@ -45,7 +48,7 @@ - + @@ -71,10 +74,8 @@ - - - - - + + + diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index d6abc5a2..e4a132fb 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -4,34 +4,44 @@ true + + 5.1.2 + + - - - - - - - - + + + + + + + + - - - + + + - + - - - - + + + + + + + + - - + + diff --git a/src/Polyfills/IsExternalInit.cs b/src/Polyfills/IsExternalInit.cs new file mode 100644 index 00000000..bb87a48e --- /dev/null +++ b/src/Polyfills/IsExternalInit.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +// Polyfill implementation adapted from SimonCropp/Polyfill (https://github.com/SimonCropp/Polyfill). +#if !NET5_0_OR_GREATER +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace System.Runtime.CompilerServices; + +/// Reserved for the compiler to track metadata for -only members; not for use in source. +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +internal static class IsExternalInit +{ + /// Gets a value indicating that this is the compiler-recognized init-only marker type. + internal static bool IsCompilerMarker => true; +} +#endif diff --git a/src/Splat.DI.SourceGenerator.slnx b/src/Splat.DI.SourceGenerator.slnx index e543ca27..10cdf7d6 100644 --- a/src/Splat.DI.SourceGenerator.slnx +++ b/src/Splat.DI.SourceGenerator.slnx @@ -4,6 +4,9 @@ + + + @@ -13,7 +16,6 @@ - diff --git a/src/Splat.DependencyInjection.Analyzer/Analyzers/AnalyzerHelpers.cs b/src/Splat.DependencyInjection.Analyzer/Analyzers/AnalyzerHelpers.cs index af60d2c0..8025a7d5 100644 --- a/src/Splat.DependencyInjection.Analyzer/Analyzers/AnalyzerHelpers.cs +++ b/src/Splat.DependencyInjection.Analyzer/Analyzers/AnalyzerHelpers.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System; @@ -9,36 +9,26 @@ namespace Splat.DependencyInjection.Analyzer.Analyzers; -/// -/// Helper methods for Splat analyzers. -/// +/// Helper methods for Splat analyzers. internal static class AnalyzerHelpers { - /// - /// The fully qualified symbol display format used for attribute string comparison fallback. - /// + /// The fully qualified symbol display format used for attribute string comparison fallback. private static readonly SymbolDisplayFormat _fullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat; - /// - /// Checks if a method symbol is a specific method from SplatRegistrations class. - /// + /// Checks if a method symbol is a specific method from SplatRegistrations class. /// The method symbol to check. /// The expected method name. /// True if the method is from SplatRegistrations with the specified name. - public static bool IsSplatRegistrationsMethod(IMethodSymbol methodSymbol, string methodName) - { - return IsContainedInSplatRegistrations(methodSymbol.ContainingType?.OriginalDefinition) && - methodSymbol.Name == methodName && - !methodSymbol.IsExtensionMethod; - } + internal static bool IsSplatRegistrationsMethod(IMethodSymbol methodSymbol, string methodName) => + IsContainedInSplatRegistrations(methodSymbol.ContainingType?.OriginalDefinition) + && methodSymbol.Name == methodName + && !methodSymbol.IsExtensionMethod; - /// - /// Analyzes constructors for a specific type and reports diagnostics. - /// + /// Analyzes constructors for a specific type and reports diagnostics. /// The compilation. /// The type to analyze. /// Action to report diagnostics. - public static void AnalyzeConstructorsForType( + internal static void AnalyzeConstructorsForType( Compilation compilation, ITypeSymbol typeSymbol, Action reportDiagnostic) @@ -60,25 +50,21 @@ public static void AnalyzeConstructorsForType( ReportDiagnostics(analysis, namedType, constructorAttributeSymbol, reportDiagnostic); } - /// - /// Checks if a type symbol represents the SplatRegistrations class in the Splat namespace. - /// + /// Checks if a type symbol represents the SplatRegistrations class in the Splat namespace. /// The containing type (may be null if the method has no containing type). /// True if the type is Splat.SplatRegistrations. internal static bool IsContainedInSplatRegistrations(INamedTypeSymbol? containingType) { - if (containingType == null) + if (containingType is null) { return false; } - return containingType.ContainingNamespace?.Name == SourceGenerator.Constants.NamespaceName && - containingType.Name == SourceGenerator.Constants.ClassName; + return containingType.ContainingNamespace?.Name == SourceGenerator.Constants.NamespaceName + && containingType.Name == SourceGenerator.Constants.ClassName; } - /// - /// Analyzes the constructors of a type to count accessible and marked constructors. - /// + /// Analyzes the constructors of a type to count accessible and marked constructors. /// The type to analyze. /// The attribute symbol to check for. /// Analysis result. @@ -105,33 +91,33 @@ internal static ConstructorAnalysisResult GetConstructorAnalysis(INamedTypeSymbo accessibleCount++; } - if (IsConstructorMarked(ctor, constructorAttributeSymbol)) + if (!IsConstructorMarked(ctor, constructorAttributeSymbol)) { - markedCount++; - if (firstMarked == null) - { - firstMarked = ctor; - } - else if (secondMarked == null) - { - secondMarked = ctor; - } + continue; + } + + markedCount++; + if (firstMarked is null) + { + firstMarked = ctor; + } + else + { + secondMarked ??= ctor; } } - return new ConstructorAnalysisResult(accessibleCount, markedCount, firstMarked, secondMarked); + return new(accessibleCount, markedCount, firstMarked, secondMarked); } - /// - /// Checks if a constructor is marked with the DependencyInjectionConstructor attribute. - /// + /// Checks if a constructor is marked with the DependencyInjectionConstructor attribute. /// The constructor to check. /// The attribute symbol to check against (if available). /// True if marked. internal static bool IsConstructorMarked(IMethodSymbol ctor, INamedTypeSymbol? constructorAttributeSymbol) { var attrs = ctor.GetAttributes(); - if (constructorAttributeSymbol != null) + if (constructorAttributeSymbol is not null) { // Fast path: symbol comparison for (var j = 0; j < attrs.Length; j++) @@ -192,17 +178,13 @@ internal static void ReportDiagnostics( } } } - else if (analysis.FirstMarked != null) + else if (analysis.FirstMarked is not null && analysis.FirstMarked.DeclaredAccessibility < Accessibility.Internal) { - // Exactly one constructor is marked - check accessibility - if (analysis.FirstMarked.DeclaredAccessibility < Accessibility.Internal) - { - // SPLATDI004: Constructor must be public or internal - reportDiagnostic(Diagnostic.Create( - SourceGenerator.DiagnosticWarnings.ConstructorsMustBePublic, - GetFirstLocation(analysis.FirstMarked.Locations), - namedType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); - } + // SPLATDI004: exactly one constructor is marked, and it must be public or internal + reportDiagnostic(Diagnostic.Create( + SourceGenerator.DiagnosticWarnings.ConstructorsMustBePublic, + GetFirstLocation(analysis.FirstMarked.Locations), + namedType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); } return; // Don't check for multiple constructors without attribute if one is marked @@ -219,17 +201,13 @@ internal static void ReportDiagnostics( } } - /// - /// Gets the first location from a locations array, or if empty. - /// + /// Gets the first location from a locations array, or if empty. /// The locations array. /// The first location or . - internal static Location GetFirstLocation(ImmutableArray locations) - => locations.Length > 0 ? locations[0] : Location.None; + internal static Location GetFirstLocation(ImmutableArray locations) => + !locations.IsEmpty ? locations[0] : Location.None; - /// - /// Result of constructor analysis. - /// + /// Result of constructor analysis. /// Gets the number of accessible constructors. /// Gets the number of constructors marked with the attribute. /// Gets the first constructor found that was marked with the attribute. diff --git a/src/Splat.DependencyInjection.Analyzer/Analyzers/ConstructorAnalyzer.cs b/src/Splat.DependencyInjection.Analyzer/Analyzers/ConstructorAnalyzer.cs index d27de300..1b538fa8 100644 --- a/src/Splat.DependencyInjection.Analyzer/Analyzers/ConstructorAnalyzer.cs +++ b/src/Splat.DependencyInjection.Analyzer/Analyzers/ConstructorAnalyzer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System; @@ -21,10 +21,11 @@ public class ConstructorAnalyzer : DiagnosticAnalyzer { /// public override ImmutableArray SupportedDiagnostics => - ImmutableArray.Create( - SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute, - SourceGenerator.DiagnosticWarnings.MultipleConstructorsMarked, - SourceGenerator.DiagnosticWarnings.ConstructorsMustBePublic); + [ + SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute, + SourceGenerator.DiagnosticWarnings.MultipleConstructorsMarked, + SourceGenerator.DiagnosticWarnings.ConstructorsMustBePublic, + ]; /// public override void Initialize(AnalysisContext context) @@ -47,20 +48,19 @@ public override void Initialize(AnalysisContext context) /// The operation analysis context. private static void AnalyzeInvocation(OperationAnalysisContext context) { - var invocation = (IInvocationOperation)context.Operation; - var method = invocation.TargetMethod; + var method = ((IInvocationOperation)context.Operation).TargetMethod; // Check if it's SplatRegistrations.Register or RegisterLazySingleton // Note: RegisterConstant is NOT included because it takes a pre-instantiated object, // so constructor analysis is not needed (GitHub issue #292) - if (!AnalyzerHelpers.IsSplatRegistrationsMethod(method, SourceGenerator.Constants.MethodNameRegister) && - !AnalyzerHelpers.IsSplatRegistrationsMethod(method, SourceGenerator.Constants.MethodNameRegisterLazySingleton)) + if (!AnalyzerHelpers.IsSplatRegistrationsMethod(method, SourceGenerator.Constants.MethodNameRegister) + && !AnalyzerHelpers.IsSplatRegistrationsMethod(method, SourceGenerator.Constants.MethodNameRegisterLazySingleton)) { return; } // Extract concrete type from type arguments - if (method.TypeArguments.Length == 0 || method.TypeArguments.Length > 2) + if (method.TypeArguments.IsEmpty || method.TypeArguments.Length > 2) { return; } diff --git a/src/Splat.DependencyInjection.Analyzer/Analyzers/PropertyAnalyzer.cs b/src/Splat.DependencyInjection.Analyzer/Analyzers/PropertyAnalyzer.cs index 7e685633..b1a96cb5 100644 --- a/src/Splat.DependencyInjection.Analyzer/Analyzers/PropertyAnalyzer.cs +++ b/src/Splat.DependencyInjection.Analyzer/Analyzers/PropertyAnalyzer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System; @@ -17,14 +17,9 @@ namespace Splat.DependencyInjection.Analyzer.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class PropertyAnalyzer : DiagnosticAnalyzer { - /// - /// The fully qualified symbol display format used for diagnostic messages. - /// - private static readonly SymbolDisplayFormat _fullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat; - /// public override ImmutableArray SupportedDiagnostics => - ImmutableArray.Create(SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable); + [SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable]; /// public override void Initialize(AnalysisContext context) @@ -44,7 +39,7 @@ public override void Initialize(AnalysisContext context) var propertyAttributeSymbol = compilationContext.Compilation.GetTypeByMetadataName(SourceGenerator.Constants.PropertyAttributeMetadataName); // Only register the symbol action if the attribute exists in this compilation - if (propertyAttributeSymbol != null) + if (propertyAttributeSymbol is not null) { compilationContext.RegisterSymbolAction( symbolContext => AnalyzeProperty(symbolContext, propertyAttributeSymbol), @@ -59,7 +54,7 @@ public override void Initialize(AnalysisContext context) /// /// The symbol analysis context. /// The resolved DependencyInjectionPropertyAttribute symbol. - private static void AnalyzeProperty(SymbolAnalysisContext context, INamedTypeSymbol propertyAttributeSymbol) + private static void AnalyzeProperty(in SymbolAnalysisContext context, INamedTypeSymbol propertyAttributeSymbol) { var property = (IPropertySymbol)context.Symbol; @@ -70,11 +65,13 @@ private static void AnalyzeProperty(SymbolAnalysisContext context, INamedTypeSym // Fast path: symbol comparison (no string allocations) for (var i = 0; i < attrs.Length; i++) { - if (SymbolEqualityComparer.Default.Equals(attrs[i].AttributeClass, propertyAttributeSymbol)) + if (!SymbolEqualityComparer.Default.Equals(attrs[i].AttributeClass, propertyAttributeSymbol)) { - hasAttribute = true; - break; + continue; } + + hasAttribute = true; + break; } if (!hasAttribute) @@ -83,11 +80,11 @@ private static void AnalyzeProperty(SymbolAnalysisContext context, INamedTypeSym } // Check if setter exists and is accessible (public or internal) - if (property.SetMethod == null || property.SetMethod.DeclaredAccessibility < Accessibility.Internal) + if (property.SetMethod is null || property.SetMethod.DeclaredAccessibility < Accessibility.Internal) { context.ReportDiagnostic(Diagnostic.Create( SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable, - property.Locations.Length > 0 ? property.Locations[0] : Location.None, + AnalyzerHelpers.GetFirstLocation(property.Locations), property.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); } } diff --git a/src/Splat.DependencyInjection.Analyzer/CodeFixes/ConstructorCodeFixProvider.cs b/src/Splat.DependencyInjection.Analyzer/CodeFixes/ConstructorCodeFixProvider.cs index b33d2f5a..36bc6a12 100644 --- a/src/Splat.DependencyInjection.Analyzer/CodeFixes/ConstructorCodeFixProvider.cs +++ b/src/Splat.DependencyInjection.Analyzer/CodeFixes/ConstructorCodeFixProvider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; @@ -8,23 +8,21 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; namespace Splat.DependencyInjection.Analyzer.CodeFixes; -/// -/// Code fix provider that adds [DependencyInjectionConstructor] attribute to a constructor. -/// +/// Code fix provider that adds [DependencyInjectionConstructor] attribute to a constructor. [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ConstructorCodeFixProvider))] [Shared] public class ConstructorCodeFixProvider : CodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds => - ImmutableArray.Create(SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute.Id); + [SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute.Id]; /// public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; @@ -32,62 +30,25 @@ public class ConstructorCodeFixProvider : CodeFixProvider /// public override async Task RegisterCodeFixesAsync(CodeFixContext context) { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); - if (root == null) - { - return; - } + // This provider is exported for C# only, and C# documents always support syntax trees, so the root is never null. + var root = (await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false))!; var diagnostic = context.Diagnostics[0]; - var diagnosticSpan = diagnostic.Location.SourceSpan; - // Manual ancestor walk to find TypeDeclarationSyntax - var node = root.FindToken(diagnosticSpan.Start).Parent; - TypeDeclarationSyntax? typeDeclaration = null; - while (node != null) - { - if (node is TypeDeclarationSyntax tds) - { - typeDeclaration = tds; - break; - } - - node = node.Parent; - } - - if (typeDeclaration == null) + // Every token found in a syntax tree has a parent node (at least the compilation unit). + var typeDeclaration = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent!.FirstAncestorOrSelf(); + if (typeDeclaration is null) { return; } - // Find all non-static constructors (manual loop to avoid LINQ allocations) - var constructors = new System.Collections.Generic.List(capacity: 4); - var members = typeDeclaration.Members; - for (var i = 0; i < members.Count; i++) + foreach (var member in typeDeclaration.Members) { - if (members[i] is ConstructorDeclarationSyntax ctor) + if (member is not ConstructorDeclarationSyntax constructor || constructor.Modifiers.Any(SyntaxKind.StaticKeyword)) { - // Check if not static - var isStatic = false; - var modifiers = ctor.Modifiers; - for (var j = 0; j < modifiers.Count; j++) - { - if (modifiers[j].IsKind(SyntaxKind.StaticKeyword)) - { - isStatic = true; - break; - } - } - - if (!isStatic) - { - constructors.Add(ctor); - } + continue; } - } - foreach (var constructor in constructors) - { var parameterCount = constructor.ParameterList.Parameters.Count; var title = parameterCount == 0 ? $"Add [{SourceGenerator.Constants.ConstructorAttributeShortName}] to parameterless constructor" @@ -102,9 +63,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - /// - /// Adds the [DependencyInjectionConstructor] attribute to the specified constructor. - /// + /// Adds the [DependencyInjectionConstructor] attribute to the specified constructor. /// The document containing the constructor. /// The constructor syntax to add the attribute to. /// The cancellation token. @@ -114,11 +73,8 @@ internal static async Task AddAttributeAsync( ConstructorDeclarationSyntax constructor, CancellationToken cancellationToken) { - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - if (root == null) - { - return document; - } + // Only C# documents reach this method, and C# documents always support syntax trees, so the root is never null. + var root = (await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false))!; // Create attribute syntax var attribute = SyntaxFactory.Attribute( diff --git a/src/Splat.DependencyInjection.Analyzer/CodeFixes/PropertyCodeFixProvider.cs b/src/Splat.DependencyInjection.Analyzer/CodeFixes/PropertyCodeFixProvider.cs index e181b482..6c9b7260 100644 --- a/src/Splat.DependencyInjection.Analyzer/CodeFixes/PropertyCodeFixProvider.cs +++ b/src/Splat.DependencyInjection.Analyzer/CodeFixes/PropertyCodeFixProvider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; @@ -8,23 +8,21 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; namespace Splat.DependencyInjection.Analyzer.CodeFixes; -/// -/// Code fix provider that fixes property setter accessibility for dependency injection. -/// +/// Code fix provider that fixes property setter accessibility for dependency injection. [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PropertyCodeFixProvider))] [Shared] public class PropertyCodeFixProvider : CodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds => - ImmutableArray.Create(SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable.Id); + [SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable.Id]; /// public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; @@ -32,19 +30,15 @@ public class PropertyCodeFixProvider : CodeFixProvider /// public override async Task RegisterCodeFixesAsync(CodeFixContext context) { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); - if (root == null) - { - return; - } + // This provider is exported for C# only, and C# documents always support syntax trees, so the root is never null. + var root = (await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false))!; var diagnostic = context.Diagnostics[0]; - var diagnosticSpan = diagnostic.Location.SourceSpan; // Manual ancestor walk to find PropertyDeclarationSyntax - var node = root.FindToken(diagnosticSpan.Start).Parent; + var node = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent; PropertyDeclarationSyntax? propertyDeclaration = null; - while (node != null) + while (node is not null) { if (node is PropertyDeclarationSyntax pds) { @@ -55,7 +49,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) node = node.Parent; } - if (propertyDeclaration == null) + if (propertyDeclaration is null) { return; } @@ -92,17 +86,14 @@ internal static async Task AddSetterAsync( SyntaxKind accessorModifier, CancellationToken cancellationToken) { - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - if (root == null) - { - return document; - } + // Only C# documents reach this method, and C# documents always support syntax trees, so the root is never null. + var root = (await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false))!; var setterModifiers = BuildSetterModifiers(property, accessorModifier); PropertyDeclarationSyntax newProperty; - if (property.AccessorList == null) + if (property.AccessorList is null) { newProperty = ConvertExpressionBodiedProperty(property, setterModifiers); } @@ -113,14 +104,16 @@ internal static async Task AddSetterAsync( AccessorDeclarationSyntax? existingSetter = null; for (var i = 0; i < accessors.Count; i++) { - if (accessors[i].Kind() == SyntaxKind.SetAccessorDeclaration) + if (accessors[i].Kind() != SyntaxKind.SetAccessorDeclaration) { - existingSetter = accessors[i]; - break; + continue; } + + existingSetter = accessors[i]; + break; } - newProperty = existingSetter == null + newProperty = existingSetter is null ? AddSetterToGetterOnlyProperty(property, setterModifiers) : UpdateExistingSetterModifiers(property, existingSetter, setterModifiers); } @@ -159,7 +152,7 @@ internal static SyntaxTokenList BuildSetterModifiers(PropertyDeclarationSyntax p /// The transformed property with getter and setter accessors. internal static PropertyDeclarationSyntax ConvertExpressionBodiedProperty( PropertyDeclarationSyntax property, - SyntaxTokenList setterModifiers) + in SyntaxTokenList setterModifiers) { var getter = SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, @@ -188,15 +181,13 @@ internal static PropertyDeclarationSyntax ConvertExpressionBodiedProperty( .WithSemicolonToken(default); } - /// - /// Adds a setter accessor to a property that only has a getter. - /// + /// Adds a setter accessor to a property that only has a getter. /// The getter-only property. /// The modifier tokens for the setter. /// The property with the setter added. internal static PropertyDeclarationSyntax AddSetterToGetterOnlyProperty( PropertyDeclarationSyntax property, - SyntaxTokenList setterModifiers) + in SyntaxTokenList setterModifiers) { var setter = SyntaxFactory.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration) @@ -207,9 +198,7 @@ internal static PropertyDeclarationSyntax AddSetterToGetterOnlyProperty( return property.WithAccessorList(newAccessorList); } - /// - /// Updates the accessibility modifiers on an existing setter accessor. - /// + /// Updates the accessibility modifiers on an existing setter accessor. /// The property containing the setter. /// The existing setter accessor to update. /// The new modifier tokens for the setter. @@ -217,7 +206,7 @@ internal static PropertyDeclarationSyntax AddSetterToGetterOnlyProperty( internal static PropertyDeclarationSyntax UpdateExistingSetterModifiers( PropertyDeclarationSyntax property, AccessorDeclarationSyntax existingSetter, - SyntaxTokenList setterModifiers) + in SyntaxTokenList setterModifiers) { var newSetter = existingSetter.WithModifiers(setterModifiers); var newAccessorList = property.AccessorList!.ReplaceNode(existingSetter, newSetter); diff --git a/src/Splat.DependencyInjection.Analyzer/Constants.cs b/src/Splat.DependencyInjection.Analyzer/Constants.cs index 72e58106..483379bd 100644 --- a/src/Splat.DependencyInjection.Analyzer/Constants.cs +++ b/src/Splat.DependencyInjection.Analyzer/Constants.cs @@ -1,14 +1,15 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace Splat.DependencyInjection.Analyzer; -/// -/// Constants for code fix titles and other analyzer-specific strings. -/// +/// Constants for code fix titles and other analyzer-specific strings. internal static class Constants { + /// The title of the code fix that gives a property a public setter. public const string CodeFixAddPublicSetter = "Add public setter"; + + /// The title of the code fix that gives a property an internal setter. public const string CodeFixAddInternalSetter = "Add internal setter"; } diff --git a/src/Splat.DependencyInjection.Analyzer/IsExternalInit.cs b/src/Splat.DependencyInjection.Analyzer/IsExternalInit.cs deleted file mode 100644 index a934098c..00000000 --- a/src/Splat.DependencyInjection.Analyzer/IsExternalInit.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace System.Runtime.CompilerServices; - -/// -/// Reserved to be used by the compiler for tracking metadata. -/// This class should not be used by developers in source code. -/// -[ExcludeFromCodeCoverage] -[EditorBrowsable(EditorBrowsableState.Never)] -internal static class IsExternalInit; diff --git a/src/Splat.DependencyInjection.Analyzer/Splat.DependencyInjection.Analyzer.csproj b/src/Splat.DependencyInjection.Analyzer/Splat.DependencyInjection.Analyzer.csproj index 9763d83b..02bd533d 100644 --- a/src/Splat.DependencyInjection.Analyzer/Splat.DependencyInjection.Analyzer.csproj +++ b/src/Splat.DependencyInjection.Analyzer/Splat.DependencyInjection.Analyzer.csproj @@ -26,6 +26,11 @@ + + + + + diff --git a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/CodeGenerator.cs b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/CodeGenerator.cs index 2bfe6af4..5b5c8549 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/CodeGenerator.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/CodeGenerator.cs @@ -1,188 +1,347 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System; using System.Collections.Immutable; -using System.Text; +using System.Runtime.CompilerServices; using Splat.DependencyInjection.SourceGenerator.Models; namespace Splat.DependencyInjection.SourceGenerator.CodeGeneration; -/// -/// Handles string-based code generation for Splat DI. -/// +/// Writes the registrations file: the body of SetupIOCInternal. +/// +/// +/// Every registration becomes a factory passed to Splat's generic Register<T>. A factory that needs nothing +/// from the resolver captures nothing, so the compiler caches its delegate once for the life of the application. The +/// others share the one closure the compiler creates for resolver. +/// +/// +/// A dependency the resolver does not have throws through a helper written once per file. The factory then holds a +/// call rather than the construction and concatenation of an exception, which keeps the code the factory runs on +/// every resolution small. +/// +/// internal static class CodeGenerator { - /// - /// Generates the SetupIOCInternal method. - /// - /// The transient registrations. - /// The lazy singleton registrations. - /// The generated source code. - internal static string GenerateSetupIOCMethod( - ImmutableArray transients, - ImmutableArray lazySingletons) - { - var sb = new StringBuilder(); + /// The characters the fixed parts of the file take. + internal const int FileCapacity = 2048; - sb.Append(""" - // + /// The characters a registration typically takes. + internal const int RegistrationCapacity = 384; - #nullable enable annotations - #nullable disable warnings + /// The name of the helpers that throw for an unregistered dependency. + internal const string ThrowNotRegistered = "ThrowNotRegistered"; - // Suppress warnings about [Obsolete] member usage in generated code. - #pragma warning disable CS0612, CS0618 + /// The start of a registration on the resolver, before the registered type. + private const string RegisterOpen = "resolver.Register<"; - namespace Splat - { - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { - """); - - foreach (var registration in transients) + /// The name of a lazy singleton's local, before its number. + private const string LazyLocal = "lazy"; + + /// The opening of the fully qualified type. + private const string LazyTypeOpen = "global::System.Lazy<"; + + /// The markers at the top of the file. + private const string FileHeader = """ + // + + #nullable enable annotations + #nullable disable warnings + + // Suppress warnings about [Obsolete] member usage in generated code. + #pragma warning disable CS0612, CS0618 + """; + + /// The declaration of the partial class, written inside the namespace. + private const string ClassDeclaration = """ + /// + /// Provides extension methods for the Splat dependency injection source generator. + /// This partial class contains the generated implementation of dependency registrations. + /// + internal static partial class SplatRegistrations + """; + + /// The declaration of the registration method, written inside the class. + private const string MethodDeclaration = """ + /// + /// Internal implementation of dependency injection setup. + /// This method is generated at compile-time and contains all registrations + /// defined through the source generator marker methods. + /// + /// The instance to register dependencies with. + static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) + """; + + /// The helper that throws for a dependency registered without a contract. + private const string ThrowNotRegisteredMethod = $$""" + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T {{ThrowNotRegistered}}(string typeName) { - sb.AppendLine(); - GenerateTransientRegistration(sb, registration); + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } + """; - foreach (var registration in lazySingletons) + /// The helper that throws for a dependency registered under a contract. + private const string ThrowNotRegisteredWithContractMethod = $$""" + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T {{ThrowNotRegistered}}(string typeName, string contract) { - sb.AppendLine(); - GenerateLazySingletonRegistration(sb, registration); + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } + """; - sb.Append(""" - } - } - } - """); + /// Which throw helpers the written registrations call. + [Flags] + internal enum ThrowHelpers + { + /// No helper is called. + None = 0, + + /// The helper for a dependency without a contract is called. + WithoutContract = 1 << 0, - return sb.ToString(); + /// The helper for a dependency under a contract is called. + WithContract = 1 << 1, } - /// - /// Generates a transient registration. - /// - /// The string builder to append to. - /// The registration information. - internal static void GenerateTransientRegistration( - StringBuilder sb, - TransientRegistrationInfo registration) + /// Writes the registrations file. + /// The registrations, in source order. + /// The source. + /// + /// Transient registrations are written before lazy singletons, as they always have been. Splat resolves the last + /// registration of a type, so the order decides which of two registrations of one type wins. + /// + internal static string Generate(ImmutableArray registrations) { - var constructorArgs = GetConstructorArguments(registration.ConstructorParameters, registration.ContractValue); - var propertyInitializer = GetPropertyInitializer(registration.PropertyInjections, registration.ContractValue); - var contractArg = registration.ContractValue is not null ? $", {registration.ContractValue}" : string.Empty; + var writer = SourceWriter.Rent(FileCapacity + (registrations.Length * RegistrationCapacity)) + .Lines(FileHeader) + .BlankLine() + .OpenNamespace(Constants.NamespaceName) + .Lines(ClassDeclaration) + .OpenBlock() + .Lines(MethodDeclaration) + .OpenBlock(); - sb.AppendLine($" resolver.Register<{registration.InterfaceTypeFullName}>(() => new {registration.ConcreteTypeFullName}({constructorArgs}){propertyInitializer}{contractArg});"); + var used = ThrowHelpers.None; + var written = 0; + var lazySingletons = 0; + foreach (var registration in registrations) + { + if (registration.Kind != RegistrationKind.Transient) + { + continue; + } + + SeparateRegistration(writer, written); + written++; + AppendTransient(writer, registration, ref used); + } + + foreach (var registration in registrations) + { + if (registration.Kind != RegistrationKind.LazySingleton) + { + continue; + } + + SeparateRegistration(writer, written); + written++; + AppendLazySingleton(writer, registration, lazySingletons, ref used); + lazySingletons++; + } + + _ = writer.CloseBlock(); + AppendThrowHelpers(writer, used); + return writer.CloseBlock().CloseBlock().ToStringAndReturn(); } - /// - /// Generates a lazy singleton registration. - /// - /// The string builder to append to. - /// The registration information. - internal static void GenerateLazySingletonRegistration( - StringBuilder sb, - LazySingletonRegistrationInfo registration) + /// Writes a transient registration. + /// The writer, at the method body's level. + /// The registration. + /// The throw helpers called so far, updated with those this registration calls. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void AppendTransient(SourceWriter writer, RegistrationInfo registration, ref ThrowHelpers used) => + AppendFactoryCall( + writer.Append(RegisterOpen).Append(registration.InterfaceTypeFullName).Append(">("), + registration, + registration.ContractValue, + ref used); + + /// Writes a lazy singleton registration: the lazy value, and the lazy and its value registered. + /// The writer, at the method body's level. + /// The registration. + /// The number of lazy singletons written before this one, which names its local. + /// The throw helpers called so far, updated with those this registration calls. + /// + /// Each lazy is a local of the method itself, named by its position, rather than of a block of its own. The + /// compiler keeps every captured local of one scope in one closure object, and resolver already needs one, + /// so the lambdas that read the lazy add no closure; a block per registration would add one each. + /// + internal static void AppendLazySingleton(SourceWriter writer, RegistrationInfo registration, int index, ref ThrowHelpers used) { - var constructorArgs = GetConstructorArguments(registration.ConstructorParameters, registration.ContractValue); - var propertyInitializer = GetPropertyInitializer(registration.PropertyInjections, registration.ContractValue); - var lazyTypeFullName = $"global::System.Lazy<{registration.InterfaceTypeFullName}>"; - var lazyModeArg = registration.LazyThreadSafetyMode is not null ? $", {registration.LazyThreadSafetyMode}" : string.Empty; - var contractArg = registration.ContractValue is not null ? $", {registration.ContractValue}" : string.Empty; - - sb.AppendLine($$""" - { - {{lazyTypeFullName}} lazy = new {{lazyTypeFullName}}(() => new {{registration.ConcreteTypeFullName}}({{constructorArgs}}){{propertyInitializer}}{{lazyModeArg}}); - resolver.Register<{{lazyTypeFullName}}>(() => lazy{{contractArg}}); - resolver.Register<{{registration.InterfaceTypeFullName}}>(() => lazy.Value{{contractArg}}); - } - """); + var serviceType = registration.InterfaceTypeFullName; + _ = writer.Append("var ").Append(LazyLocal).Append(index).Append(" = new ").Append(LazyTypeOpen).Append(serviceType).Append(">("); + AppendFactoryCall(writer, registration, registration.LazyThreadSafetyMode, ref used); + + _ = writer.Append(RegisterOpen).Append(LazyTypeOpen).Append(serviceType).Append(">>(() => ").Append(LazyLocal).Append(index); + _ = AppendTrailingArgument(writer, registration.ContractValue).Line(");"); + + _ = writer.Append(RegisterOpen).Append(serviceType).Append(">(() => ").Append(LazyLocal).Append(index).Append(".Value"); + _ = AppendTrailingArgument(writer, registration.ContractValue).Line(");"); } - /// - /// Builds a comma-separated string of constructor arguments with resolved dependencies. - /// - /// The constructor parameters to generate arguments for. - /// The optional contract value for keyed resolution. - /// A comma-separated string of resolved dependency expressions. - internal static string GetConstructorArguments(EquatableArray parameters, string? contractValue) + /// Finishes a call whose first argument is the registration's factory. + /// The writer, after the call's opening parenthesis. + /// The registration. + /// The argument after the factory, as C# source; for none. + /// The throw helpers called so far, updated with those the factory calls. + /// + /// A factory with nothing to resolve stays on the call's line. Otherwise each argument takes its own line, one + /// level deeper, and the call closes after the last of them. + /// + internal static void AppendFactoryCall(SourceWriter writer, RegistrationInfo registration, string? lastArgument, ref ThrowHelpers used) { - if (parameters.Length == 0) + if (registration.ConstructorParameters.Length == 0 && registration.PropertyInjections.Length == 0) { - return string.Empty; + _ = writer.Append("() => new ").Append(registration.ConcreteTypeFullName).Append("()"); + _ = AppendTrailingArgument(writer, lastArgument).Line(");"); + return; } - var args = new string[parameters.Length]; - for (var i = 0; i < parameters.Length; i++) + AppendFactory(writer.OpenContinuation(), registration, ref used); + if (lastArgument is not null) { - var p = parameters[i]; - args[i] = GetResolutionString(p.TypeFullName, p.IsCollection, p.CollectionItemType, contractValue); + _ = writer.ArgumentSeparator().Append(lastArgument); } - return string.Join(", ", args); + _ = writer.CloseContinuation(");"); } - /// - /// Builds an object initializer string for property injections. - /// - /// The property injections to generate initializers for. - /// The optional contract value for keyed resolution. - /// An object initializer expression string, or empty if no properties. - internal static string GetPropertyInitializer(EquatableArray properties, string? contractValue) + /// Writes the lambda that constructs a registration's type, with its dependencies one per line. + /// The writer, at the start of a line. + /// The registration. + /// The throw helpers called so far, updated with those the factory calls. + /// Leaves the writer on the lambda's last line, for the caller to finish. + internal static void AppendFactory(SourceWriter writer, RegistrationInfo registration, ref ThrowHelpers used) { + var contract = registration.ContractValue; + _ = writer.Append("() => new ").Append(registration.ConcreteTypeFullName).Append('('); + + var parameters = registration.ConstructorParameters; + if (parameters.Length != 0) + { + _ = writer.OpenContinuation(); + for (var i = 0; i < parameters.Length; i++) + { + if (i != 0) + { + _ = writer.ArgumentSeparator(); + } + + AppendParameter(writer, parameters[i], contract, ref used); + } + + _ = writer.Outdent(); + } + + _ = writer.Append(')'); + + var properties = registration.PropertyInjections; if (properties.Length == 0) { - return string.Empty; + return; } - var props = new string[properties.Length]; + _ = writer.EndLine().OpenBlock(); for (var i = 0; i < properties.Length; i++) { - var p = properties[i]; - var resolution = GetResolutionString(p.TypeFullName, false, null, contractValue); - props[i] = $"{p.PropertyName} = {resolution}"; + var property = properties[i]; + _ = writer.Append(property.PropertyName).Append(" = "); + AppendService(writer, property.TypeFullName, contract, ref used); + _ = writer.ArgumentSeparator(); + } + + _ = writer.CloseBlockInline(); + } + + /// Writes the expression that resolves a constructor parameter. + /// The writer. + /// The parameter. + /// The registration's contract, as C# source; for none. + /// The throw helpers called so far, updated with the one this parameter calls. + /// A collection resolves to every registration, which may be none, so it never throws. + internal static void AppendParameter(SourceWriter writer, in ConstructorParameter parameter, string? contract, ref ThrowHelpers used) + { + if (parameter.Kind != DependencyKind.Collection) + { + AppendService(writer, parameter.TypeFullName, contract, ref used); + return; + } + + _ = writer.Append("resolver.GetServices<").Append(parameter.InnerTypeFullName!).Append(">("); + _ = contract is null ? writer.Append(')') : writer.Append(contract).Append(')'); + } + + /// Writes the expression that resolves one service, throwing when it is not registered. + /// The writer. + /// The fully qualified type of the service. + /// The registration's contract, as C# source; for none. + /// The throw helpers called so far, updated with the one this service calls. + internal static void AppendService(SourceWriter writer, string typeFullName, string? contract, ref ThrowHelpers used) + { + _ = writer.Append("resolver.GetService<").Append(typeFullName).Append(">("); + if (contract is null) + { + used |= ThrowHelpers.WithoutContract; + _ = writer.Append(") ?? ").Append(ThrowNotRegistered).Append('<').Append(typeFullName).Append(">(\"").Append(typeFullName).Append("\")"); + return; } - return $" {{ {string.Join(", ", props)} }}"; + used |= ThrowHelpers.WithContract; + _ = writer.Append(contract).Append(") ?? ").Append(ThrowNotRegistered).Append('<').Append(typeFullName).Append(">(\"") + .Append(typeFullName).Append("\", ").Append(contract).Append(')'); } - /// - /// Generates a resolver call expression for a single dependency. - /// - /// The fully qualified type name of the dependency. - /// Whether the parameter is a collection type. - /// The item type for collection parameters, or null. - /// The optional contract value for keyed resolution. - /// A resolver call expression string. - internal static string GetResolutionString(string typeFullName, bool isCollection, string? collectionItemType, string? contractValue) + /// Writes the throw helpers the registrations call, after the registration method. + /// The writer, at the class body's level. + /// The helpers the registrations call. + internal static void AppendThrowHelpers(SourceWriter writer, ThrowHelpers used) { - if (isCollection && collectionItemType is not null) + if ((used & ThrowHelpers.WithoutContract) != 0) { - return contractValue is not null - ? $"resolver.GetServices<{collectionItemType}>({contractValue})" - : $"resolver.GetServices<{collectionItemType}>()"; + _ = writer.BlankLine().Lines(ThrowNotRegisteredMethod); } - if (contractValue is not null) + if ((used & ThrowHelpers.WithContract) != 0) { - return $"resolver.GetService<{typeFullName}>({contractValue}) ?? throw new global::System.InvalidOperationException(\"Dependency '{typeFullName}' with contract \" + {contractValue} + \" not registered with Splat resolver.\")"; + _ = writer.BlankLine().Lines(ThrowNotRegisteredWithContractMethod); } + } + + /// Writes a trailing argument when there is one. + /// The writer, after the argument before it. + /// The argument, as C# source; for none. + /// The writer. + private static SourceWriter AppendTrailingArgument(SourceWriter writer, string? argument) => + argument is null ? writer : writer.Append(", ").Append(argument); - return $"resolver.GetService<{typeFullName}>() ?? throw new global::System.InvalidOperationException(\"Dependency '{typeFullName}' not registered with Splat resolver.\")"; + /// Separates a registration from the one before it with a blank line. + /// The writer, at the method body's level. + /// How many registrations have been written. + private static void SeparateRegistration(SourceWriter writer, int index) + { + if (index != 0) + { + _ = writer.BlankLine(); + } } } diff --git a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/MarkerSource.cs b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/MarkerSource.cs new file mode 100644 index 00000000..c484ab89 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/MarkerSource.cs @@ -0,0 +1,211 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +/// The fixed source every consumer gets: the marker methods and the injection attributes. +internal static class MarkerSource +{ + /// The assembly name of the source generator, used in GeneratedCodeAttribute. + private static readonly AssemblyName GeneratorAssemblyName = typeof(MarkerSource).Assembly.GetName(); + + /// Gets the marker methods and attributes, built once per generator load. + internal static string Text { get; } = $$""" + // + + #nullable enable annotations + #nullable disable warnings + + // Suppress warnings about [Obsolete] member usage in generated code. + #pragma warning disable CS0612, CS0618 + + namespace {{Constants.NamespaceName}} + { + /// + /// Provides extension methods for the Splat dependency injection source generator. + /// This class contains marker methods that are analyzed at compile-time to generate + /// dependency injection registrations. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{GeneratorAssemblyName.Name}}", "{{GeneratorAssemblyName.Version}}")] + internal static partial class {{Constants.ClassName}} + { + /// + /// Registers a transient dependency mapping from to . + /// A new instance of will be created each time is resolved. + /// + /// The interface or base type to register. + /// The concrete type that implements . + public static void Register() + { + } + + /// + /// Registers a transient dependency mapping from to with a contract. + /// A new instance of will be created each time is resolved with the specified contract. + /// + /// The interface or base type to register. + /// The concrete type that implements . + /// A unique string identifier to distinguish between multiple registrations of the same type. + public static void Register(string contract) + { + } + + /// + /// Registers a lazy singleton dependency mapping from to . + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The interface or base type to register. + /// The concrete type that implements . + public static void RegisterLazySingleton() + { + } + + /// + /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The interface or base type to register. + /// The concrete type that implements . + /// The specifying how the singleton should be initialized in multi-threaded scenarios. + public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) + { + } + + /// + /// Registers a lazy singleton dependency mapping from to with a contract. + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The interface or base type to register. + /// The concrete type that implements . + /// A unique string identifier to distinguish between multiple registrations of the same type. + public static void RegisterLazySingleton(string contract) + { + } + + /// + /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The interface or base type to register. + /// The concrete type that implements . + /// A unique string identifier to distinguish between multiple registrations of the same type. + /// The specifying how the singleton should be initialized in multi-threaded scenarios. + public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) + { + } + + /// + /// Registers a transient dependency for type . + /// A new instance of will be created each time it is resolved. + /// + /// The type to register. + public static void Register() + { + } + + + /// + /// Registers a transient dependency for type with a contract. + /// A new instance of will be created each time it is resolved with the specified contract. + /// + /// The type to register. + /// A unique string identifier to distinguish between multiple registrations of the same type. + public static void Register(string contract) + { + } + + /// + /// Registers a lazy singleton dependency for type . + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The type to register. + public static void RegisterLazySingleton() + { + } + + + /// + /// Registers a lazy singleton dependency for type with a contract. + /// A single instance of will be created on first resolution and reused for all subsequent resolutions. + /// + /// The type to register. + /// A unique string identifier to distinguish between multiple registrations of the same type. + public static void RegisterLazySingleton(string contract) + { + } + + /// + /// Registers a constant (singleton) instance of type with the dependency resolver. + /// This method is a proxy for . + /// + /// The type of the instance to register. Must be a reference type. + /// The instance to register as a constant. + public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); + + /// + /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. + /// This method is a proxy for . + /// + /// The type of the instance to register. Must be a reference type. + /// The instance to register as a constant. + /// A unique string identifier to distinguish between multiple registrations of the same type. + public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); + + /// + /// Initializes the dependency injection container by registering all dependencies with the default . + /// This method should be called once during application startup after all registration calls have been made. + /// + public static void SetupIOC() + { + SetupIOCInternal(Splat.AppLocator.GetLocator()); + } + + /// + /// Initializes the dependency injection container by registering all dependencies with the specified resolver. + /// This method should be called once during application startup after all registration calls have been made. + /// + /// The instance to register dependencies with. + public static void SetupIOC(Splat.IDependencyResolver resolver) + { + SetupIOCInternal(resolver); + } + + + static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); + } + + /// + /// Marks a property to be injected by the dependency injection engine. + /// Properties marked with this attribute will have their values automatically + /// resolved and set by the DI container during object construction. + /// + /// + /// The property must have an accessible setter (public, internal, or internal protected). + /// The property type must be registered in the DI container, or resolution will fail at runtime. + /// + [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] + internal sealed class DependencyInjectionPropertyAttribute : System.Attribute + { + } + + /// + /// Marks a constructor as the preferred constructor for dependency injection. + /// When a class has multiple constructors, this attribute specifies which constructor + /// the DI engine should use for object construction. + /// + /// + /// Only one constructor per class should be marked with this attribute. + /// If multiple constructors exist without this attribute, the analyzer will generate + /// diagnostic warning SPLATDI001. + /// The constructor must be accessible (public, internal, or internal protected). + /// + [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] + internal sealed class DependencyInjectionConstructorAttribute : System.Attribute + { + } + } + """; +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/PooledBuilder.cs b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/PooledBuilder.cs new file mode 100644 index 00000000..7f898b96 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/PooledBuilder.cs @@ -0,0 +1,65 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Text; + +namespace Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +/// Hands out reusable string builders so a generation pass reuses buffers instead of allocating per file. +/// +/// +/// Each generated file used to be built in its own fresh builder, so every pass allocated a builder and its grown +/// chunk chain and threw them away. Renting from a per-thread slot lets one pass reuse the buffer, and a builder that +/// has already grown to fit the registrations file starts large enough for the next pass. +/// +/// +/// Thread-static because source-output callbacks can run concurrently, and because renting must not need a lock to be +/// worth doing. A builder is only reused after hands it back, so two live rents never +/// share one. The generator writes one file at a time, so one slot per thread is enough. +/// +/// +internal static class PooledBuilder +{ + /// + /// The largest builder worth keeping. One outsized file would otherwise pin its whole chunk chain for the life of + /// the thread, which in a build host outlives the compilation that needed it. + /// + internal const int MaxRetainedCapacity = 256 * 1024; + + /// The builder this thread last handed back. + [ThreadStatic] + private static StringBuilder? _cached; + + /// Rents a builder, empty and ready to write. + /// The capacity the caller expects to need. + /// An empty builder. + internal static StringBuilder Rent(int capacity) + { + var cached = _cached; + if (cached is null) + { + return new(capacity); + } + + _cached = null; + _ = cached.EnsureCapacity(capacity); + return cached; + } + + /// Materializes a rented builder's content and hands the builder back for reuse. + /// The rented builder, which the caller must not touch afterwards. + /// The accumulated string. + internal static string ToStringAndReturn(StringBuilder builder) + { + var result = builder.ToString(); + if (builder.Capacity <= MaxRetainedCapacity) + { + _ = builder.Clear(); + _cached = builder; + } + + return result; + } +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriter.cs b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriter.cs new file mode 100644 index 00000000..1e8bc7f8 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriter.cs @@ -0,0 +1,207 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; +using System.Text; + +namespace Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +/// Writes generated C# source, tracking the indentation level so emitters never spell it out. +/// +/// +/// The writer owns the layout rules: a line is indented when its first character is written, a blank line carries no +/// trailing whitespace, and every line ends with \n. Emitters say what they write - a line, a block, a nested +/// argument list - and the level follows from the structure, so a fragment written by one emitter lands at the right +/// depth whichever emitter called it. +/// +/// +/// The text accumulates in a , which grows in chunks rather than by copying. Indentation +/// comes from a table of precomputed strings, so indenting a line is one append. Names are appended straight from the +/// model's strings, so no intermediate string is built for a line. +/// +/// +/// A writer is used by one source-output callback at a time and never outlives it. takes its +/// builder from 's per-thread slot. Nothing a writer holds reaches a pipeline model, so it +/// has no bearing on incremental caching. +/// +/// +internal sealed class SourceWriter +{ + /// The number of spaces one indentation level adds. + internal const int IndentWidth = 4; + + /// The number of indentation levels served from the precomputed table. + internal const int CachedIndentLevels = 16; + + /// The indentation for each level, indexed by level. + private static readonly string[] Indents = BuildIndents(); + + /// The builder the text accumulates in. + private readonly StringBuilder _builder; + + /// The length of the text when the current line began; equal to the length while nothing is on it. + private int _lineStart; + + /// Initializes a new instance of the class over an empty builder. + /// The builder to write into. + private SourceWriter(StringBuilder builder) => _builder = builder; + + /// Gets the current indentation level. + internal int Level { get; private set; } + + /// Materializes the text written so far, leaving the writer usable. + /// The accumulated text. + public override string ToString() => _builder.ToString(); + + /// Rents an empty writer at level zero, over a builder from the thread's pool. + /// The capacity the caller expects to need. + /// An empty writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static SourceWriter Rent(int capacity) => new(PooledBuilder.Rent(capacity)); + + /// Materializes the text and hands the builder back for reuse. + /// The accumulated text. + /// The caller must not touch the writer afterwards. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal string ToStringAndReturn() => PooledBuilder.ToStringAndReturn(_builder); + + /// Moves one level deeper. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter Indent() + { + Level++; + return this; + } + + /// Moves one level shallower. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter Outdent() + { + Level--; + return this; + } + + /// Writes text, indenting it when it starts a line. + /// The text, which must not contain a line break. + /// This writer. + internal SourceWriter Append(string text) + { + StartLine(); + _ = _builder.Append(text); + return this; + } + + /// Writes one character, indenting it when it starts a line. + /// The character, which must not be a line break. + /// This writer. + internal SourceWriter Append(char value) + { + StartLine(); + _ = _builder.Append(value); + return this; + } + + /// Writes the invariant decimal rendering of an integer. + /// The value, which is never negative. + /// This writer. + internal SourceWriter Append(int value) + { + StartLine(); + _ = _builder.Append(value); + return this; + } + + /// Ends the current line; at the start of a line, writes a blank one. + /// This writer. + internal SourceWriter EndLine() + { + _ = _builder.Append('\n'); + _lineStart = _builder.Length; + return this; + } + + /// Writes text and ends the line. + /// The text, which must not contain a line break. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter Line(string text) => Append(text).EndLine(); + + /// Writes a block of lines, each at the current level plus the indentation it carries itself. + /// The lines, separated by \n or \r\n; the last line need not be terminated. + /// This writer. + /// + /// For fixed text written as a raw string literal. The literal's own indentation is relative to the level it is + /// written at, so the same block reads correctly wherever an emitter places it. An empty line stays empty. + /// + internal SourceWriter Lines(string block) + { + var start = 0; + while (start < block.Length) + { + var end = block.IndexOf('\n', start); + var next = end < 0 ? block.Length : end + 1; + var contentEnd = end < 0 ? block.Length : end; + if (contentEnd > start && block[contentEnd - 1] == '\r') + { + contentEnd--; + } + + if (contentEnd > start) + { + StartLine(); + _ = _builder.Append(block, start, contentEnd - start); + } + + _ = EndLine(); + start = next; + } + + return this; + } + + /// Opens a brace block on its own line and moves one level deeper. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter OpenBlock() => Line("{").Indent(); + + /// Moves one level shallower and closes the brace block on its own line. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter CloseBlock() => Outdent().Line("}"); + + /// Moves one level shallower and writes the closing brace, leaving the line open. + /// This writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter CloseBlockInline() => Outdent().Append('}'); + + /// Builds the indentation table. + /// The indentation for each cached level. + private static string[] BuildIndents() + { + var indents = new string[CachedIndentLevels]; + for (var i = 0; i < indents.Length; i++) + { + indents[i] = new(' ', i * IndentWidth); + } + + return indents; + } + + /// Writes the indentation when nothing has been written on the current line yet. + /// + /// A line that has started is longer than its start, so the test needs no flag of its own. At level zero the + /// indentation is empty, so the table's first entry writes nothing. The registration file nests six levels at + /// most, so every level is served from the table. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void StartLine() + { + if (_builder.Length == _lineStart) + { + _ = _builder.Append(Indents[Level]); + } + } +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriterExtensions.cs b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriterExtensions.cs new file mode 100644 index 00000000..5a09e334 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/CodeGeneration/SourceWriterExtensions.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; + +namespace Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +/// The C# constructs generated code is built from, each written through a . +/// +/// Each member names one construct and writes its fixed text and its level changes, so an emitter says what it builds +/// and the layout follows from the writer's level. +/// +internal static class SourceWriterExtensions +{ + /// Writes C# constructs through a writer. + /// The writer the construct is written to. + extension(SourceWriter writer) + { + /// Opens a block-scoped namespace, the form every language version parses. + /// The namespace. + /// The writer, one level deeper. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter OpenNamespace(string namespaceName) => + writer.Append("namespace ").Line(namespaceName).OpenBlock(); + + /// Writes a blank line. + /// The writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter BlankLine() => writer.EndLine(); + + /// Ends the line and moves one level deeper, for the continuation lines of an expression. + /// The writer, one level deeper. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter OpenContinuation() => writer.EndLine().Indent(); + + /// Finishes the last continuation line and moves back to the level the expression began at. + /// What ends the line, such as );. + /// The writer, one level shallower. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter CloseContinuation(string trailer) => writer.Line(trailer).Outdent(); + + /// Writes a separating comma and ends the line, for an argument that is followed by another. + /// The writer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal SourceWriter ArgumentSeparator() => writer.Line(","); + } +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/Constants.cs b/src/Splat.DependencyInjection.SourceGenerator/Constants.cs index 8d997551..07acb1da 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Constants.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Constants.cs @@ -1,15 +1,11 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using System.Reflection; - namespace Splat.DependencyInjection.SourceGenerator; -/// -/// Constants used throughout the source generator for attribute names, method names, -/// type names, and generated file names. -/// +/// The names the generator and the analyzers match against, and the names of the generated files. +/// Linked into the analyzer project, so it holds constants only. internal static class Constants { /// The class name of the SplatRegistrations marker class. @@ -21,9 +17,6 @@ internal static class Constants /// Fully qualified display string for the DependencyInjectionConstructorAttribute. public const string ConstructorAttribute = "global::Splat.DependencyInjectionConstructorAttribute"; - /// Fully qualified display string for the DependencyInjectionPropertyAttribute. - public const string PropertyAttribute = "global::Splat.DependencyInjectionPropertyAttribute"; - /// Metadata name for resolving the DependencyInjectionConstructorAttribute via compilation. public const string ConstructorAttributeMetadataName = "Splat.DependencyInjectionConstructorAttribute"; @@ -45,244 +38,18 @@ internal static class Constants /// Parameter name for the thread safety mode in lazy singleton methods. public const string ParameterNameMode = "mode"; - /// Fully qualified display string for the open generic type. - public const string LazyOpenGenericTypeName = "global::System.Lazy"; - /// Metadata name for resolving via compilation. public const string LazyMetadataName = "System.Lazy`1"; - /// Fully qualified display string for the open generic IEnumerable type. - public const string EnumerableOpenGenericTypeName = "global::System.Collections.Generic.IEnumerable"; - /// Metadata name for resolving IEnumerable via compilation. public const string EnumerableMetadataName = "System.Collections.Generic.IEnumerable`1"; - /// File name for the generated EmbeddedAttribute source. - public const string EmbeddedAttributeFileName = "Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs"; + /// Metadata name for resolving via compilation. + public const string LazyThreadSafetyModeMetadataName = "System.Threading.LazyThreadSafetyMode"; /// File name for the generated marker methods and attributes source. public const string ExtensionMethodFileName = "Splat.DI.g.cs"; /// File name for the generated registration implementation source. public const string RegistrationFileName = "Splat.DI.Reg.g.cs"; - - /// The assembly name of the source generator, used in GeneratedCodeAttribute. - private static readonly AssemblyName _assemblyName = typeof(Constants).Assembly.GetName(); - - public static string ExtensionMethodText => $$""" - // - - #nullable enable annotations - #nullable disable warnings - - // Suppress warnings about [Obsolete] member usage in generated code. - #pragma warning disable CS0612, CS0618 - - namespace {{NamespaceName}} - { - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{_assemblyName.Name}}", "{{_assemblyName.Version}}")] - internal static partial class {{ClassName}} - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } - } - """; - - // EmbeddedAttribute definition - prevents conflicts with InternalsVisibleTo - public static string EmbeddedAttributeText => $$""" - // - - #nullable enable annotations - #nullable disable warnings - - // Suppress warnings about [Obsolete] member usage in generated code. - #pragma warning disable CS0612, CS0618 - - namespace Microsoft.CodeAnalysis - { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{_assemblyName.Name}}", "{{_assemblyName.Version}}")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } - } - """; } diff --git a/src/Splat.DependencyInjection.SourceGenerator/DiagnosticWarnings.cs b/src/Splat.DependencyInjection.SourceGenerator/DiagnosticWarnings.cs index 7cc91362..f57e2d6e 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/DiagnosticWarnings.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/DiagnosticWarnings.cs @@ -1,19 +1,15 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using Microsoft.CodeAnalysis; namespace Splat.DependencyInjection.SourceGenerator; -/// -/// Diagnostic descriptors for Splat DI source generator and analyzer. -/// +/// Diagnostic descriptors for Splat DI source generator and analyzer. public static class DiagnosticWarnings { - /// - /// SPLATDI001: Class has multiple constructors without DependencyInjectionConstructorAttribute. - /// + /// SPLATDI001: Class has multiple constructors without DependencyInjectionConstructorAttribute. public static readonly DiagnosticDescriptor MultipleConstructorNeedAttribute = new( "SPLATDI001", "Can't find valid constructor", @@ -22,9 +18,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Error, true); - /// - /// SPLATDI002: Property marked with DependencyInjectionPropertyAttribute must have public or internal setter. - /// + /// SPLATDI002: Property marked with DependencyInjectionPropertyAttribute must have public or internal setter. public static readonly DiagnosticDescriptor PropertyMustPublicBeSettable = new( "SPLATDI002", "Property must be public/internal settable", @@ -33,9 +27,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Error, true); - /// - /// SPLATDI003: Multiple constructors marked with DependencyInjectionConstructorAttribute. - /// + /// SPLATDI003: Multiple constructors marked with DependencyInjectionConstructorAttribute. public static readonly DiagnosticDescriptor MultipleConstructorsMarked = new( "SPLATDI003", "Multiple constructors have DependencyInjectionConstructorAttribute", @@ -44,9 +36,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Error, true); - /// - /// SPLATDI004: Constructor marked with DependencyInjectionConstructorAttribute must be public or internal. - /// + /// SPLATDI004: Constructor marked with DependencyInjectionConstructorAttribute must be public or internal. public static readonly DiagnosticDescriptor ConstructorsMustBePublic = new( "SPLATDI004", "Constructors not public or internal", @@ -55,9 +45,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Error, true); - /// - /// SPLATDI005: Constructor parameters must not have circular dependencies. - /// + /// SPLATDI005: Constructor parameters must not have circular dependencies. public static readonly DiagnosticDescriptor ConstructorsMustNotHaveCircularDependency = new( "SPLATDI005", "Constructors must not have a circular dependency", @@ -66,9 +54,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Error, true); - /// - /// SPLATDI006: Interface has been registered multiple times. - /// + /// SPLATDI006: Interface has been registered multiple times. public static readonly DiagnosticDescriptor InterfaceRegisteredMultipleTimes = new( "SPLATDI006", "Interface has been registered before", @@ -77,9 +63,7 @@ public static class DiagnosticWarnings DiagnosticSeverity.Warning, true); - /// - /// SPLATDI007: Constructor has a lazy parameter that is not registered with RegisterLazySingleton. - /// + /// SPLATDI007: Constructor has a lazy parameter that is not registered with RegisterLazySingleton. public static readonly DiagnosticDescriptor LazyParameterNotRegisteredLazy = new( "SPLATDI007", "Constructor has a lazy parameter", diff --git a/src/Splat.DependencyInjection.SourceGenerator/Generator.cs b/src/Splat.DependencyInjection.SourceGenerator/Generator.cs index eb13c0cd..5cd198ec 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Generator.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Generator.cs @@ -1,83 +1,80 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; -using System.Text; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; using Splat.DependencyInjection.SourceGenerator.CodeGeneration; using Splat.DependencyInjection.SourceGenerator.Models; namespace Splat.DependencyInjection.SourceGenerator; -/// -/// Incremental generator for Splat dependency injection registrations. -/// +/// Generates the Splat registrations the marker calls in a project describe. +/// +/// +/// One syntax provider finds the calls to both marker methods, so each syntax node is tested once. The transform turns +/// each call into a , which holds values only and so compares by value. +/// +/// +/// The pipeline then splits. The generated code is built from the registrations alone, without their locations, so an +/// edit that only moves a registration leaves the file cached and nothing is regenerated. The graph diagnostics need +/// the locations, and are reported from their own output. +/// +/// [Generator] -public class Generator : IIncrementalGenerator +public sealed class Generator : IIncrementalGenerator { + /// The tracking name of the step that extracts each call's registration and location. + internal const string SitesStep = "RegistrationSites"; + + /// The tracking name of the step that drops the locations, leaving what the generated code needs. + internal const string RegistrationsStep = "Registrations"; + + /// The tracking name of the step that gathers the registrations for the file. + internal const string CollectedRegistrationsStep = "CollectedRegistrations"; + /// public void Initialize(IncrementalGeneratorInitializationContext context) { - // Always emit attributes and marker methods (per Cookbook best practices) - context.RegisterPostInitializationOutput(ctx => + context.RegisterPostInitializationOutput(static postInitializationContext => { - // Emit EmbeddedAttribute first to avoid conflicts with InternalsVisibleTo - ctx.AddSource( - Constants.EmbeddedAttributeFileName, - SourceText.From(Constants.EmbeddedAttributeText, Encoding.UTF8)); - - // Emit marker attributes and extension methods - ctx.AddSource( - Constants.ExtensionMethodFileName, - SourceText.From(Constants.ExtensionMethodText, Encoding.UTF8)); + postInitializationContext.AddEmbeddedAttributeDefinition(); + postInitializationContext.AddSource(Constants.ExtensionMethodFileName, MarkerSource.Text); }); - // Pipeline 1: Register() calls - var registerCalls = context.SyntaxProvider + var sites = context.SyntaxProvider .CreateSyntaxProvider( - predicate: RoslynHelpers.IsRegisterInvocation, - transform: MetadataExtractor.ExtractRegisterMetadata) - .Where(x => x is not null) - .Select((x, _) => x!); + predicate: static (node, _) => RoslynHelpers.IsRegistrationInvocation(node), + transform: MetadataExtractor.Extract) + .WithTrackingName(SitesStep) + .Where(static site => site is not null); - // Pipeline 2: RegisterLazySingleton() calls - var lazySingletonCalls = context.SyntaxProvider - .CreateSyntaxProvider( - predicate: RoslynHelpers.IsRegisterLazySingletonInvocation, - transform: MetadataExtractor.ExtractLazySingletonMetadata) - .Where(x => x is not null) - .Select((x, _) => x!); - - // Combine all registrations - var allRegistrations = registerCalls + var registrations = sites + .Select(static (site, _) => site!.Registration) + .WithTrackingName(RegistrationsStep) .Collect() - .Combine(lazySingletonCalls.Collect()); + .WithTrackingName(CollectedRegistrationsStep); - // Generate output with validation - context.RegisterSourceOutput(allRegistrations, GenerateCode); + context.RegisterSourceOutput(sites.Collect(), RegistrationValidator.ReportDiagnostics); + context.RegisterSourceOutput(registrations, GenerateCode); } - /// - /// Generates the source output for all collected registrations. - /// - /// The source production context for emitting generated source. - /// The combined transient and lazy singleton registration data. - private static void GenerateCode( - SourceProductionContext context, - (ImmutableArray Transients, ImmutableArray LazySingletons) data) + /// Writes the registrations file. + /// The context the file is added to. + /// The registrations, in source order. + /// + /// With no registrations the file is left out: SetupIOCInternal is a partial method with no body, so the + /// compiler removes the calls to it. + /// + internal static void GenerateCode(SourceProductionContext context, ImmutableArray registrations) { - var (transients, lazySingletons) = data; - - // Report graph-level diagnostics that the per-type analyzers cannot detect - // (SPLATDI005 circular dependencies, SPLATDI006 duplicate registrations, SPLATDI007 lazy). - RegistrationValidator.ReportDiagnostics(context, transients, lazySingletons); + if (registrations.IsEmpty) + { + return; + } - // Generate code only for valid registrations (invalid ones were filtered out in transform) - var code = CodeGenerator.GenerateSetupIOCMethod(transients, lazySingletons); - context.AddSource(Constants.RegistrationFileName, SourceText.From(code, Encoding.UTF8)); + context.AddSource(Constants.RegistrationFileName, CodeGenerator.Generate(registrations)); } -} \ No newline at end of file +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/IsExternalInit.cs b/src/Splat.DependencyInjection.SourceGenerator/IsExternalInit.cs deleted file mode 100644 index a934098c..00000000 --- a/src/Splat.DependencyInjection.SourceGenerator/IsExternalInit.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace System.Runtime.CompilerServices; - -/// -/// Reserved to be used by the compiler for tracking metadata. -/// This class should not be used by developers in source code. -/// -[ExcludeFromCodeCoverage] -[EditorBrowsable(EditorBrowsableState.Never)] -internal static class IsExternalInit; diff --git a/src/Splat.DependencyInjection.SourceGenerator/MetadataExtractor.cs b/src/Splat.DependencyInjection.SourceGenerator/MetadataExtractor.cs index d68c3600..3665f658 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/MetadataExtractor.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/MetadataExtractor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Generic; @@ -14,411 +14,364 @@ namespace Splat.DependencyInjection.SourceGenerator; -/// -/// Extracts metadata from Roslyn symbols for DI registration. -/// +/// Turns a bound marker call into the value-only model the rest of the pipeline works from. +/// +/// Binding a call is the costliest thing a transform does, so each check that can turn a call away without binding it +/// runs first, and each name is read from a symbol at most once. +/// internal static class MetadataExtractor { - /// - /// The fully qualified symbol display format used for type name extraction. - /// - private static readonly SymbolDisplayFormat _fullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat; - - /// - /// Cache for well-known symbols keyed by compilation instance. - /// Uses weak references to compilation keys to prevent memory leaks. - /// - private static readonly ConditionalWeakTable _symbolsCache = new(); - - /// - /// Extracts metadata for a Register call. Resolves the method symbol from the generator - /// syntax context and delegates to . - /// - /// The generator syntax context. - /// The cancellation token. - /// Transient registration info or null. - internal static TransientRegistrationInfo? ExtractRegisterMetadata( - GeneratorSyntaxContext context, - CancellationToken ct) + /// The fully qualified name of a lazy before its type argument. + private const string LazyPrefix = "global::System.Lazy<"; + + /// The fully qualified name of a collection before its type argument. + private const string EnumerablePrefix = "global::System.Collections.Generic.IEnumerable<"; + + /// The fully qualified members, indexed by value. + private static readonly string[] LazyThreadSafetyModeNames = + [ + "global::System.Threading.LazyThreadSafetyMode.None", + "global::System.Threading.LazyThreadSafetyMode.PublicationOnly", + "global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication", + ]; + + /// Extracts the registration a marker call makes; the pipeline's transform. + /// The call and its semantic model. + /// The cancellation token. + /// The registration and where it is made, or when the call is not a valid registration. + internal static RegistrationSite? Extract(GeneratorSyntaxContext context, CancellationToken cancellationToken) { var invocation = (InvocationExpressionSyntax)context.Node; var semanticModel = context.SemanticModel; - if (semanticModel.GetSymbolInfo(invocation, ct).Symbol is not IMethodSymbol methodSymbol) + if (invocation.Expression is MemberAccessExpressionSyntax memberAccess + && !IsRegistrationsReceiver(memberAccess.Expression, semanticModel, cancellationToken)) { return null; } - var symbols = ResolveWellKnownSymbols(semanticModel.Compilation); - return ExtractRegisterMetadataFromSymbol(methodSymbol, invocation, semanticModel, symbols, ct); + if (semanticModel.GetSymbolInfo(invocation, cancellationToken).Symbol is not IMethodSymbol method + || !RoslynHelpers.IsSplatRegistrationsMethod(method)) + { + return null; + } + + var registration = ExtractRegistration(method, invocation, semanticModel, WellKnownSymbols.For(semanticModel.Compilation), cancellationToken); + return registration is null ? null : new(registration, LocationInfo.From(invocation)); } - /// - /// Extracts metadata for a Register call from a resolved method symbol. - /// - /// The resolved method symbol. - /// The invocation expression syntax. + /// Tests whether the receiver of a call names the SplatRegistrations class. + /// The expression before the call's name. /// The semantic model. - /// Pre-resolved well-known symbols for efficient comparison. - /// The cancellation token. - /// Transient registration info or null. - internal static TransientRegistrationInfo? ExtractRegisterMetadataFromSymbol( - IMethodSymbol methodSymbol, + /// The cancellation token. + /// when the receiver could be the class. + /// + /// A receiver spelled SplatRegistrations is accepted from syntax. Anything else - a using alias, or a + /// resolver variable in a call to Splat's own Register - binds on its own, which is far cheaper than binding + /// the whole call with its overloads and type inference. + /// + internal static bool IsRegistrationsReceiver(ExpressionSyntax receiver, SemanticModel semanticModel, CancellationToken cancellationToken) => + receiver is IdentifierNameSyntax { Identifier.ValueText: Constants.ClassName } + or MemberAccessExpressionSyntax { Name.Identifier.ValueText: Constants.ClassName } + || semanticModel.GetSymbolInfo(receiver, cancellationToken).Symbol is INamedTypeSymbol { Name: Constants.ClassName }; + + /// Extracts the registration a bound marker call makes. + /// The bound marker method. + /// The call. + /// The semantic model. + /// The compilation's well-known symbols. + /// The cancellation token. + /// The registration, or when the type cannot be constructed or injected. + internal static RegistrationInfo? ExtractRegistration( + IMethodSymbol method, InvocationExpressionSyntax invocation, SemanticModel semanticModel, WellKnownSymbols symbols, - CancellationToken ct) + CancellationToken cancellationToken) { - if (!RoslynHelpers.IsSplatRegistrationsMethod(methodSymbol, Constants.MethodNameRegister)) - { - return null; - } - - var numberTypeParameters = methodSymbol.TypeArguments.Length; - if (numberTypeParameters is 0 or > 2) - { - return null; - } - - var interfaceType = methodSymbol.TypeArguments[0]; - var concreteType = numberTypeParameters == 2 - ? methodSymbol.TypeArguments[1] - : interfaceType; + var typeArguments = method.TypeArguments; + var concreteType = typeArguments[typeArguments.Length - 1]; - var constructorParams = ExtractConstructorParameters(concreteType, symbols); - if (constructorParams == null) + if (!TryExtractConstructorParameters(concreteType, symbols, out var constructorParameters) + || !TryExtractPropertyInjections(concreteType, symbols, out var propertyInjections)) { return null; } - var propertyInjections = ExtractPropertyInjections(concreteType, symbols.PropertyAttribute); - if (propertyInjections == null) - { - return null; - } - - var contractValue = RoslynHelpers.ExtractContractParameter(methodSymbol, invocation, semanticModel, ct); - - return new TransientRegistrationInfo( - InterfaceTypeFullName: interfaceType.ToDisplayString(_fullyQualifiedFormat), - ConcreteTypeFullName: concreteType.ToDisplayString(_fullyQualifiedFormat), - ConstructorParameters: new EquatableArray(constructorParams), - PropertyInjections: new EquatableArray(propertyInjections), - ContractValue: contractValue, - InvocationLocation: invocation.GetLocation()); + ExtractArguments(method, invocation.ArgumentList.Arguments, semanticModel, symbols, cancellationToken, out var contract, out var mode); + + var serviceTypeName = DisplayName(typeArguments[0]); + return new( + method.Name == Constants.MethodNameRegister ? RegistrationKind.Transient : RegistrationKind.LazySingleton, + serviceTypeName, + typeArguments.Length == 1 ? serviceTypeName : DisplayName(concreteType), + constructorParameters, + propertyInjections, + contract, + mode); } - /// - /// Extracts metadata for a RegisterLazySingleton call. Resolves the method symbol from the generator - /// syntax context and delegates to . - /// - /// The generator syntax context. - /// The cancellation token. - /// Lazy singleton registration info or null. - internal static LazySingletonRegistrationInfo? ExtractLazySingletonMetadata( - GeneratorSyntaxContext context, - CancellationToken ct) + /// Extracts the parameters of the constructor a registration calls. + /// The type constructed. + /// The compilation's well-known symbols. + /// The parameters, when a constructor can be called. + /// when no single accessible constructor can be chosen. + /// + /// Constructors are looked up by name, which a type answers from its member table without building a list of + /// every member. A type with one constructor uses it; a type with several uses the one marked + /// [DependencyInjectionConstructor]. The analyzers report the types this turns away. + /// + internal static bool TryExtractConstructorParameters(ITypeSymbol concreteType, WellKnownSymbols symbols, out EquatableArray parameters) { - var invocation = (InvocationExpressionSyntax)context.Node; - var semanticModel = context.SemanticModel; + parameters = EquatableArray.Empty; + var constructors = concreteType.GetMembers(WellKnownMemberNames.InstanceConstructorName); - if (semanticModel.GetSymbolInfo(invocation, ct).Symbol is not IMethodSymbol methodSymbol) + if (constructors.IsEmpty) { - return null; + return true; } - var symbols = ResolveWellKnownSymbols(semanticModel.Compilation); - return ExtractLazySingletonMetadataFromSymbol(methodSymbol, invocation, semanticModel, symbols, ct); - } + var constructor = constructors.Length == 1 + ? (IMethodSymbol)constructors[0] + : FindMarkedConstructor(concreteType, constructors, symbols); - /// - /// Extracts metadata for a RegisterLazySingleton call from a resolved method symbol. - /// - /// The resolved method symbol. - /// The invocation expression syntax. - /// The semantic model. - /// Pre-resolved well-known symbols for efficient comparison. - /// The cancellation token. - /// Lazy singleton registration info or null. - internal static LazySingletonRegistrationInfo? ExtractLazySingletonMetadataFromSymbol( - IMethodSymbol methodSymbol, - InvocationExpressionSyntax invocation, - SemanticModel semanticModel, - WellKnownSymbols symbols, - CancellationToken ct) - { - if (!RoslynHelpers.IsSplatRegistrationsMethod(methodSymbol, Constants.MethodNameRegisterLazySingleton)) - { - return null; - } - - var numberTypeParameters = methodSymbol.TypeArguments.Length; - if (numberTypeParameters is 0 or > 2) + if (constructor is null || constructor.DeclaredAccessibility < Accessibility.Internal) { - return null; + return false; } - var interfaceType = methodSymbol.TypeArguments[0]; - var concreteType = numberTypeParameters == 2 - ? methodSymbol.TypeArguments[1] - : interfaceType; - - var constructorParams = ExtractConstructorParameters(concreteType, symbols); - if (constructorParams == null) + var constructorParameters = constructor.Parameters; + if (constructorParameters.IsEmpty) { - return null; + return true; } - var propertyInjections = ExtractPropertyInjections(concreteType, symbols.PropertyAttribute); - if (propertyInjections == null) + var extracted = new ConstructorParameter[constructorParameters.Length]; + for (var i = 0; i < extracted.Length; i++) { - return null; + extracted[i] = CreateParameter(constructorParameters[i].Type, symbols); } - var contractValue = RoslynHelpers.ExtractContractParameter(methodSymbol, invocation, semanticModel, ct); - var lazyMode = RoslynHelpers.ExtractLazyThreadSafetyMode(methodSymbol, invocation, semanticModel, ct); - - return new LazySingletonRegistrationInfo( - InterfaceTypeFullName: interfaceType.ToDisplayString(_fullyQualifiedFormat), - ConcreteTypeFullName: concreteType.ToDisplayString(_fullyQualifiedFormat), - ConstructorParameters: new EquatableArray(constructorParams), - PropertyInjections: new EquatableArray(propertyInjections), - ContractValue: contractValue, - LazyThreadSafetyMode: lazyMode, - InvocationLocation: invocation.GetLocation()); + parameters = new(extracted); + return true; } - /// - /// Extracts constructor parameters for a type. - /// - /// The type to extract from. - /// Pre-resolved well-known symbols for efficient comparison. - /// Array of constructor parameters or null. - internal static ConstructorParameter[]? ExtractConstructorParameters(ITypeSymbol concreteType, WellKnownSymbols symbols) + /// Finds the one constructor marked [DependencyInjectionConstructor]. + /// The type the constructors belong to. + /// The type's instance constructors. + /// The compilation's well-known symbols. + /// The marked constructor, or when none or several are marked. + /// + /// The attribute is internal and embedded, so only a type compiled here can carry it. A type from a reference is + /// turned away without decoding the attributes of its constructors. + /// + internal static IMethodSymbol? FindMarkedConstructor(ITypeSymbol concreteType, ImmutableArray constructors, WellKnownSymbols symbols) { - var members = concreteType.GetMembers(); - var constructors = new List(capacity: 4); - - for (var i = 0; i < members.Length; i++) + var attribute = symbols.ConstructorAttribute; + if (attribute is null || !SymbolEqualityComparer.Default.Equals(concreteType.ContainingAssembly, symbols.SourceAssembly)) { - if (members[i] is IMethodSymbol { MethodKind: MethodKind.Constructor, IsStatic: false } ctor) - { - constructors.Add(ctor); - } + return null; } - var constructorCount = constructors.Count; - IMethodSymbol? selectedConstructor = null; - - if (constructorCount == 1) + IMethodSymbol? marked = null; + foreach (var constructor in constructors) { - selectedConstructor = constructors[0]; - } - else if (constructorCount > 1) - { - for (var i = 0; i < constructorCount; i++) + if (!HasAttribute(constructor, attribute)) { - var constructor = constructors[i]; - if (HasAttribute(constructor, symbols.ConstructorAttribute, Constants.ConstructorAttribute)) - { - if (selectedConstructor != null) - { - return null; - } - - selectedConstructor = constructor; - } + continue; } - if (selectedConstructor == null) + if (marked is not null) { return null; } - } - if (selectedConstructor == null) - { - return []; + marked = (IMethodSymbol)constructor; } - if (selectedConstructor.DeclaredAccessibility < Accessibility.Internal) + return marked; + } + + /// Extracts the properties marked [DependencyInjectionProperty] on a type and its base types. + /// The type constructed. + /// The compilation's well-known symbols. + /// The properties, when every marked one can be set. + /// when a marked property has no setter the generated code can call. + /// + /// The walk stops at the first base type from a reference: the attribute is internal and embedded, so no type + /// compiled elsewhere carries this compilation's copy, and its members need never be loaded. The list is only + /// allocated once a property is found; most types have none. + /// + internal static bool TryExtractPropertyInjections(ITypeSymbol concreteType, WellKnownSymbols symbols, out EquatableArray properties) + { + properties = EquatableArray.Empty; + var attribute = symbols.PropertyAttribute; + if (attribute is null) { - return null; + return true; } - var parameters = new List(selectedConstructor.Parameters.Length); - foreach (var param in selectedConstructor.Parameters) + List? found = null; + for (var type = concreteType; type is not null && SymbolEqualityComparer.Default.Equals(type.ContainingAssembly, symbols.SourceAssembly); type = type.BaseType) { - var paramType = param.Type; - var paramTypeName = paramType.ToDisplayString(_fullyQualifiedFormat); - - bool isLazy = false; - string? lazyInnerType = null; - - if (paramType is INamedTypeSymbol namedType && - IsOriginalDefinition(namedType, symbols.LazyType, Constants.LazyOpenGenericTypeName)) + foreach (var member in type.GetMembers()) { - isLazy = true; - if (namedType.TypeArguments.Length > 0) + if (member is not IPropertySymbol property || !HasAttribute(property, attribute)) { - lazyInnerType = namedType.TypeArguments[0].ToDisplayString(_fullyQualifiedFormat); + continue; } - } - bool isCollection = false; - string? collectionItemType = null; - - if (paramType is INamedTypeSymbol namedCollType && - IsOriginalDefinition(namedCollType, symbols.EnumerableType, Constants.EnumerableOpenGenericTypeName)) - { - isCollection = true; - if (namedCollType.TypeArguments.Length > 0) + if (property.SetMethod is not { DeclaredAccessibility: >= Accessibility.Internal }) { - collectionItemType = namedCollType.TypeArguments[0].ToDisplayString(_fullyQualifiedFormat); + return false; } + + (found ??= []).Add(new(property.Name, DisplayName(property.Type))); } + } - parameters.Add(new ConstructorParameter( - ParameterName: param.Name, - TypeFullName: paramTypeName, - IsLazy: isLazy, - LazyInnerType: lazyInnerType, - IsCollection: isCollection, - CollectionItemType: collectionItemType)); + if (found is not null) + { + properties = new(found.ToArray()); } - return parameters.ToArray(); + return true; } - /// - /// Extracts property injections for a type. - /// - /// The type to extract from. - /// Pre-resolved property attribute symbol for efficient comparison. - /// Array of property injections or null. - internal static PropertyInjection[]? ExtractPropertyInjections(ITypeSymbol concreteType, INamedTypeSymbol? propertyAttributeSymbol) + /// Reads the contract and thread safety mode a marker call passes. + /// The bound marker method. + /// The call's arguments. + /// The semantic model. + /// The compilation's well-known symbols. + /// The cancellation token. + /// The contract, as C# source; for none. + /// The thread safety mode, as C# source; for none. + internal static void ExtractArguments( + IMethodSymbol method, + SeparatedSyntaxList arguments, + SemanticModel semanticModel, + WellKnownSymbols symbols, + CancellationToken cancellationToken, + out string? contract, + out string? mode) { - var properties = new List(capacity: 4); - var allTypes = RoslynHelpers.GetBaseTypesAndThis(concreteType); - - foreach (var type in allTypes) + contract = null; + mode = null; + for (var i = 0; i < arguments.Count; i++) { - foreach (var member in type.GetMembers()) + var argument = arguments[i]; + var parameterName = RoslynHelpers.GetParameterName(argument, method, i); + if (parameterName == Constants.ParameterNameContract) { - if (member is not IPropertySymbol property) - { - continue; - } - - if (!HasAttribute(property, propertyAttributeSymbol, Constants.PropertyAttribute)) - { - continue; - } - - if (property.SetMethod == null || property.SetMethod.DeclaredAccessibility < Accessibility.Internal) - { - return null; - } - - properties.Add(new PropertyInjection( - PropertyName: property.Name, - TypeFullName: property.Type.ToDisplayString(_fullyQualifiedFormat), - PropertyLocation: GetFirstLocation(property.Locations))); + contract = ExtractContract(argument.Expression, semanticModel, cancellationToken); + } + else if (parameterName == Constants.ParameterNameMode) + { + mode = ExtractMode(argument.Expression, semanticModel, symbols, cancellationToken); } } + } - return properties.ToArray(); + /// Reads a contract argument as C# source that compiles in the generated file. + /// The argument. + /// The semantic model. + /// The cancellation token. + /// The contract, or when it does not bind. + /// + /// A literal is copied from its token, whose text the syntax tree already holds, so it costs no allocation and no + /// binding. Members are qualified with their type, so they compile from the generated file's namespace. + /// + internal static string? ExtractContract(ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken) => + expression is LiteralExpressionSyntax literal + ? literal.Token.Text + : ExtractValue(expression, semanticModel.GetSymbolInfo(expression, cancellationToken).Symbol); + + /// Reads a thread safety mode argument as C# source that compiles in the generated file. + /// The argument. + /// The semantic model. + /// The compilation's well-known symbols. + /// The cancellation token. + /// The mode, or when it does not bind. + /// A member of the enum, the usual argument, is looked up in a table rather than formatted. + internal static string? ExtractMode(ExpressionSyntax expression, SemanticModel semanticModel, WellKnownSymbols symbols, CancellationToken cancellationToken) + { + var symbol = semanticModel.GetSymbolInfo(expression, cancellationToken).Symbol; + return symbol is IFieldSymbol { ConstantValue: int value } field + && SymbolEqualityComparer.Default.Equals(field.ContainingType, symbols.LazyThreadSafetyModeType) + ? LazyThreadSafetyModeNames[value] + : ExtractValue(expression, symbol); } - /// - /// Resolves well-known type symbols from the compilation for efficient symbol comparison. - /// Results are cached per instance using a - /// so that repeated calls within the same compilation (e.g., across multiple syntax transforms) avoid redundant lookups. - /// - /// The compilation to resolve symbols from. - /// A struct containing the resolved symbols (any may be null if not found). - internal static WellKnownSymbols ResolveWellKnownSymbols(Compilation compilation) - => _symbolsCache.GetValue(compilation, static c => new WellKnownSymbolsBox(new( - ConstructorAttribute: c.GetTypeByMetadataName(Constants.ConstructorAttributeMetadataName), - PropertyAttribute: c.GetTypeByMetadataName(Constants.PropertyAttributeMetadataName), - LazyType: c.GetTypeByMetadataName(Constants.LazyMetadataName)?.OriginalDefinition as INamedTypeSymbol, - EnumerableType: c.GetTypeByMetadataName(Constants.EnumerableMetadataName)?.OriginalDefinition as INamedTypeSymbol))).Value; - - /// - /// Checks if a symbol has a specific attribute using symbol comparison (fast path) - /// with string comparison fallback when the attribute symbol is not available. - /// - /// The symbol to check for attributes. - /// The pre-resolved attribute symbol (may be null). - /// The fully qualified display string fallback. - /// True if the symbol has the specified attribute. - internal static bool HasAttribute(ISymbol symbol, INamedTypeSymbol? attributeSymbol, string attributeDisplayString) + /// Renders a bound argument as C# source that compiles in the generated file. + /// The argument. + /// The symbol the argument binds to. + /// The source, or when the argument does not bind. + internal static string? ExtractValue(ExpressionSyntax expression, ISymbol? symbol) => + symbol switch + { + null => null, + IFieldSymbol or IPropertySymbol => RoslynHelpers.GetFullyQualifiedMemberReference(symbol), + IMethodSymbol invokedMethod when expression is InvocationExpressionSyntax invocation => + RoslynHelpers.GetFullyQualifiedMethodInvocation(invokedMethod, invocation), + _ => expression.ToString(), + }; + + /// Describes how a constructor parameter is resolved. + /// The parameter's type. + /// The compilation's well-known symbols. + /// The parameter. + /// + /// The type argument of a lazy or a collection is cut from the name already formatted for the whole type, which + /// is the type argument's own name between the generic type's prefix and the closing bracket. + /// + internal static ConstructorParameter CreateParameter(ITypeSymbol type, WellKnownSymbols symbols) { - var attrs = symbol.GetAttributes(); - if (attributeSymbol != null) + var typeName = DisplayName(type); + if (type is INamedTypeSymbol { TypeArguments.Length: 1 } namedType) { - for (var i = 0; i < attrs.Length; i++) + var definition = namedType.OriginalDefinition; + if (SymbolEqualityComparer.Default.Equals(definition, symbols.LazyType)) { - if (SymbolEqualityComparer.Default.Equals(attrs[i].AttributeClass, attributeSymbol)) - { - return true; - } + return new(typeName, DependencyKind.Lazy, TypeArgumentName(typeName, LazyPrefix.Length)); } - } - else - { - for (var i = 0; i < attrs.Length; i++) + + if (SymbolEqualityComparer.Default.Equals(definition, symbols.EnumerableType)) { - if (attrs[i].AttributeClass?.ToDisplayString(_fullyQualifiedFormat) == attributeDisplayString) - { - return true; - } + return new(typeName, DependencyKind.Collection, TypeArgumentName(typeName, EnumerablePrefix.Length)); } } - return false; + return new(typeName, DependencyKind.Service, null); } - /// - /// Checks if a named type's original definition matches an expected type using symbol comparison (fast path) - /// with string comparison fallback when the expected symbol is not available. - /// - /// The named type to check. - /// The pre-resolved expected type symbol (may be null). - /// The fully qualified display string fallback. - /// True if the named type's original definition matches. - internal static bool IsOriginalDefinition(INamedTypeSymbol namedType, INamedTypeSymbol? expectedSymbol, string expectedDisplayString) + /// Tests whether a symbol carries an attribute. + /// The symbol. + /// The attribute type. + /// when the symbol carries the attribute. + internal static bool HasAttribute(ISymbol symbol, INamedTypeSymbol attribute) { - return expectedSymbol != null - ? SymbolEqualityComparer.Default.Equals(namedType.OriginalDefinition, expectedSymbol) - : namedType.OriginalDefinition.ToDisplayString(_fullyQualifiedFormat) == expectedDisplayString; + foreach (var data in symbol.GetAttributes()) + { + if (attribute.Equals(data.AttributeClass, SymbolEqualityComparer.Default)) + { + return true; + } + } + + return false; } - /// - /// Gets the first location from a locations array, or if empty. - /// - /// The locations array. - /// The first location or . - internal static Location GetFirstLocation(ImmutableArray locations) - => locations.Length > 0 ? locations[0] : Location.None; - - /// - /// Pre-resolved well-known symbols for efficient comparison without string allocations. - /// - /// The DependencyInjectionConstructorAttribute symbol. - /// The DependencyInjectionPropertyAttribute symbol. - /// The System.Lazy open generic type symbol. - /// The IEnumerable open generic type symbol. - internal readonly record struct WellKnownSymbols( - INamedTypeSymbol? ConstructorAttribute, - INamedTypeSymbol? PropertyAttribute, - INamedTypeSymbol? LazyType, - INamedTypeSymbol? EnumerableType); - - /// - /// Reference-type wrapper for to satisfy - /// value type constraint. - /// - /// The well-known symbols to wrap. - private sealed record WellKnownSymbolsBox(WellKnownSymbols Value); + /// Formats a type's fully qualified name, as the generated code writes it. + /// The type. + /// The name, starting global:: for a named type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static string DisplayName(ITypeSymbol type) => type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + + /// Cuts the single type argument out of a generic type's formatted name. + /// The generic type's name. + /// The length of the name before the type argument. + /// The type argument's name. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static string TypeArgumentName(string typeName, int prefixLength) => + typeName.Substring(prefixLength, typeName.Length - prefixLength - 1); } diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/ConstructorParameter.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/ConstructorParameter.cs index 9c8e1f20..eb129219 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/ConstructorParameter.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/ConstructorParameter.cs @@ -1,25 +1,15 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using System; - namespace Splat.DependencyInjection.SourceGenerator.Models; -/// -/// Represents a constructor parameter for dependency injection. -/// This is a cache-friendly POCO - contains only primitive data, no ISymbol/SyntaxNode references. -/// -/// The name of the constructor parameter. -/// The fully qualified type name of the parameter. -/// Whether the parameter is a type. -/// The inner type of the Lazy parameter, or null if not lazy. -/// Whether the parameter is an IEnumerable collection type. -/// The item type of the collection, or null if not a collection. -internal sealed record ConstructorParameter( - string ParameterName, - string TypeFullName, - bool IsLazy, - string? LazyInnerType, - bool IsCollection, - string? CollectionItemType) : IEquatable; +/// A constructor parameter the generated factory resolves. +/// The fully qualified type of the parameter. +/// How the parameter is resolved. +/// +/// The fully qualified type argument of a or +/// parameter; for a . +/// +/// A value type, so a registration's parameters are one array rather than one object each. +internal readonly record struct ConstructorParameter(string TypeFullName, DependencyKind Kind, string? InnerTypeFullName); diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/DependencyKind.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/DependencyKind.cs new file mode 100644 index 00000000..3e010d5c --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/DependencyKind.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DependencyInjection.SourceGenerator.Models; + +/// How a constructor parameter is resolved. +internal enum DependencyKind +{ + /// One registered service, which must exist. + Service = 0, + + /// A of a service, itself registered by RegisterLazySingleton. + Lazy = 1, + + /// An of every registration of a service. + Collection = 2, +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/EquatableArray.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/EquatableArray.cs index 37ce00aa..0a695a86 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/EquatableArray.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/EquatableArray.cs @@ -1,93 +1,91 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System; -using System.Collections; -using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace Splat.DependencyInjection.SourceGenerator.Models; -/// -/// A value-equatable wrapper around an array for use in incremental generator pipelines. -/// This enables structural equality comparisons of arrays in record types. -/// -/// The type of elements in the array, must be equatable. -internal readonly struct EquatableArray : IEquatable>, IEnumerable +/// A value-equatable wrapper around an array, so a record holding one compares by content. +/// The element type, which must be equatable. +/// +/// +/// The hash is computed once at construction: the pipeline hashes a model each time it compares a run's output with +/// the last, and the array never changes. +/// +/// +/// It is read by index, which allocates nothing. It deliberately does not implement +/// , whose enumerator a caller would allocate on every loop. +/// +/// +internal readonly struct EquatableArray : IEquatable> where T : IEquatable { - /// - /// The underlying array, or null if default-constructed. - /// + /// The multiplier used in the deterministic hash-combine loop. + private const int HashMultiplier = 31; + + /// The seed of the deterministic hash-combine loop. + private const int HashSeed = 17; + + /// The underlying array, or null if default-constructed. private readonly T[]? _array; - /// - /// Initializes a new instance of the struct. - /// - /// The array to wrap. + /// The hash code, computed once at construction. + private readonly int _hashCode; + + /// Initializes a new instance of the struct. + /// The array to wrap, which the caller must not change afterwards. public EquatableArray(T[] array) { _array = array; + _hashCode = ComputeHashCode(array); } - /// - /// Gets the length of the array. - /// - public int Length => _array?.Length ?? 0; + /// Gets an empty array. + internal static EquatableArray Empty { get; } = new([]); - /// - /// Gets the element at the specified index. - /// + /// Gets the number of elements. + internal int Length => _array?.Length ?? 0; + + /// Gets the element at the specified index. /// The zero-based index of the element to get. - public T this[int index] => _array![index]; + internal T this[int index] => _array![index]; - /// - /// Determines whether two arrays are equal. - /// + /// Determines whether two arrays are equal. /// The first array to compare. /// The second array to compare. - /// true if the arrays are equal; otherwise, false. - public static bool operator ==(EquatableArray left, EquatableArray right) - { - return left.Equals(right); - } + /// if the arrays are equal; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(EquatableArray left, EquatableArray right) => left.Equals(right); - /// - /// Determines whether two arrays are not equal. - /// + /// Determines whether two arrays are not equal. /// The first array to compare. /// The second array to compare. - /// true if the arrays are not equal; otherwise, false. - public static bool operator !=(EquatableArray left, EquatableArray right) - { - return !left.Equals(right); - } + /// if the arrays are not equal; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(EquatableArray left, EquatableArray right) => !left.Equals(right); - /// - /// Indicates whether the current array is equal to another array. - /// - /// An array to compare with this array. - /// true if the arrays are equal; otherwise, false. + /// Indicates whether this array has the same elements as another. + /// The array to compare with this one. + /// if the arrays are equal; otherwise, . public bool Equals(EquatableArray other) { - if (_array == null && other._array == null) + var array = _array ?? []; + var otherArray = other._array ?? []; + if (ReferenceEquals(array, otherArray)) { return true; } - if (_array == null || other._array == null) - { - return false; - } - - if (_array.Length != other._array.Length) + if (array.Length != otherArray.Length || _hashCode != other._hashCode) { return false; } - for (int i = 0; i < _array.Length; i++) + for (var i = 0; i < array.Length; i++) { - if (!_array[i].Equals(other._array[i])) + if (!array[i].Equals(otherArray[i])) { return false; } @@ -96,54 +94,29 @@ public bool Equals(EquatableArray other) return true; } - /// - /// Determines whether the specified object is equal to the current array. - /// - /// The object to compare with the current array. - /// true if the specified object is equal to the current array; otherwise, false. - public override bool Equals(object? obj) - { - return obj is EquatableArray other && Equals(other); - } + /// Determines whether the specified object is an equal array. + /// The object to compare with this array. + /// if the object is an equal array; otherwise, . + public override bool Equals(object? obj) => obj is EquatableArray other && Equals(other); - /// - /// Returns the hash code for this array. - /// - /// A hash code for the current array. - public override int GetHashCode() - { - if (_array == null) - { - return 0; - } + /// Returns the hash code computed at construction. + /// A hash code for the array. + public override int GetHashCode() => _hashCode; + /// Computes a deterministic hash code for an array. + /// The array to hash. + /// A hash code for the array. + private static int ComputeHashCode(T[] array) + { unchecked { - int hash = 17; - foreach (var item in _array) + var hash = HashSeed; + for (var i = 0; i < array.Length; i++) { - hash = (hash * 31) + (item?.GetHashCode() ?? 0); + hash = (hash * HashMultiplier) + array[i].GetHashCode(); } return hash; } } - - /// - /// Returns an enumerator that iterates through the array. - /// - /// An enumerator for the array. - public IEnumerator GetEnumerator() - { - return ((_array ?? []) as IEnumerable).GetEnumerator(); - } - - /// - /// Returns an enumerator that iterates through the array. - /// - /// An enumerator for the array. - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } } diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/LazySingletonRegistrationInfo.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/LazySingletonRegistrationInfo.cs deleted file mode 100644 index 7c97a178..00000000 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/LazySingletonRegistrationInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using Microsoft.CodeAnalysis; - -namespace Splat.DependencyInjection.SourceGenerator.Models; - -/// -/// Represents a lazy singleton registration (created once on first resolve). -/// This is a cache-friendly POCO - contains only primitive data, no ISymbol/SyntaxNode references. -/// -/// The fully qualified type name of the interface being registered. -/// The fully qualified type name of the concrete implementation. -/// The constructor parameters for the concrete type. -/// The property injections for the concrete type. -/// The optional contract key value, or null for unkeyed registrations. -/// The thread safety mode for the lazy initialization, or null for default. -/// The source location of the registration invocation. -internal sealed record LazySingletonRegistrationInfo( - string InterfaceTypeFullName, - string ConcreteTypeFullName, - EquatableArray ConstructorParameters, - EquatableArray PropertyInjections, - string? ContractValue, - string? LazyThreadSafetyMode, - Location InvocationLocation) - : RegistrationInfo( - InterfaceTypeFullName, - ConcreteTypeFullName, - ConstructorParameters, - PropertyInjections, - ContractValue, - InvocationLocation); diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/LocationInfo.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/LocationInfo.cs new file mode 100644 index 00000000..73d1b018 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/LocationInfo.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace Splat.DependencyInjection.SourceGenerator.Models; + +/// A source location held as values, so a pipeline model compares by value and roots no syntax tree. +/// The path of the file. +/// The span within the file. +/// The line and column span within the file. +/// +/// A holds its syntax tree, so keeping one in a model would keep every tree of an old +/// compilation alive and make two models from different compilations unequal even when nothing moved. +/// +internal readonly record struct LocationInfo(string FilePath, TextSpan TextSpan, LinePositionSpan LineSpan) +{ + /// Captures the location of a syntax node. + /// The node. + /// The location. + internal static LocationInfo From(SyntaxNode node) + { + var tree = node.SyntaxTree; + var span = node.Span; + return new(tree.FilePath, span, tree.GetLineSpan(span).Span); + } + + /// Creates the a diagnostic is reported at. + /// The location. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Location ToLocation() => Location.Create(FilePath, TextSpan, LineSpan); +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/PropertyInjection.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/PropertyInjection.cs index 77a78d36..a82287fe 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/PropertyInjection.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/PropertyInjection.cs @@ -1,21 +1,11 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using System; - -using Microsoft.CodeAnalysis; - namespace Splat.DependencyInjection.SourceGenerator.Models; -/// -/// Represents a property injection for dependency injection. -/// This is a cache-friendly POCO - contains only primitive data and Location for diagnostics. -/// -/// The name of the property to inject. -/// The fully qualified type name of the property. -/// The source location of the property declaration. -internal sealed record PropertyInjection( - string PropertyName, - string TypeFullName, - Location PropertyLocation) : IEquatable; +/// A property the generated factory sets in its object initializer. +/// The name of the property. +/// The fully qualified type of the property. +/// A value type, so a registration's properties are one array rather than one object each. +internal readonly record struct PropertyInjection(string PropertyName, string TypeFullName); diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationInfo.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationInfo.cs index 864811f0..e32e6553 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationInfo.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationInfo.cs @@ -1,25 +1,26 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using Microsoft.CodeAnalysis; - namespace Splat.DependencyInjection.SourceGenerator.Models; -/// -/// Base record for all registration types. -/// This is a cache-friendly POCO - contains only primitive data, no ISymbol/SyntaxNode references. -/// -/// The fully qualified type name of the interface being registered. -/// The fully qualified type name of the concrete implementation. -/// The constructor parameters for the concrete type. -/// The property injections for the concrete type. -/// The optional contract key value, or null for unkeyed registrations. -/// The source location of the registration invocation. -internal abstract record RegistrationInfo( +/// Everything the generated code needs for one registration. +/// How the registration creates its instances. +/// The fully qualified type being registered. +/// The fully qualified type that is constructed. +/// The parameters of the constructor that is called. +/// The properties set after construction. +/// The contract expression, as C# source; for none. +/// The thread safety mode expression, as C# source; for the default. +/// +/// Holds strings and values only - no symbol, syntax node or location - so it compares by value and an edit that +/// leaves the registration unchanged, such as one that moves it down a line, leaves the generated file cached. +/// +internal sealed record RegistrationInfo( + RegistrationKind Kind, string InterfaceTypeFullName, string ConcreteTypeFullName, EquatableArray ConstructorParameters, EquatableArray PropertyInjections, string? ContractValue, - Location InvocationLocation); + string? LazyThreadSafetyMode); diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationKind.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationKind.cs new file mode 100644 index 00000000..526303ed --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationKind.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DependencyInjection.SourceGenerator.Models; + +/// How a registration creates its instances. +internal enum RegistrationKind +{ + /// A new instance per resolution, from Register. + Transient = 0, + + /// One instance, created on first resolution, from RegisterLazySingleton. + LazySingleton = 1, +} diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationSite.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationSite.cs new file mode 100644 index 00000000..a43f5454 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/Models/RegistrationSite.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DependencyInjection.SourceGenerator.Models; + +/// A registration and the call that made it. +/// The registration. +/// Where the registration call is. +/// +/// The generated code is built from alone, so it is not rebuilt when only +/// moves. The graph diagnostics need both. +/// +internal sealed record RegistrationSite(RegistrationInfo Registration, LocationInfo Location); diff --git a/src/Splat.DependencyInjection.SourceGenerator/Models/TransientRegistrationInfo.cs b/src/Splat.DependencyInjection.SourceGenerator/Models/TransientRegistrationInfo.cs deleted file mode 100644 index 7f6227e5..00000000 --- a/src/Splat.DependencyInjection.SourceGenerator/Models/TransientRegistrationInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using Microsoft.CodeAnalysis; - -namespace Splat.DependencyInjection.SourceGenerator.Models; - -/// -/// Represents a transient registration (created per resolve). -/// This is a cache-friendly POCO - contains only primitive data, no ISymbol/SyntaxNode references. -/// -/// The fully qualified type name of the interface being registered. -/// The fully qualified type name of the concrete implementation. -/// The constructor parameters for the concrete type. -/// The property injections for the concrete type. -/// The optional contract key value, or null for unkeyed registrations. -/// The source location of the registration invocation. -internal sealed record TransientRegistrationInfo( - string InterfaceTypeFullName, - string ConcreteTypeFullName, - EquatableArray ConstructorParameters, - EquatableArray PropertyInjections, - string? ContractValue, - Location InvocationLocation) - : RegistrationInfo( - InterfaceTypeFullName, - ConcreteTypeFullName, - ConstructorParameters, - PropertyInjections, - ContractValue, - InvocationLocation); diff --git a/src/Splat.DependencyInjection.SourceGenerator/RegistrationValidator.cs b/src/Splat.DependencyInjection.SourceGenerator/RegistrationValidator.cs index 67b83be8..d0b05812 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/RegistrationValidator.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/RegistrationValidator.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using Microsoft.CodeAnalysis; @@ -13,213 +13,345 @@ namespace Splat.DependencyInjection.SourceGenerator; /// -/// Validates the collected registrations and reports the SPLATDI diagnostics that require the full -/// registration graph (SPLATDI005, SPLATDI006, SPLATDI007) and therefore cannot be detected by the -/// per-type analyzers. +/// Reports the diagnostics that need the whole registration graph - SPLATDI005, SPLATDI006 and SPLATDI007 - which the +/// per-type analyzers cannot see. /// +/// +/// Each check first looks for anything to report and returns before building a lookup when there is nothing, which is +/// the case for a project that builds cleanly. +/// internal static class RegistrationValidator { - /// - /// Reports graph-level registration diagnostics. - /// - /// The source production context used to report diagnostics. - /// The transient registrations. - /// The lazy singleton registrations. - public static void ReportDiagnostics( - SourceProductionContext context, - ImmutableArray transients, - ImmutableArray lazySingletons) - { - var all = transients.Cast() - .Concat(lazySingletons.Cast()) - .ToList(); + /// The DFS state of a node on the current path. + private const int OnPath = 1; + + /// The DFS state of a node whose descendants are all visited. + private const int Visited = 2; - if (all.Count == 0) + /// The number of registrations that makes a service registered more than once. + private const int Duplicate = 2; + + /// The entries each registration adds to the lookup of constructed types: its service and its type. + private const int NamesPerRegistration = 2; + + /// Reports the graph diagnostics. + /// The context diagnostics are reported to. + /// The registrations and where they are made, in source order. + internal static void ReportDiagnostics(SourceProductionContext context, ImmutableArray sites) + { + if (sites.IsEmpty) { return; } - ReportDuplicateInterfaceRegistrations(context, all); - ReportLazyParametersNotRegisteredLazy(context, all, lazySingletons); - ReportCircularDependencies(context, all); + var ordered = TransientsFirst(sites); + ReportDuplicateRegistrations(context, ordered); + ReportLazyParametersNotRegisteredLazy(context, ordered); + ReportCircularDependencies(context, ordered); } - /// - /// Reports SPLATDI006 when the same interface (and contract) is registered more than once. - /// - /// The source production context. - /// All registrations. - private static void ReportDuplicateInterfaceRegistrations(SourceProductionContext context, List all) + /// Orders the registrations the way the generated code makes them: transients, then lazy singletons. + /// The registrations in source order. + /// The registrations in registration order. + /// Returns the input unchanged, without copying, when it is already in that order. + internal static ImmutableArray TransientsFirst(ImmutableArray sites) + { + var sawLazySingleton = false; + var needsReorder = false; + foreach (var site in sites) + { + var isLazySingleton = site!.Registration.Kind == RegistrationKind.LazySingleton; + needsReorder |= sawLazySingleton && !isLazySingleton; + sawLazySingleton |= isLazySingleton; + } + + if (!needsReorder) + { + return sites; + } + + var builder = ImmutableArray.CreateBuilder(sites.Length); + AddKind(builder, sites, RegistrationKind.Transient); + AddKind(builder, sites, RegistrationKind.LazySingleton); + return builder.MoveToImmutable(); + } + + /// Reports SPLATDI006 at every registration of a type and contract that is registered more than once. + /// The context diagnostics are reported to. + /// The registrations in registration order. + internal static void ReportDuplicateRegistrations(in SourceProductionContext context, ImmutableArray sites) { - foreach (var group in all.GroupBy(r => (r.InterfaceTypeFullName, r.ContractValue))) + if (sites.Length < Duplicate) + { + return; + } + + var counts = new Dictionary<(string Service, string? Contract), int>(sites.Length); + var duplicated = false; + foreach (var site in sites) + { + var key = Key(site!.Registration); + _ = counts.TryGetValue(key, out var count); + counts[key] = count + 1; + duplicated |= count != 0; + } + + if (!duplicated) + { + return; + } + + // Each duplicated type is reported as a group, at the position of its first registration. + for (var i = 0; i < sites.Length; i++) { - if (group.Count() <= 1) + var key = Key(sites[i]!.Registration); + if (counts[key] < Duplicate) { continue; } - foreach (var registration in group) + counts[key] = 0; + for (var j = i; j < sites.Length; j++) { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticWarnings.InterfaceRegisteredMultipleTimes, - registration.InvocationLocation, - registration.InterfaceTypeFullName)); + var site = sites[j]!; + if (Key(site.Registration) == key) + { + context.ReportDiagnostic(Diagnostic.Create( + DiagnosticWarnings.InterfaceRegisteredMultipleTimes, + site.Location.ToLocation(), + site.Registration.InterfaceTypeFullName)); + } } } } - /// - /// Reports SPLATDI007 when a constructor takes a parameter whose - /// inner type is not registered via RegisterLazySingleton. - /// - /// The source production context. - /// All registrations. - /// The lazy singleton registrations. - private static void ReportLazyParametersNotRegisteredLazy( - SourceProductionContext context, - List all, - ImmutableArray lazySingletons) + /// Reports SPLATDI007 for a parameter whose type is not a lazy singleton. + /// The context diagnostics are reported to. + /// The registrations in registration order. + internal static void ReportLazyParametersNotRegisteredLazy(in SourceProductionContext context, ImmutableArray sites) { - var lazilyRegistered = new HashSet(); - foreach (var lazySingleton in lazySingletons) + HashSet? lazilyRegistered = null; + foreach (var site in sites) { - lazilyRegistered.Add(lazySingleton.InterfaceTypeFullName); - lazilyRegistered.Add(lazySingleton.ConcreteTypeFullName); - } - - foreach (var registration in all) - { - foreach (var parameter in registration.ConstructorParameters) + var registration = site!.Registration; + var parameters = registration.ConstructorParameters; + for (var i = 0; i < parameters.Length; i++) { - if (!parameter.IsLazy || parameter.LazyInnerType is null) + var parameter = parameters[i]; + if (parameter.Kind != DependencyKind.Lazy) { continue; } - if (lazilyRegistered.Contains(parameter.LazyInnerType)) + lazilyRegistered ??= LazilyRegisteredTypes(sites); + if (!lazilyRegistered.Contains(parameter.InnerTypeFullName!)) { - continue; + context.ReportDiagnostic(Diagnostic.Create( + DiagnosticWarnings.LazyParameterNotRegisteredLazy, + site.Location.ToLocation(), + registration.ConcreteTypeFullName, + parameter.InnerTypeFullName)); } - - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticWarnings.LazyParameterNotRegisteredLazy, - registration.InvocationLocation, - registration.ConcreteTypeFullName, - parameter.LazyInnerType)); } } } /// - /// Reports SPLATDI005 for registrations whose concrete types form a circular dependency through - /// their (non-lazy, non-collection) constructor parameters. + /// Reports SPLATDI005, once per type, at the first registration of each constructed type that takes part in a + /// dependency cycle through its constructor. /// - /// The source production context. - /// All registrations. - private static void ReportCircularDependencies(SourceProductionContext context, List all) + /// The context diagnostics are reported to. + /// The registrations in registration order. + /// + /// A lazy or collection parameter defers its resolution until after construction, so it cannot close a cycle and + /// is left out of the graph. + /// + internal static void ReportCircularDependencies(in SourceProductionContext context, ImmutableArray sites) { - // Map each requested type (interface or concrete) to the concrete that satisfies it. - var requestedToConcrete = new Dictionary(); - var concreteToLocation = new Dictionary(); - foreach (var registration in all) - { - requestedToConcrete[registration.InterfaceTypeFullName] = registration.ConcreteTypeFullName; - requestedToConcrete[registration.ConcreteTypeFullName] = registration.ConcreteTypeFullName; - if (!concreteToLocation.ContainsKey(registration.ConcreteTypeFullName)) - { - concreteToLocation[registration.ConcreteTypeFullName] = registration.InvocationLocation; - } + if (!HasServiceParameter(sites)) + { + return; } - // Build the dependency graph among concrete types. Lazy and collection parameters defer - // resolution and therefore break a cycle, so they are excluded. - var graph = new Dictionary>(); - foreach (var registration in all) + // Each type a constructor can ask for - a registered service or a constructed type - maps to the type + // constructed for it. + var constructedFor = new Dictionary(sites.Length * NamesPerRegistration, StringComparer.Ordinal); + var firstLocation = new Dictionary(sites.Length, StringComparer.Ordinal); + foreach (var site in sites) { - if (!graph.TryGetValue(registration.ConcreteTypeFullName, out var dependencies)) + var registration = site!.Registration; + constructedFor[registration.InterfaceTypeFullName] = registration.ConcreteTypeFullName; + constructedFor[registration.ConcreteTypeFullName] = registration.ConcreteTypeFullName; + if (!firstLocation.ContainsKey(registration.ConcreteTypeFullName)) { - dependencies = new HashSet(); - graph[registration.ConcreteTypeFullName] = dependencies; + firstLocation.Add(registration.ConcreteTypeFullName, site.Location); } + } - foreach (var parameter in registration.ConstructorParameters) - { - if (parameter.IsLazy || parameter.IsCollection) - { - continue; - } + var graph = BuildGraph(sites, constructedFor); + foreach (var concreteType in FindNodesInCycles(graph)) + { + context.ReportDiagnostic(Diagnostic.Create( + DiagnosticWarnings.ConstructorsMustNotHaveCircularDependency, + firstLocation[concreteType].ToLocation())); + } + } - if (requestedToConcrete.TryGetValue(parameter.TypeFullName, out var dependencyConcrete)) + /// Builds the graph of constructed types, each pointing at the constructed types it depends on. + /// The registrations in registration order. + /// The constructed type for each type a constructor can ask for. + /// Every constructed type, in registration order, with its dependencies; for none. + internal static Dictionary?> BuildGraph(ImmutableArray sites, Dictionary constructedFor) + { + var graph = new Dictionary?>(sites.Length, StringComparer.Ordinal); + foreach (var site in sites) + { + var registration = site!.Registration; + _ = graph.TryGetValue(registration.ConcreteTypeFullName, out var dependencies); + var parameters = registration.ConstructorParameters; + for (var i = 0; i < parameters.Length; i++) + { + var parameter = parameters[i]; + if (parameter.Kind == DependencyKind.Service + && constructedFor.TryGetValue(parameter.TypeFullName, out var dependency) + && (dependencies is null || !dependencies.Contains(dependency))) { - dependencies.Add(dependencyConcrete); + (dependencies ??= []).Add(dependency); } } + + graph[registration.ConcreteTypeFullName] = dependencies; } - foreach (var concrete in FindNodesInCycles(graph)) + return graph; + } + + /// Finds the nodes that lie on at least one cycle. + /// The graph, each node pointing at nodes of the same graph. + /// The nodes on a cycle, in the order the search reached them. + /// + /// A depth-first search from each node in turn. Reaching a node still on the path closes a cycle, and every node + /// from it to the top of the path lies on that cycle. + /// + internal static List FindNodesInCycles(Dictionary?> graph) + { + var inCycle = new List(); + var state = new Dictionary(graph.Count, StringComparer.Ordinal); + var path = new List(); + + foreach (var node in graph.Keys) { - if (concreteToLocation.TryGetValue(concrete, out var location)) + if (!state.ContainsKey(node)) { - context.ReportDiagnostic(Diagnostic.Create( - DiagnosticWarnings.ConstructorsMustNotHaveCircularDependency, - location)); + Visit(node); } } - } - /// - /// Returns the set of graph nodes that participate in at least one cycle. - /// - /// The dependency graph (concrete type to its concrete dependencies). - /// The concrete types that are part of a cycle. - private static HashSet FindNodesInCycles(Dictionary> graph) - { - var inCycle = new HashSet(); - var state = new Dictionary(); // 0 = unvisited, 1 = on stack, 2 = done. - var stack = new List(); + return inCycle; void Visit(string node) { - state[node] = 1; - stack.Add(node); + state[node] = OnPath; + path.Add(node); - if (graph.TryGetValue(node, out var dependencies)) + var dependencies = graph[node]; + if (dependencies is not null) { foreach (var next in dependencies) { - if (!graph.ContainsKey(next)) - { - continue; - } - - var nextState = state.TryGetValue(next, out var value) ? value : 0; + _ = state.TryGetValue(next, out var nextState); if (nextState == 0) { Visit(next); } - else if (nextState == 1) + else if (nextState == OnPath) { - var index = stack.LastIndexOf(next); - for (var i = index; i < stack.Count; i++) - { - inCycle.Add(stack[i]); - } + AddCycle(path, next, inCycle); } } } - stack.RemoveAt(stack.Count - 1); - state[node] = 2; + path.RemoveAt(path.Count - 1); + state[node] = Visited; } + } - foreach (var node in graph.Keys) + /// Adds the nodes of a cycle the search has closed. + /// The search's path, from its root to the node that reached . + /// The node on the path that the cycle returns to. + /// The nodes found on a cycle so far, in the order found. + internal static void AddCycle(List path, string start, List inCycle) + { + for (var i = path.LastIndexOf(start); i < path.Count; i++) { - if (!state.ContainsKey(node)) + if (!inCycle.Contains(path[i])) { - Visit(node); + inCycle.Add(path[i]); } } + } - return inCycle; + /// Tests whether any constructor takes a service directly, the only kind of edge a cycle can use. + /// The registrations. + /// when a constructor takes a service directly. + internal static bool HasServiceParameter(ImmutableArray sites) + { + foreach (var site in sites) + { + var parameters = site!.Registration.ConstructorParameters; + for (var i = 0; i < parameters.Length; i++) + { + if (parameters[i].Kind == DependencyKind.Service) + { + return true; + } + } + } + + return false; + } + + /// Collects the types RegisterLazySingleton registers, as services and as constructed types. + /// The registrations. + /// The types. + internal static HashSet LazilyRegisteredTypes(ImmutableArray sites) + { + var types = new HashSet(StringComparer.Ordinal); + foreach (var site in sites) + { + var registration = site!.Registration; + if (registration.Kind != RegistrationKind.LazySingleton) + { + continue; + } + + _ = types.Add(registration.InterfaceTypeFullName); + _ = types.Add(registration.ConcreteTypeFullName); + } + + return types; } + + /// Adds the registrations of one kind, in order. + /// The builder to add to. + /// The registrations. + /// The kind to add. + private static void AddKind(ImmutableArray.Builder builder, ImmutableArray sites, RegistrationKind kind) + { + foreach (var site in sites) + { + if (site!.Registration.Kind != kind) + { + continue; + } + + builder.Add(site); + } + } + + /// Gets the key two registrations of the same service share. + /// The registration. + /// The service type and contract. + private static (string Service, string? Contract) Key(RegistrationInfo registration) => + (registration.InterfaceTypeFullName, registration.ContractValue); } diff --git a/src/Splat.DependencyInjection.SourceGenerator/RoslynHelpers.cs b/src/Splat.DependencyInjection.SourceGenerator/RoslynHelpers.cs index fcd73fb8..0b00b3ca 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/RoslynHelpers.cs +++ b/src/Splat.DependencyInjection.SourceGenerator/RoslynHelpers.cs @@ -1,310 +1,114 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using System; -using System.Threading; +using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Splat.DependencyInjection.SourceGenerator; -/// -/// Helper methods for working with Roslyn symbols and syntax nodes. -/// +/// Syntax and symbol tests the pipeline runs before and while it binds a call. internal static class RoslynHelpers { - /// - /// The fully qualified symbol display format used for type name resolution. - /// - private static readonly SymbolDisplayFormat _fullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat; - - /// - /// Checks if a syntax node is a Register method invocation. - /// - /// The syntax node to check. - /// Cancellation token. - /// True if the node is a Register invocation, false otherwise. - internal static bool IsRegisterInvocation(SyntaxNode node, CancellationToken ct) + /// The largest number of arguments, and of type arguments, a marker method takes. + private const int MaxMarkerArguments = 2; + + /// Tests whether a syntax node could be a call to a marker method, from its syntax alone. + /// The syntax node. + /// for a call worth binding. + /// + /// + /// This runs on every node of every file on every edit, so it reads only syntax and allocates nothing. Every + /// marker is generic and none can infer its type arguments, so a call names them; a call with no type argument + /// list is not one. No marker takes a lambda, so a call passing one - Splat's own + /// resolver.Register<T>(() => ...) - is not one either. + /// + /// + /// A call through ?. is not considered: the markers are static, and a type cannot be conditionally accessed. + /// + /// + internal static bool IsRegistrationInvocation(SyntaxNode node) { if (node is not InvocationExpressionSyntax invocation) { return false; } - return invocation.Expression switch + var name = invocation.Expression switch { - MemberAccessExpressionSyntax { Name.Identifier.Text: Constants.MethodNameRegister } => true, - MemberBindingExpressionSyntax { Name.Identifier.Text: Constants.MethodNameRegister } => true, - SimpleNameSyntax { Identifier.Text: Constants.MethodNameRegister } => true, - _ => false + MemberAccessExpressionSyntax memberAccess => memberAccess.Name, + SimpleNameSyntax simpleName => simpleName, + _ => null, }; - } - /// - /// Checks if a syntax node is a RegisterLazySingleton method invocation. - /// - /// The syntax node to check. - /// Cancellation token. - /// True if the node is a RegisterLazySingleton invocation, false otherwise. - internal static bool IsRegisterLazySingletonInvocation(SyntaxNode node, CancellationToken ct) - { - if (node is not InvocationExpressionSyntax invocation) + if (name is not GenericNameSyntax { TypeArgumentList.Arguments.Count: > 0 and <= MaxMarkerArguments } genericName + || genericName.Identifier.ValueText is not (Constants.MethodNameRegister or Constants.MethodNameRegisterLazySingleton)) { return false; } - return invocation.Expression switch - { - MemberAccessExpressionSyntax { Name.Identifier.Text: Constants.MethodNameRegisterLazySingleton } => true, - MemberBindingExpressionSyntax { Name.Identifier.Text: Constants.MethodNameRegisterLazySingleton } => true, - SimpleNameSyntax { Identifier.Text: Constants.MethodNameRegisterLazySingleton } => true, - _ => false - }; - } - - /// - /// Checks if a method symbol is a specific method from SplatRegistrations class. - /// - /// The method symbol to check. - /// The expected method name. - /// True if the method is from SplatRegistrations with the specified name. - internal static bool IsSplatRegistrationsMethod(IMethodSymbol methodSymbol, string methodName) - { - var containingType = methodSymbol.ContainingType?.OriginalDefinition; - if (containingType == null) + var arguments = invocation.ArgumentList.Arguments; + if (arguments.Count > MaxMarkerArguments) { return false; } - return containingType.ContainingNamespace?.Name == Constants.NamespaceName && - containingType.Name == Constants.ClassName && - methodSymbol.Name == methodName && - !methodSymbol.IsExtensionMethod; - } - - /// - /// Gets all base types and the type itself in inheritance order. - /// - /// The type to get base types for. - /// An array of the type and all its base types. - internal static ITypeSymbol[] GetBaseTypesAndThis(ITypeSymbol type) - { - // Count inheritance depth first (typical: 1-5 levels) - var depth = 0; - var current = type; - while (current != null) - { - depth++; - current = current.BaseType; - } - - // Early exit for empty case (shouldn't happen, but defensive) - if (depth == 0) + foreach (var argument in arguments) { - return []; - } - - // Allocate exact-size array and populate - var result = new ITypeSymbol[depth]; - current = type; - for (var i = 0; i < depth; i++) - { - if (current == null) - { - // Defensive: shouldn't happen if depth calculation was correct - // Return partial results collected so far - var partial = new ITypeSymbol[i]; - Array.Copy(result, partial, i); - return partial; - } - - result[i] = current; - current = current.BaseType; - } - - return result; - } - - /// - /// Extracts the contract parameter value from a method invocation. - /// - /// The method symbol being invoked. - /// The invocation expression. - /// The semantic model. - /// Cancellation token. - /// The contract value as a string, or null if not found. - internal static string? ExtractContractParameter( - IMethodSymbol methodSymbol, - InvocationExpressionSyntax invocation, - SemanticModel semanticModel, - CancellationToken ct) - { - for (int i = 0; i < invocation.ArgumentList.Arguments.Count; i++) - { - var argument = invocation.ArgumentList.Arguments[i]; - var parameter = ResolveParameterForArgument(argument, methodSymbol, i); - - if (parameter == null || parameter.Name != Constants.ParameterNameContract) - { - continue; - } - - var expression = argument.Expression; - - // Handle string literals - if (expression is LiteralExpressionSyntax literal) - { - // Returns raw literal token (includes quotes), safe for embedding in generated code - return literal.ToString(); - } - - // Handle non-literal expressions (constant fields, properties, etc.) - // We need to fully qualify the reference to avoid CS0103 errors in generated code - // when the symbol is from a different namespace (GitHub issue: Keys from different namespace) - var symbolInfo = semanticModel.GetSymbolInfo(expression, ct); - if (symbolInfo.Symbol is IFieldSymbol or IPropertySymbol) - { - return GetFullyQualifiedMemberReference(symbolInfo.Symbol); - } - - // Handle method invocation expressions by fully qualifying the containing type - // while preserving the original argument list from the syntax tree. - if (symbolInfo.Symbol is IMethodSymbol invokedMethod - && expression is InvocationExpressionSyntax contractInvocation - && invokedMethod.ContainingType != null) + if (argument.Expression is AnonymousFunctionExpressionSyntax) { - return GetFullyQualifiedMethodInvocation(invokedMethod, contractInvocation); - } - - // For other resolved symbols (locals, etc.) - // preserve the expression as written since ToDisplayString may produce - // a signature-like string that is not a valid expression in generated code - if (symbolInfo.Symbol != null) - { - return expression.ToString(); + return false; } } - return null; + return true; } - /// - /// Gets a fully qualified reference string for a symbol (field, property, or other member). - /// For fields/properties, returns the fully qualified containing type plus the member name. - /// For other symbols, returns the fully qualified name directly. - /// - /// The symbol to get the fully qualified reference for. - /// A fully qualified reference string safe for use in generated code. - internal static string GetFullyQualifiedMemberReference(ISymbol symbol) + /// Tests whether a bound method is one of the marker methods on Splat.SplatRegistrations. + /// The method symbol. + /// for a marker method. + /// + /// The syntax predicate has already matched the method's name. A method bound from a call always has a containing + /// type - a local function's is the type it is declared in - and a type always has a containing namespace. + /// + internal static bool IsSplatRegistrationsMethod(IMethodSymbol methodSymbol) { - // For fields and properties, we need to build: global::Namespace.Type.MemberName - if (symbol is IFieldSymbol or IPropertySymbol) - { - var containingType = symbol.ContainingType; - if (containingType != null) - { - var fullyQualifiedTypeName = containingType.ToDisplayString(_fullyQualifiedFormat); - return $"{fullyQualifiedTypeName}.{symbol.Name}"; - } - } - - // For other symbols (e.g., local variables, parameters), return the display string - return symbol.ToDisplayString(_fullyQualifiedFormat); + var containingType = methodSymbol.ContainingType!; + return !methodSymbol.IsExtensionMethod + && containingType.Name == Constants.ClassName + && containingType.ContainingNamespace!.Name == Constants.NamespaceName; } - /// - /// Gets a fully qualified method invocation string for use in generated code. - /// Fully qualifies the containing type while preserving the method name (including type arguments) - /// and the original argument list from the syntax tree. - /// - /// The method symbol being invoked. - /// The invocation expression syntax. - /// A fully qualified method invocation string safe for use in generated code. + /// Builds a reference to a field or property that compiles from any namespace. + /// The field or property. + /// The fully qualified containing type, a dot, and the member's name. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static string GetFullyQualifiedMemberReference(ISymbol symbol) => + $"{symbol.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.{symbol.Name}"; + + /// Builds a call to a method that compiles from any namespace. + /// The called method. + /// The call as written. + /// + /// The fully qualified containing type, then the method's name and type arguments and the argument list as written. + /// internal static string GetFullyQualifiedMethodInvocation(IMethodSymbol invokedMethod, InvocationExpressionSyntax invocation) { - var fullyQualifiedTypeName = invokedMethod.ContainingType!.ToDisplayString(_fullyQualifiedFormat); - - // Extract method name from syntax to preserve type arguments (e.g., GetKey) - var methodName = invocation.Expression switch - { - MemberAccessExpressionSyntax memberAccess => memberAccess.Name.ToString(), - SimpleNameSyntax simpleName => simpleName.ToString(), - _ => invokedMethod.Name - }; - - return $"{fullyQualifiedTypeName}.{methodName}{invocation.ArgumentList}"; + var name = invocation.Expression is MemberAccessExpressionSyntax memberAccess ? memberAccess.Name : invocation.Expression; + return $"{invokedMethod.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.{name}{invocation.ArgumentList}"; } - /// - /// Extracts the LazyThreadSafetyMode parameter value from a RegisterLazySingleton invocation. - /// - /// The method symbol being invoked. - /// The invocation expression. - /// The semantic model. - /// Cancellation token. - /// The thread safety mode as a string, or null if not found. - internal static string? ExtractLazyThreadSafetyMode( - IMethodSymbol methodSymbol, - InvocationExpressionSyntax invocation, - SemanticModel semanticModel, - CancellationToken ct) - { - for (int i = 0; i < invocation.ArgumentList.Arguments.Count; i++) - { - var argument = invocation.ArgumentList.Arguments[i]; - var parameter = ResolveParameterForArgument(argument, methodSymbol, i); - - if (parameter == null || parameter.Name != Constants.ParameterNameMode) - { - continue; - } - - var expression = argument.Expression; - var symbolInfo = semanticModel.GetSymbolInfo(expression, ct); - - if (symbolInfo.Symbol != null) - { - return symbolInfo.Symbol.ToDisplayString(_fullyQualifiedFormat); - } - } - - return null; - } - - /// - /// Resolves the method parameter that corresponds to a given invocation argument, - /// handling both positional and named arguments correctly. - /// - /// The argument syntax from the invocation. - /// The method symbol being invoked. - /// The zero-based positional index of the argument in the argument list. - /// The corresponding parameter symbol, or if the parameter cannot be resolved. - internal static IParameterSymbol? ResolveParameterForArgument( - ArgumentSyntax argument, - IMethodSymbol methodSymbol, - int positionalIndex) - { - if (argument.NameColon != null) - { - var argumentName = argument.NameColon.Name.Identifier.Text; - for (int j = 0; j < methodSymbol.Parameters.Length; j++) - { - if (methodSymbol.Parameters[j].Name == argumentName) - { - return methodSymbol.Parameters[j]; - } - } - - return null; - } - - if (positionalIndex < 0 || positionalIndex >= methodSymbol.Parameters.Length) - { - return null; - } - - return methodSymbol.Parameters[positionalIndex]; - } + /// Finds the name of the parameter an argument is passed to. + /// The argument. + /// The bound method. + /// The argument's position in the list. + /// The parameter's name. + /// + /// The call bound, so a named argument names a parameter that exists and a positional one sits at a position that + /// exists. + /// + internal static string GetParameterName(ArgumentSyntax argument, IMethodSymbol methodSymbol, int position) => + argument.NameColon?.Name.Identifier.ValueText ?? methodSymbol.Parameters[position].Name; } diff --git a/src/Splat.DependencyInjection.SourceGenerator/Splat.DependencyInjection.SourceGenerator.csproj b/src/Splat.DependencyInjection.SourceGenerator/Splat.DependencyInjection.SourceGenerator.csproj index fdf4738f..6893693e 100644 --- a/src/Splat.DependencyInjection.SourceGenerator/Splat.DependencyInjection.SourceGenerator.csproj +++ b/src/Splat.DependencyInjection.SourceGenerator/Splat.DependencyInjection.SourceGenerator.csproj @@ -21,6 +21,11 @@ + + + + + diff --git a/src/Splat.DependencyInjection.SourceGenerator/WellKnownSymbols.cs b/src/Splat.DependencyInjection.SourceGenerator/WellKnownSymbols.cs new file mode 100644 index 00000000..57dd1da6 --- /dev/null +++ b/src/Splat.DependencyInjection.SourceGenerator/WellKnownSymbols.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; + +using Microsoft.CodeAnalysis; + +namespace Splat.DependencyInjection.SourceGenerator; + +/// The symbols extraction compares against, resolved once per compilation. +/// +/// Every registration call in a compilation needs the same symbols. They are kept in a +/// keyed by the compilation, so each transform finds them with one +/// lookup rather than five metadata-name searches, and they go when the compilation goes. +/// +internal sealed class WellKnownSymbols +{ + /// The symbols of each live compilation. + private static readonly ConditionalWeakTable Cache = new(); + + /// The factory the cache calls on a miss, allocated once. + private static readonly ConditionalWeakTable.CreateValueCallback Create = + static compilation => new(compilation); + + /// Initializes a new instance of the class. + /// The compilation to resolve the symbols from. + internal WellKnownSymbols(Compilation compilation) + { + SourceAssembly = compilation.Assembly; + ConstructorAttribute = compilation.GetTypeByMetadataName(Constants.ConstructorAttributeMetadataName); + PropertyAttribute = compilation.GetTypeByMetadataName(Constants.PropertyAttributeMetadataName); + LazyType = compilation.GetTypeByMetadataName(Constants.LazyMetadataName); + EnumerableType = compilation.GetTypeByMetadataName(Constants.EnumerableMetadataName); + LazyThreadSafetyModeType = compilation.GetTypeByMetadataName(Constants.LazyThreadSafetyModeMetadataName); + } + + /// Gets the assembly being compiled: the only one whose types can carry this compilation's attributes. + internal IAssemblySymbol SourceAssembly { get; } + + /// Gets the DependencyInjectionConstructorAttribute type, or when it is ambiguous. + internal INamedTypeSymbol? ConstructorAttribute { get; } + + /// Gets the DependencyInjectionPropertyAttribute type, or when it is ambiguous. + internal INamedTypeSymbol? PropertyAttribute { get; } + + /// Gets the open type. + internal INamedTypeSymbol? LazyType { get; } + + /// Gets the open type. + internal INamedTypeSymbol? EnumerableType { get; } + + /// Gets the type. + internal INamedTypeSymbol? LazyThreadSafetyModeType { get; } + + /// Gets the symbols of a compilation, resolving them on its first request. + /// The compilation. + /// The symbols. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static WellKnownSymbols For(Compilation compilation) => Cache.GetValue(compilation, Create); +} diff --git a/src/benchmarks/README.md b/src/benchmarks/README.md new file mode 100644 index 00000000..10eb5ebf --- /dev/null +++ b/src/benchmarks/README.md @@ -0,0 +1,117 @@ +# Benchmarks + +`Splat.DI.SourceGenerator.Benchmarks` measures two things: what a consumer's build pays while the generator runs, and +what a consumer's application pays in the code the generator wrote. + +## Running them + +```sh +cd src/benchmarks/Splat.DI.SourceGenerator.Benchmarks +dotnet run -c Release -- --filter '*' --artifacts ~/.cache/splat-bench/run +``` + +Release configuration is required. Every run attaches BenchmarkDotNet's memory diagnoser and an EventPipe profiler +with the `GcVerbose` profile plus CPU sampling (`Configs/ProfilerConfig.cs`), so each case leaves a `.nettrace` and a +`.speedscope.json` in the artifacts folder. Set `BENCHMARK_PROFILERS=false` for a timing-only A/B run. + +The benchmark project builds against Roslyn 5.9 (BenchmarkDotNet needs 5.6 or newer); the generator itself is built +against 4.14 and runs on any newer compiler, as it does on a current SDK. + +## Reading the allocations + +The trace's allocation ticks carry stacks, which is what tells the generator's allocations from Roslyn's: + +```sh +# Allocation types, sites and inclusive frames for one case +dotnet run ~/source/rxui/tools/nettrace-analyzer.cs -- --top 60 '/...Cold(Registrations_ 128)-*.nettrace' + +# Everything allocated beneath one generator method +dotnet run --project ~/source/rxui/tools/TraceFocus -c Release -- --file '/...speedscope.json' \ + --profile alloc --no-default-includes --include TryExtractConstructorParameters +``` + +## The cases + +`GenerationBenchmarks` runs the generator over a corpus with 1, 16 or 128 registrations. Registrations cycle through +a parameterless type, constructor and property injection, a lazy singleton with a mode taking a collection, and a +contract taking a lazy dependency; a third of the types have two constructors, one marked. Every service file also +calls Splat's own `resolver.Register(() => ...)`. + +- `Cold` builds a fresh driver per operation: a whole pass. +- `EditUnrelated` reruns a primed driver after an edit to a file with no registrations. +- `EditBootstrapper` reruns it after an edit that moves every registration down a line without changing one. + +`RuntimeBenchmarks` resolves services through the code the generator wrote for the benchmark project itself. +`Setup` makes every registration on a new resolver; the `Resolve` cases ask for a service. + +## Results + +Measured on an AMD Ryzen 7 5800X, .NET 10.0.12, with the profilers attached. The baseline is the generator before +this rewrite, built from the same benchmark sources. + +| Generation | Registrations | Before | After | +|------------|--------------:|-------:|------:| +| `Cold` | 1 | 1,466.7 us / 332.8 KB | 906.4 us / 242.0 KB | +| `EditUnrelated` | 1 | 710.0 us / 155.7 KB | 396.2 us / 105.3 KB | +| `EditBootstrapper` | 1 | 724.0 us / 166.4 KB | 387.0 us / 107.3 KB | +| `Cold` | 16 | 4,689.2 us / 770.5 KB | 2,203.7 us / 432.5 KB | +| `EditUnrelated` | 16 | 3,302.5 us / 519.6 KB | 1,515.2 us / 267.8 KB | +| `EditBootstrapper` | 16 | 3,301.8 us / 605.5 KB | 1,561.8 us / 281.4 KB | +| `Cold` | 128 | 21,045.1 us / 3,979.9 KB | 9,583.4 us / 1,824.4 KB | +| `EditUnrelated` | 128 | 18,523.2 us / 3,128.3 KB | 8,226.4 us / 1,475.9 KB | +| `EditBootstrapper` | 128 | 18,523.8 us / 3,811.3 KB | 8,471.5 us / 1,554.0 KB | + +| Runtime | Before | After | +|---------|-------:|------:| +| `Setup` | 1,701.9 ns / 8,144 B | 1,639.1 ns / 8,128 B | +| `ResolveLeaf` | 27.9 ns / 24 B | 28.9 ns / 24 B | +| `ResolveBranch` | 68.8 ns / 48 B | 69.0 ns / 48 B | +| `ResolveTree` | 201.8 ns / 200 B | 203.1 ns / 200 B | +| `ResolveSingleton` | 25.0 ns / 0 B | 25.3 ns / 0 B | +| `ResolveLazyConsumer` | 64.8 ns / 24 B | 65.0 ns / 24 B | +| `ResolveKeyed` | 61.5 ns / 48 B | 64.9 ns / 48 B | + +The baseline generator also wrote code that does not compile for a lazy singleton given a thread safety mode +(`PublicationOnly` instead of the enum member), which the corpus has; its generation figures are still comparable, +since the generator never compiles its own output. + +## Where the generation time went, and where it goes now + +In the baseline trace, 86% of an unrelated edit's allocation was the transform binding calls: a `CreateSyntaxProvider` +transform re-runs for every matching node whenever the compilation changes, and the old predicate let through every +call named `Register`, including Splat's own `resolver.Register(() => new T(...))`. Binding those lambdas and their +overloads dominated the trace. The predicate now requires a type argument list and rejects lambda arguments, so those +calls never reach the transform, and a receiver not spelled `SplatRegistrations` is bound on its own before the call. + +What remains of a pass, by allocation beneath each generator frame in the `Cold`/128 trace: + +- Binding the marker call (`GetSymbolInfo`). Required: the type arguments, overload and argument bindings come from it. +- Building each registered type's member table on first touch (`GetMembers(".ctor")`, beneath + `TryExtractConstructorParameters`). Required by any inspection of a type's constructors; looking constructors up by + name avoids building a list of all members as well. +- Binding attributes (`GetAttributes`, beneath `HasAttribute`). Required to tell our attribute from another, including + through a using alias. The walk stops at the first base type from a reference, whose members are never loaded, and + a type from a reference with several constructors is turned away without decoding theirs. +- The registrations file string (`PooledBuilder.ToStringAndReturn`). One string of the file's size is the least + `AddSource` accepts; the builder behind it is pooled per thread and reused across passes. +- Type names (`ToDisplayString`), about a twentieth of the constructor-extraction figure. Each is kept in the model; a lazy's and + a collection's type argument is cut from the name already formatted rather than formatted again. A per-compilation + name cache was considered and rejected: it would cost a dictionary and its entries per compilation to save a small + share, and hit only when many registrations share a dependency. +- The models: one `RegistrationInfo` and one `RegistrationSite` per registration, one array of `ConstructorParameter` + values (structs) per registration with parameters, and nothing for a type without injected properties. The split + into `RegistrationSite` costs one object per registration and is what lets `EditBootstrapper` skip regeneration. +- The graph checks allocate their lookups only when there is something to look for, and are a fraction of a percent. + +## What the generated code allocates + +Resolving a service allocates the objects it constructs and nothing else from the generated code: `ResolveLeaf` is +the `Leaf` (24 B), `ResolveBranch` the `Branch` and its `Leaf`, `ResolveSingleton` nothing once created. +`ResolveTree` also includes the collection Splat returns from `GetServices`. Every figure includes Splat's lookup. + +`Setup` allocates one closure for `resolver` and every lazy, one delegate for each registration that captures, and +for each lazy singleton the `Lazy` and three delegates. A registration with nothing to resolve captures nothing, so +its delegate is created once for the life of the application. The rest is Splat's registration storage. + +Resolution through the resolver cannot be avoided: constructing a dependency directly would ignore a registration the +application makes later, which Splat's semantics allow. diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/BenchmarkProfiling.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/BenchmarkProfiling.cs new file mode 100644 index 00000000..96fcfa40 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/BenchmarkProfiling.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Configs; + +/// Reads whether the benchmark config attaches its profiler. +/// +/// An A/B comparison measures timing only. It sets BENCHMARK_PROFILERS to false, which skips the +/// second pass the profiler adds to every benchmark. +/// +public static class BenchmarkProfiling +{ + /// The environment variable that turns the profiler off when set to false. + private const string VariableName = "BENCHMARK_PROFILERS"; + + /// Gets a value indicating whether the profiler is attached. + public static bool Enabled => + !string.Equals(Environment.GetEnvironmentVariable(VariableName), "false", StringComparison.OrdinalIgnoreCase); +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/ProfilerConfig.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/ProfilerConfig.cs new file mode 100644 index 00000000..8805b840 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Configs/ProfilerConfig.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics.Tracing; + +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Exporters; + +using Microsoft.Diagnostics.NETCore.Client; +using Microsoft.Diagnostics.Tracing.Parsers; + +namespace Splat.DI.SourceGenerator.Benchmarks.Configs; + +/// The memory diagnoser, and an EventPipe trace of CPU samples and verbose GC events. +/// +/// A config keeps one EventPipe profiler, and the CPU and GC profiles both enable the runtime provider. So the +/// sample profiler is added beside the profile, and the runtime provider +/// carries the keywords of both. The trace's allocation ticks carry stacks, which is what attributes an allocation +/// to the generator rather than to Roslyn. +/// +public class ProfilerConfig : ManualConfig +{ + /// The provider that samples CPU stacks. + private const string SampleProfilerProviderName = "Microsoft-DotNETCore-SampleProfiler"; + + /// The runtime keywords of both profiles: the CPU profile's defaults, which include GC, plus GC handles. + private const ClrTraceEventParser.Keywords RuntimeKeywords = + ClrTraceEventParser.Keywords.Default | ClrTraceEventParser.Keywords.GCHandle; + + /// Initializes a new instance of the class. + public ProfilerConfig() + { + Add(DefaultConfig.Instance); + _ = AddDiagnoser(MemoryDiagnoser.Default); + _ = AddColumn(CategoriesColumn.Default); + _ = AddExporter(MarkdownExporter.GitHub); + + if (!BenchmarkProfiling.Enabled) + { + return; + } + + EventPipeProvider[] providers = + [ + new(SampleProfilerProviderName, EventLevel.Informational), + new(ClrTraceEventParser.ProviderName, EventLevel.Verbose, (long)RuntimeKeywords), + ]; + + _ = AddDiagnoser(new EventPipeProfiler(EventPipeProfile.GcVerbose, providers)); + } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Corpus/CorpusBuilder.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Corpus/CorpusBuilder.cs new file mode 100644 index 00000000..d916fb95 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Corpus/CorpusBuilder.cs @@ -0,0 +1,261 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Text; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +using Splat.DependencyInjection.SourceGenerator; + +namespace Splat.DI.SourceGenerator.Benchmarks.Corpus; + +/// Builds a consumer compilation holding a chosen number of registrations, and the driver that runs over it. +/// +/// +/// Registrations cycle through the shapes the generator handles: a parameterless constructor, constructor and +/// property injection, a lazy singleton with a thread safety mode taking a collection, and a contract taking a lazy +/// dependency. Every third type carries two constructors, one marked for injection. +/// +/// +/// Every service file also calls Splat's own Register and other methods, so the syntax predicate sees the +/// invocations a real project has and the transform sees calls that share a name with the marker methods. +/// +/// +internal static class CorpusBuilder +{ + /// The name of the file that makes the registrations. + internal const string BootstrapperFile = "Bootstrapper.cs"; + + /// The name of the file that takes no part in registration. + internal const string UnrelatedFile = "Unrelated.cs"; + + /// How many services each service file declares. + private const int ServicesPerFile = 8; + + /// The files beside the service files: the bootstrapper and the unrelated file. + private const int FixedFiles = 2; + + /// The characters the bootstrapper takes besides its registrations. + private const int BootstrapperCapacity = 256; + + /// The characters one registration call takes. + private const int RegistrationCapacity = 96; + + /// The characters a file of services takes. + private const int ServicesCapacity = 2048; + + /// How many blank lines an edit to the bootstrapper can insert, cycling by revision. + private const int MaxInsertedLines = 8; + + /// One type in this many carries a second, unmarked constructor. + private const uint SecondConstructorEvery = 3; + + /// The number of registration shapes the corpus cycles through. + private const uint ShapeCount = 4; + + /// How far back a contract registration's service dependency reaches. + private const int ServiceDependencyDistance = 2; + + /// The start of a registration of a service. + private const string RegisterService = " SplatRegistrations.RegisterThe separator between a service and its implementation in a registration. + private const string ServiceSeparator = ", Service"; + + /// The parse options every tree is parsed with. + private static readonly CSharpParseOptions ParseOptions = new(LanguageVersion.Latest); + + /// The shape of registration each service is given, by its number modulo . + private enum Shape + { + /// A parameterless constructor. + Parameterless = 0, + + /// A constructor dependency and an injected property. + Injected = 1, + + /// A lazy singleton taking a collection. + LazyCollection = 2, + + /// A contract, with a service and a lazy dependency. + ContractLazy = 3, + } + + /// Builds the consumer compilation. + /// The number of registrations. + /// The compilation. + internal static CSharpCompilation Build(int registrations) + { + var trees = new List((registrations / ServicesPerFile) + FixedFiles) { Parse(BuildBootstrapper(registrations, 0), BootstrapperFile) }; + + for (var start = 0; start < registrations; start += ServicesPerFile) + { + trees.Add(Parse(BuildServices(start, Math.Min(start + ServicesPerFile, registrations)), $"Services{start}.cs")); + } + + trees.Add(Parse(BuildUnrelated(0), UnrelatedFile)); + + List references = [.. Basic.Reference.Assemblies.Net100.References.All, MetadataReference.CreateFromFile(typeof(IReadonlyDependencyResolver).Assembly.Location)]; + + return CSharpCompilation.Create("BenchmarkConsumer", trees, references, new(OutputKind.DynamicallyLinkedLibrary)); + } + + /// Returns the compilation with one file's text changed, as an edit between two builds. + /// The compilation to edit. + /// The file to change: or . + /// The number of registrations the compilation was built with. + /// Tells one edit from the next. + /// The edited compilation. + /// The corpus has no file of that name. + internal static CSharpCompilation Edit(CSharpCompilation compilation, string fileName, int registrations, int revision) + { + ArgumentNullException.ThrowIfNull(compilation); + + foreach (var tree in compilation.SyntaxTrees) + { + if (tree.FilePath != fileName) + { + continue; + } + + var text = fileName == BootstrapperFile + ? BuildBootstrapper(registrations, revision) + : BuildUnrelated(revision); + return compilation.ReplaceSyntaxTree(tree, Parse(text, fileName)); + } + + throw new ArgumentException($"The corpus has no file named {fileName}.", nameof(fileName)); + } + + /// Creates a driver that runs the generator with step tracking off, as a build does. + /// The driver. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static GeneratorDriver CreateDriver() => + CSharpGeneratorDriver.Create( + [new Generator().AsSourceGenerator()], + parseOptions: ParseOptions, + driverOptions: new(IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: false)); + + /// Parses a file. + /// The source. + /// The file path. + /// The tree. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static SyntaxTree Parse(string text, string path) => CSharpSyntaxTree.ParseText(text, ParseOptions, path); + + /// Gets the shape of registration a service is given; the first service always takes no parameters. + /// The service number, which is never negative. + /// The shape. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Shape ShapeOf(int service) => service == 0 ? Shape.Parameterless : (Shape)((uint)service % ShapeCount); + + /// Builds the file that makes every registration. + /// The number of registrations. + /// Blank lines added at the top, so an edit moves every registration. + /// The source. + private static string BuildBootstrapper(int registrations, int revision) + { + var builder = new StringBuilder(BootstrapperCapacity + (registrations * RegistrationCapacity)); + _ = builder.Append('\n', revision % MaxInsertedLines); + _ = builder.AppendLine("using System.Threading;").AppendLine("using Splat;").AppendLine(); + _ = builder.AppendLine("namespace Consumer;").AppendLine(); + _ = builder.AppendLine("public static class Bootstrapper").AppendLine("{"); + _ = builder.AppendLine(" public static void Register()").AppendLine(" {"); + for (var i = 0; i < registrations; i++) + { + _ = ShapeOf(i) switch + { + Shape.LazyCollection => builder.Append(" SplatRegistrations.RegisterLazySingleton(LazyThreadSafetyMode.PublicationOnly);"), + Shape.ContractLazy => builder.Append(RegisterService).Append(i).Append(ServiceSeparator).Append(i).AppendLine(">(Keys.Contract);"), + _ => builder.Append(RegisterService).Append(i).Append(ServiceSeparator).Append(i).AppendLine(">();"), + }; + } + + _ = builder.AppendLine(" SplatRegistrations.SetupIOC();").AppendLine(" }").AppendLine("}").AppendLine(); + _ = builder.AppendLine("public static class Keys").AppendLine("{").AppendLine(" public const string Contract = \"contract\";").AppendLine("}"); + return builder.ToString(); + } + + /// Builds a file of services. + /// The first service. + /// One past the last service. + /// The source. + private static string BuildServices(int start, int end) + { + var builder = new StringBuilder(ServicesCapacity); + _ = builder.AppendLine("using System;").AppendLine("using System.Collections.Generic;").AppendLine("using Splat;").AppendLine(); + _ = builder.AppendLine("namespace Consumer;").AppendLine(); + for (var i = start; i < end; i++) + { + _ = builder.Append("public interface IService").Append(i).AppendLine(" { }").AppendLine(); + _ = builder.Append("public sealed class Service").Append(i).Append(" : IService").AppendLine(i.ToString(CultureInfo.InvariantCulture)).AppendLine("{"); + AppendConstructors(builder, i); + _ = builder.AppendLine(" public void Work(IMutableDependencyResolver resolver, List values)").AppendLine(" {"); + _ = builder.AppendLine(" values.Add(1);").AppendLine(" Console.WriteLine(values.Count);"); + _ = builder.Append(" resolver.Register(() => new Service").Append(i).Append('('); + AppendNewArguments(builder, i); + _ = builder.AppendLine("));"); + _ = builder.AppendLine(" }").AppendLine("}").AppendLine(); + } + + return builder.ToString(); + } + + /// Writes a service's constructors and injected property. + /// The builder. + /// The service number. + private static void AppendConstructors(StringBuilder builder, int i) + { + var shape = ShapeOf(i); + var parameters = shape switch + { + Shape.Parameterless => string.Empty, + Shape.Injected => $"IService{i - 1} dependency", + Shape.LazyCollection => $"IEnumerable dependencies", + _ => $"IService{i - ServiceDependencyDistance} dependency, Lazy lazy", + }; + + if (shape == Shape.Injected && i > 1) + { + _ = builder.Append(" [DependencyInjectionProperty] public IService").Append(i - ServiceDependencyDistance).AppendLine(" Injected { get; set; }"); + } + + if ((uint)i % SecondConstructorEvery == 0) + { + _ = builder.Append(" public Service").Append(i).AppendLine("(int ignored) { }"); + _ = builder.AppendLine(" [DependencyInjectionConstructor]"); + } + + _ = builder.Append(" public Service").Append(i).Append('(').Append(parameters).AppendLine(") { }"); + } + + /// Writes the arguments Splat's own registration passes to a service's constructor. + /// The builder. + /// The service number. + private static void AppendNewArguments(StringBuilder builder, int i) => + _ = ShapeOf(i) switch + { + Shape.Parameterless => builder, + Shape.Injected => builder.Append("null!"), + Shape.LazyCollection => builder.Append("Array.Empty()"), + _ => builder.Append("null!, null!"), + }; + + /// Builds a file that takes no part in registration. + /// A value written into the file, so an edit changes it. + /// The source. + private static string BuildUnrelated(int revision) => + $$""" + namespace Consumer; + + public static class Unrelated + { + public static int Compute(int value) => (value * {{revision}}) + System.Math.Max(value, 1); + } + """; +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/GenerationBenchmarks.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/GenerationBenchmarks.cs new file mode 100644 index 00000000..93ac7919 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/GenerationBenchmarks.cs @@ -0,0 +1,143 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +using BenchmarkDotNet.Attributes; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +using Splat.DI.SourceGenerator.Benchmarks.Corpus; + +namespace Splat.DI.SourceGenerator.Benchmarks; + +/// Measures what a consumer's build pays while the generator runs. +/// +/// +/// builds a fresh driver per operation, so each measurement is a whole pass: syntax scan, +/// extraction, validation and emission. A reused driver would serve the pass from its caches. +/// +/// +/// The Edit cases keep one driver and alternate between two compilations that differ in one file, which is +/// the pass an IDE runs after each keystroke. changes a file with no registrations; +/// moves every registration down a line without changing any of them. +/// +/// +/// The compilations are built once per parameter set: loading a framework's worth of metadata references costs +/// far more than the pass under measurement, and is work the host build does once. +/// +/// +[DebuggerDisplay("GenerationBenchmarks: {Registrations}")] +public class GenerationBenchmarks +{ + /// The number of edited compilations each edit case alternates between. + private const int EditCount = 2; + + /// The generated files a clean run adds: the marker source and the registrations. + private const int ExpectedGeneratedFiles = 2; + + /// The corpus compilation. + private CSharpCompilation _compilation = null!; + + /// The corpus with the unrelated file edited. + private CSharpCompilation[] _unrelatedEdits = null!; + + /// The corpus with the bootstrapper edited. + private CSharpCompilation[] _bootstrapperEdits = null!; + + /// The driver the edit cases carry from one operation to the next. + private GeneratorDriver _driver = null!; + + /// The number of operations run on . + private int _revision; + + /// Gets or sets the number of registrations in the corpus. + [Params(1, 16, 128)] + public int Registrations { get; set; } + + /// Builds the corpus and its edited forms, and primes the edit driver. + /// The corpus does not generate, or its generated code does not compile. + [GlobalSetup] + public void Setup() + { + _compilation = CorpusBuilder.Build(Registrations); + _unrelatedEdits = CreateEdits(CorpusBuilder.UnrelatedFile); + _bootstrapperEdits = CreateEdits(CorpusBuilder.BootstrapperFile); + + var result = CorpusBuilder.CreateDriver().RunGeneratorsAndUpdateCompilation(_compilation, out var output, out var diagnostics).GetRunResult(); + if (result.GeneratedTrees.Length < ExpectedGeneratedFiles || !result.Diagnostics.IsEmpty || !diagnostics.IsEmpty) + { + throw new InvalidOperationException($"The corpus did not generate cleanly: {string.Join(", ", result.Diagnostics)}"); + } + + foreach (var diagnostic in output.GetDiagnostics()) + { + if (diagnostic.Severity == DiagnosticSeverity.Error) + { + throw new InvalidOperationException($"The generated corpus does not compile: {diagnostic}"); + } + } + + // Each benchmark case runs in its own process, so the edit cases start from a primed driver. + _driver = CorpusBuilder.CreateDriver().RunGenerators(_compilation); + } + + /// Runs a whole cold generation pass. + /// The number of generated characters, so the work cannot be optimized away. + [Benchmark(Baseline = true)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Cold() => CountCharacters(CorpusBuilder.CreateDriver().RunGenerators(_compilation)); + + /// Reruns the generator after an edit to a file with no registrations. + /// The number of generated characters. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int EditUnrelated() => RunEdit(_unrelatedEdits); + + /// Reruns the generator after an edit that moves every registration without changing one. + /// The number of generated characters. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int EditBootstrapper() => RunEdit(_bootstrapperEdits); + + /// Counts the characters a run generated. + /// The driver after the run. + /// The number of characters. + private static int CountCharacters(GeneratorDriver driver) + { + var characters = 0; + foreach (var generated in driver.GetRunResult().Results[0].GeneratedSources) + { + characters += generated.SourceText.Length; + } + + return characters; + } + + /// Builds the compilations an edit case alternates between. + /// The file each edit changes. + /// The edited compilations. + private CSharpCompilation[] CreateEdits(string fileName) + { + var edits = new CSharpCompilation[EditCount]; + for (var i = 0; i < edits.Length; i++) + { + edits[i] = CorpusBuilder.Edit(_compilation, fileName, Registrations, i + 1); + } + + return edits; + } + + /// Runs the carried driver over the next of the alternating edits. + /// The edited compilations. + /// The number of generated characters. + private int RunEdit(CSharpCompilation[] edits) + { + _revision++; + _driver = _driver.RunGenerators(edits[_revision % EditCount]); + return CountCharacters(_driver); + } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Program.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Program.cs new file mode 100644 index 00000000..399d2b15 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Program.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using BenchmarkDotNet.Running; + +using Splat.DI.SourceGenerator.Benchmarks.Configs; + +namespace Splat.DI.SourceGenerator.Benchmarks; + +/// Entry point that hands the command line to the BenchmarkDotNet switcher. +internal static class Program +{ + /// Runs the benchmarks the command line selects. + /// The command-line arguments passed to the switcher. + internal static void Main(string[] args) => + _ = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new ProfilerConfig()); +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Branch.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Branch.cs new file mode 100644 index 00000000..a35570d7 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Branch.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +/// The dependency. +[DebuggerDisplay("{Name}")] +public sealed class Branch(ILeaf leaf) : IBranch +{ + /// + public string Name => nameof(Branch); + + /// Gets the dependency. + public ILeaf Dependency { get; } = leaf; +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IBranch.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IBranch.cs new file mode 100644 index 00000000..b9a9c905 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IBranch.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service with one constructor dependency. +public interface IBranch +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IKeyed.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IKeyed.cs new file mode 100644 index 00000000..6477a668 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/IKeyed.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service registered under a contract. +public interface IKeyed +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILazyConsumer.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILazyConsumer.cs new file mode 100644 index 00000000..09582b42 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILazyConsumer.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service that takes a lazy singleton. +public interface ILazyConsumer +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILeaf.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILeaf.cs new file mode 100644 index 00000000..ed22f2cc --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ILeaf.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service with no dependencies. +public interface ILeaf +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ISingleton.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ISingleton.cs new file mode 100644 index 00000000..3277d29f --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ISingleton.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service registered as a lazy singleton. +public interface ISingleton +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ITree.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ITree.cs new file mode 100644 index 00000000..3f595a7f --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/ITree.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// A service with constructor, collection and property dependencies. +public interface ITree +{ + /// Gets the name of the implementation. + string Name { get; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Keyed.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Keyed.cs new file mode 100644 index 00000000..18434e0f --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Keyed.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +/// The dependency, resolved under the same contract. +[DebuggerDisplay("{Name}")] +public sealed class Keyed(ILeaf leaf) : IKeyed +{ + /// + public string Name => nameof(Keyed); + + /// Gets the dependency. + public ILeaf Dependency { get; } = leaf; +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/LazyConsumer.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/LazyConsumer.cs new file mode 100644 index 00000000..986d278f --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/LazyConsumer.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +/// The lazy dependency. +[DebuggerDisplay("{Name}")] +public sealed class LazyConsumer(Lazy singleton) : ILazyConsumer +{ + /// + public string Name => nameof(LazyConsumer); + + /// Gets the dependency. + public Lazy Dependency { get; } = singleton; +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Leaf.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Leaf.cs new file mode 100644 index 00000000..46e1be50 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Leaf.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +[DebuggerDisplay("{Name}")] +public sealed class Leaf : ILeaf +{ + /// + public string Name => nameof(Leaf); +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeBenchmarks.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeBenchmarks.cs new file mode 100644 index 00000000..5868eee5 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeBenchmarks.cs @@ -0,0 +1,106 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +using BenchmarkDotNet.Attributes; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// Measures the code the generator wrote for . +/// +/// is what an application pays once at start-up. The Resolve cases are what it pays each +/// time it asks the resolver for a service, which runs the factory the generator wrote. Every figure includes +/// Splat's own lookup, which the generated code does not control; read one case against another. +/// +[DebuggerDisplay("RuntimeBenchmarks")] +public class RuntimeBenchmarks : IDisposable +{ + /// The resolver the generated registrations were made on. + private ModernDependencyResolver _resolver = null!; + + /// The resolver made last. + private ModernDependencyResolver? _lastSetup; + + /// Makes the registrations once for the resolve cases. + /// The generated registrations do not resolve. + [GlobalSetup] + public void GlobalSetup() + { + _resolver = new(); + SplatRegistrations.SetupIOC(_resolver); + if (_resolver.GetService() is not Tree { Injected: not null } || _resolver.GetService(RuntimeRegistrations.Contract) is null) + { + throw new InvalidOperationException("The generated registrations did not resolve."); + } + } + + /// Makes every registration on a new resolver. + /// The resolver. + [Benchmark] + public ModernDependencyResolver Setup() + { + _lastSetup = new(); + SplatRegistrations.SetupIOC(_lastSetup); + return _lastSetup; + } + + /// Resolves a service with no dependencies. + /// The service. + [Benchmark(Baseline = true)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILeaf? ResolveLeaf() => _resolver.GetService(); + + /// Resolves a service with one constructor dependency. + /// The service. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IBranch? ResolveBranch() => _resolver.GetService(); + + /// Resolves a service with constructor, collection and property dependencies. + /// The service. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ITree? ResolveTree() => _resolver.GetService(); + + /// Resolves a lazy singleton after its first creation. + /// The service. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ISingleton? ResolveSingleton() => _resolver.GetService(); + + /// Resolves a service that takes a lazy singleton. + /// The service. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ILazyConsumer? ResolveLazyConsumer() => _resolver.GetService(); + + /// Resolves a service and its dependency under a contract. + /// The service. + [Benchmark] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IKeyed? ResolveKeyed() => _resolver.GetService(RuntimeRegistrations.Contract); + + /// Releases the resolvers. + [GlobalCleanup] + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// Releases the resolvers. + /// Whether the call comes from rather than a finalizer. + protected virtual void Dispose(bool disposing) + { + if (!disposing) + { + return; + } + + _resolver.Dispose(); + _lastSetup?.Dispose(); + } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeRegistrations.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeRegistrations.cs new file mode 100644 index 00000000..0d788b19 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/RuntimeRegistrations.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// Makes the registrations the runtime benchmarks resolve. +internal static class RuntimeRegistrations +{ + /// The contract and its dependency are registered under. + internal const string Contract = "keyed"; + + /// Declares the registrations; the generator reads the calls, which do nothing at run time. + internal static void Declare() + { + SplatRegistrations.Register(); + SplatRegistrations.Register(Contract); + SplatRegistrations.Register(); + SplatRegistrations.Register(); + SplatRegistrations.RegisterLazySingleton(); + SplatRegistrations.Register(); + SplatRegistrations.Register(Contract); + } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Singleton.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Singleton.cs new file mode 100644 index 00000000..25f3a4d3 --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Singleton.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +/// The dependency. +[DebuggerDisplay("{Name}")] +public sealed class Singleton(ILeaf leaf) : ISingleton +{ + /// + public string Name => nameof(Singleton); + + /// Gets the dependency. + public ILeaf Dependency { get; } = leaf; +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Tree.cs b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Tree.cs new file mode 100644 index 00000000..6184c67c --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Runtime/Tree.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Diagnostics; + +namespace Splat.DI.SourceGenerator.Benchmarks.Runtime; + +/// The implementation of . +/// The constructor dependency. +/// The collection dependency. +[DebuggerDisplay("{Name}")] +public sealed class Tree(IBranch branch, IEnumerable leaves) : ITree +{ + /// + public string Name => nameof(Tree); + + /// Gets the constructor dependency. + public IBranch Branch { get; } = branch; + + /// Gets the collection dependency. + public IEnumerable Leaves { get; } = leaves; + + /// Gets or sets the injected property. + [DependencyInjectionProperty] + public ILeaf? Injected { get; set; } +} diff --git a/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Splat.DI.SourceGenerator.Benchmarks.csproj b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Splat.DI.SourceGenerator.Benchmarks.csproj new file mode 100644 index 00000000..38f1975f --- /dev/null +++ b/src/benchmarks/Splat.DI.SourceGenerator.Benchmarks/Splat.DI.SourceGenerator.Benchmarks.csproj @@ -0,0 +1,28 @@ + + + + Exe + net10.0 + enable + false + + portable + + + + + + + + + + + + + + + diff --git a/src/stylecop.json b/src/stylecop.json deleted file mode 100644 index de1f1c04..00000000 --- a/src/stylecop.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "indentation": { - "useTabs": false, - "indentationSize": 4 - }, - "documentationRules": { - "documentExposedElements": true, - "documentInternalElements": false, - "documentPrivateElements": false, - "documentInterfaces": true, - "documentPrivateFields": false, - "documentationCulture": "en-US", - "companyName": "ReactiveUI Association Incorporated", - "copyrightText": "Copyright (c) 2019-2026 {companyName}. All rights reserved.\n{companyName} licenses this file to you under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.", - "variables": { - "licenseName": "MIT", - "licenseFile": "LICENSE" - }, - "xmlHeader": false - }, - "layoutRules": { - "newlineAtEndOfFile": "allow", - "allowConsecutiveUsings": true - }, - "maintainabilityRules": { - "topLevelTypes": [ - "class", - "interface", - "struct", - "enum", - "delegate" - ] - }, - "orderingRules": { - "usingDirectivesPlacement": "outsideNamespace", - "systemUsingDirectivesFirst": true - } - } -} diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/ConsoleLogger.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/ConsoleLogger.cs index 081df607..bad728ce 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/ConsoleLogger.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/ConsoleLogger.cs @@ -1,17 +1,20 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; + namespace TestApp; -/// -/// Provides a console-based implementation of . -/// -public class ConsoleLogger : ILogger +/// An that writes each message to a text writer, such as the console's output. +/// The writer each message is written to. +[DebuggerDisplay("ConsoleLogger")] +public class ConsoleLogger(TextWriter output) : ILogger { - /// - /// Logs a message to the console output with a [LOG] prefix. - /// - /// The message to log to the console. - public void Log(string message) => Console.WriteLine($"[LOG] {message}"); + /// Logs a message with a [LOG] prefix. + /// The message to log. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Log(string message) => output.WriteLine($"[LOG] {message}"); } diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/ILogger.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/ILogger.cs index d9b6c2cf..da2b8763 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/ILogger.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/ILogger.cs @@ -1,17 +1,13 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace TestApp; -/// -/// Defines a logger contract for writing log messages. -/// +/// Defines a logger contract for writing log messages. public interface ILogger { - /// - /// Logs a message to the output. - /// + /// Logs a message to the output. /// The message to log. void Log(string message); } diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/IService.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/IService.cs index 8d78a1f8..a60518bc 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/IService.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/IService.cs @@ -1,17 +1,13 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace TestApp; -/// -/// Defines a service contract for retrieving messages. -/// +/// Defines a service contract for retrieving messages. public interface IService { - /// - /// Gets a message from the service. - /// + /// Gets a message from the service. /// A string containing the service message. string GetMessage(); } diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/Program.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/Program.cs index 9e68ec4d..6703aa84 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/Program.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/Program.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using Splat; @@ -13,13 +13,14 @@ namespace TestApp; /// public static class Program { - /// - /// Main entry point for the application. - /// + /// Main entry point for the application. /// Command-line arguments passed to the application. public static void Main(string[] args) { + var output = Console.Out; + // Register dependencies using source generator + SplatRegistrations.RegisterConstant(output); SplatRegistrations.Register(); SplatRegistrations.Register(); SplatRegistrations.RegisterLazySingleton(); @@ -29,19 +30,15 @@ public static void Main(string[] args) // Test resolution var service = Locator.Current.GetService(); - var logger = Locator.Current.GetService(); - var serviceWithDep = Locator.Current.GetService(); + var serviceWithDependency = Locator.Current.GetService(); - if (service != null) + if (service is not null) { - Console.WriteLine(service.GetMessage()); + output.WriteLine(service.GetMessage()); } - if (serviceWithDep != null) - { - serviceWithDep.DoWork(); - } + serviceWithDependency?.DoWork(); - Console.WriteLine("TestApp completed successfully!"); + output.WriteLine("TestApp completed successfully!"); } } diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceImplementation.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceImplementation.cs index 20a138fc..737d6060 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceImplementation.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceImplementation.cs @@ -1,17 +1,16 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System.Runtime.CompilerServices; + namespace TestApp; -/// -/// Provides a concrete implementation of . -/// +/// Provides a concrete implementation of . public class ServiceImplementation : IService { - /// - /// Gets a greeting message from the service. - /// + /// Gets a greeting message from the service. /// A string containing "Hello from DI!". + [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetMessage() => "Hello from DI!"; } diff --git a/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceWithDependency.cs b/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceWithDependency.cs index 86112dd2..507672cd 100644 --- a/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceWithDependency.cs +++ b/src/tests/Splat.DI.SourceGenerator.TestApp/ServiceWithDependency.cs @@ -1,31 +1,22 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + namespace TestApp; -/// -/// A service that demonstrates constructor dependency injection. -/// -public class ServiceWithDependency +/// A service that demonstrates constructor dependency injection. +/// The logger instance to use for logging operations. +[DebuggerDisplay("ServiceWithDependency: {_logger}")] +public class ServiceWithDependency(ILogger logger) { - private readonly ILogger _logger; - - /// - /// Initializes a new instance of the class. - /// - /// The logger instance to use for logging operations. - /// Thrown when is null. - public ServiceWithDependency(ILogger logger) - { - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + /// The logger the work is reported to. + private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - /// - /// Performs work and logs the operation using the injected logger. - /// - public void DoWork() - { - _logger.Log("Working..."); - } + /// Performs work and logs the operation using the injected logger. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DoWork() => _logger.Log("Working..."); } diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerHelpersTests.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerHelpersTests.cs index 0d82a157..8cb6eb62 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerHelpersTests.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerHelpersTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; @@ -11,14 +11,22 @@ namespace Splat.DependencyInjection.Analyzer.Tests; -/// -/// Tests for the AnalyzerHelpers class. -/// +/// Tests for the AnalyzerHelpers class. public class AnalyzerHelpersTests { - /// - /// Tests IsSplatRegistrationsMethod with various scenarios. - /// + /// The name of the assembly compiled for each test. + private const string AssemblyName = "TestAssembly"; + + /// The name of the Splat registration method under test. + private const string RegisterMethodName = "Register"; + + /// The metadata name of the test class declared in the sources. + private const string TestClassName = "TestClass"; + + /// The metadata name of the Splat registrations class. + private const string SplatRegistrationsMetadataName = "Splat.SplatRegistrations"; + + /// Tests IsSplatRegistrationsMethod with various scenarios. /// A task representing the asynchronous operation. [Test] public async Task IsSplatRegistrationsMethod_ValidatesCorrectly() @@ -40,30 +48,28 @@ public static void Register(this string s) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]); + var splatReg = compilation.GetTypeByMetadataName(SplatRegistrationsMetadataName); await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - var otherMethod = splatReg.GetMembers("Other").OfType().First(); + var registerMethod = TestUtilities.FirstMethod(splatReg!, RegisterMethodName); + var otherMethod = TestUtilities.FirstMethod(splatReg!, "Other"); - await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(registerMethod, "Register")).IsTrue(); - await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(otherMethod, "Register")).IsFalse(); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(registerMethod, RegisterMethodName)).IsTrue(); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(otherMethod, RegisterMethodName)).IsFalse(); var otherType = compilation.GetTypeByMetadataName("Other.SplatRegistrations"); await Assert.That(otherType).IsNotNull(); - var wrongNamespaceMethod = otherType!.GetMembers("Register").OfType().First(); - await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(wrongNamespaceMethod, "Register")).IsFalse(); + var wrongNamespaceMethod = TestUtilities.FirstMethod(otherType!, RegisterMethodName); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(wrongNamespaceMethod, RegisterMethodName)).IsFalse(); var extType = compilation.GetTypeByMetadataName("Extensions"); await Assert.That(extType).IsNotNull(); - var extMethod = extType!.GetMembers("Register").OfType().First(); - await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(extMethod, "Register")).IsFalse(); + var extMethod = TestUtilities.FirstMethod(extType!, RegisterMethodName); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(extMethod, RegisterMethodName)).IsFalse(); } - /// - /// Tests GetConstructorAnalysis with various constructor types. - /// + /// Tests GetConstructorAnalysis with various constructor types. /// A task representing the asynchronous operation. [Test] public async Task GetConstructorAnalysis_CountsCorrectly() @@ -90,10 +96,10 @@ internal TestClass(float f) {} // Marked } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var testClass = compilation.GetTypeByMetadataName("TestClass"); + var testClass = compilation.GetTypeByMetadataName(TestClassName); await Assert.That(testClass).IsNotNull(); var attrSymbol = compilation.GetTypeByMetadataName("Splat.DependencyInjectionConstructorAttribute"); @@ -101,15 +107,15 @@ internal TestClass(float f) {} // Marked var analysis = AnalyzerHelpers.GetConstructorAnalysis(testClass!, attrSymbol); - await Assert.That(analysis.AccessibleCount).IsEqualTo(4); - await Assert.That(analysis.MarkedCount).IsEqualTo(2); + const int expectedAccessibleCount = 4; + const int expectedMarkedCount = 2; + await Assert.That(analysis.AccessibleCount).IsEqualTo(expectedAccessibleCount); + await Assert.That(analysis.MarkedCount).IsEqualTo(expectedMarkedCount); await Assert.That(analysis.FirstMarked).IsNotNull(); await Assert.That(analysis.SecondMarked).IsNotNull(); } - /// - /// Tests IsConstructorMarked fallback path. - /// + /// Tests IsConstructorMarked fallback path. /// A task representing the asynchronous operation. [Test] public async Task IsConstructorMarked_FallbackPath_IdentifiesAttribute() @@ -128,24 +134,22 @@ public TestClass(int i) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)); + .AddReferences(MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)); - var testClass = compilation.GetTypeByMetadataName("TestClass"); + var testClass = compilation.GetTypeByMetadataName(TestClassName); await Assert.That(testClass).IsNotNull(); - var markedCtor = testClass!.Constructors.First(c => c.Parameters.Length == 0); - var unmarkedCtor = testClass.Constructors.First(c => c.Parameters.Length == 1); + var markedCtor = TestUtilities.ConstructorWithParameterCount(testClass!, 0); + var unmarkedCtor = TestUtilities.ConstructorWithParameterCount(testClass!, 1); // Pass null for attribute symbol to force fallback await Assert.That(AnalyzerHelpers.IsConstructorMarked(markedCtor, null)).IsTrue(); await Assert.That(AnalyzerHelpers.IsConstructorMarked(unmarkedCtor, null)).IsFalse(); } - /// - /// Tests IsConstructorMarked fallback path returns false when attribute does not match. - /// + /// Tests IsConstructorMarked fallback path returns false when attribute does not match. /// A task representing the asynchronous operation. [Test] public async Task IsConstructorMarked_FallbackPath_NonMatchingAttribute_ReturnsFalse() @@ -157,21 +161,19 @@ public TestClass() {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var testClass = compilation.GetTypeByMetadataName("TestClass"); + var testClass = compilation.GetTypeByMetadataName(TestClassName); await Assert.That(testClass).IsNotNull(); - var ctor = testClass!.Constructors.First(c => !c.IsImplicitlyDeclared); + var ctor = TestUtilities.FirstExplicitConstructor(testClass!); // ctor has [Obsolete], null symbol forces string fallback - should not match await Assert.That(AnalyzerHelpers.IsConstructorMarked(ctor, null)).IsFalse(); } - /// - /// Tests IsConstructorMarked fast path. - /// + /// Tests IsConstructorMarked fast path. /// A task representing the asynchronous operation. [Test] public async Task IsConstructorMarked_FastPath_IdentifiesAttribute() @@ -189,32 +191,30 @@ public TestClass(int i) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)); + .AddReferences(MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)); - var testClass = compilation.GetTypeByMetadataName("TestClass"); + var testClass = compilation.GetTypeByMetadataName(TestClassName); await Assert.That(testClass).IsNotNull(); var attrSymbol = compilation.GetTypeByMetadataName("Splat.DependencyInjectionConstructorAttribute"); await Assert.That(attrSymbol).IsNotNull(); - var markedCtor = testClass!.Constructors.First(c => c.Parameters.Length == 0); - var unmarkedCtor = testClass.Constructors.First(c => c.Parameters.Length == 1); + var markedCtor = TestUtilities.ConstructorWithParameterCount(testClass!, 0); + var unmarkedCtor = TestUtilities.ConstructorWithParameterCount(testClass!, 1); await Assert.That(AnalyzerHelpers.IsConstructorMarked(markedCtor, attrSymbol)).IsTrue(); await Assert.That(AnalyzerHelpers.IsConstructorMarked(unmarkedCtor, attrSymbol)).IsFalse(); } - /// - /// Tests AnalyzeConstructorsForType with interface (should skip). - /// + /// Tests AnalyzeConstructorsForType with interface (should skip). /// A task representing the asynchronous operation. [Test] public async Task AnalyzeConstructorsForType_Interface_Skips() { var syntaxTree = CSharpSyntaxTree.ParseText("public interface ITest {}"); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); var type = compilation.GetTypeByMetadataName("ITest"); @@ -227,15 +227,13 @@ public async Task AnalyzeConstructorsForType_Interface_Skips() await Assert.That(diagnostics).IsEmpty(); } - /// - /// Tests AnalyzeConstructorsForType with enum (should skip). - /// + /// Tests AnalyzeConstructorsForType with enum (should skip). /// A task representing the asynchronous operation. [Test] public async Task AnalyzeConstructorsForType_Enum_Skips() { var syntaxTree = CSharpSyntaxTree.ParseText("public enum TestEnum { A, B }"); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); var type = compilation.GetTypeByMetadataName("TestEnum"); @@ -248,9 +246,7 @@ public async Task AnalyzeConstructorsForType_Enum_Skips() await Assert.That(diagnostics).IsEmpty(); } - /// - /// Tests IsSplatRegistrationsMethod with extension method. - /// + /// Tests IsSplatRegistrationsMethod with extension method. /// A task representing the asynchronous operation. [Test] public async Task IsSplatRegistrationsMethod_ExtensionMethod_ReturnsFalse() @@ -265,19 +261,16 @@ public static void Register(this SplatRegistrations r) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]); var extensionsType = compilation.GetTypeByMetadataName("Splat.Extensions"); await Assert.That(extensionsType).IsNotNull(); - var registerMethod = extensionsType!.GetMembers("Register").OfType().First(); + var registerMethod = TestUtilities.FirstMethod(extensionsType!, RegisterMethodName); await Assert.That(registerMethod.IsExtensionMethod).IsTrue(); - await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(registerMethod, "Register")).IsFalse(); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(registerMethod, RegisterMethodName)).IsFalse(); } - /// - /// Tests AnalyzeConstructorsForType where one constructor is marked but is not accessible. - /// Should report SPLATDI004. - /// + /// Tests AnalyzeConstructorsForType where one constructor is marked but is not accessible. Should report SPLATDI004. /// A task that represents the asynchronous operation. [Test] public async Task AnalyzeConstructorsForType_MarkedPrivateConstructor_ReportsError() @@ -293,11 +286,11 @@ private TestClass() {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)); + .AddReferences(MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)); - var type = compilation.GetTypeByMetadataName("TestClass"); + var type = compilation.GetTypeByMetadataName(TestClassName); var diagnostics = new List(); AnalyzerHelpers.AnalyzeConstructorsForType(compilation, type!, diagnostics.Add); @@ -328,35 +321,94 @@ public TestClass(int i) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)); + .AddReferences(MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)); - var type = compilation.GetTypeByMetadataName("TestClass"); + var type = compilation.GetTypeByMetadataName(TestClassName); var diagnostics = new List(); AnalyzerHelpers.AnalyzeConstructorsForType(compilation, type!, diagnostics.Add); - await Assert.That(diagnostics).Count().IsEqualTo(2); + const int expectedDiagnosticCount = 2; + await Assert.That(diagnostics).Count().IsEqualTo(expectedDiagnosticCount); await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI003"); await Assert.That(diagnostics[1].Id).IsEqualTo("SPLATDI003"); } - /// - /// Tests IsContainedInSplatRegistrations returns false for null. - /// + /// Tests IsContainedInSplatRegistrations returns false for null. /// A task representing the asynchronous operation. [Test] - public async Task IsContainedInSplatRegistrations_Null_ReturnsFalse() - { + public async Task IsContainedInSplatRegistrations_Null_ReturnsFalse() => await Assert.That(AnalyzerHelpers.IsContainedInSplatRegistrations(null)).IsFalse(); + + /// Tests IsContainedInSplatRegistrations returns false for a type with no containing namespace. + /// A task representing the asynchronous operation. + [Test] + public async Task IsContainedInSplatRegistrations_NoContainingNamespace_ReturnsFalse() + { + var compilation = CSharpCompilation.Create(AssemblyName); + var errorType = compilation.CreateErrorTypeSymbol(null, "SplatRegistrations", 0); + + await Assert.That(errorType.ContainingNamespace).IsNull(); + await Assert.That(AnalyzerHelpers.IsContainedInSplatRegistrations(errorType)).IsFalse(); + } + + /// Tests IsSplatRegistrationsMethod returns false for a method with no containing type. + /// A task representing the asynchronous operation. + [Test] + public async Task IsSplatRegistrationsMethod_NoContainingType_ReturnsFalse() + { + var compilation = CSharpCompilation.Create(AssemblyName) + .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); + var functionPointer = compilation.CreateFunctionPointerTypeSymbol( + compilation.GetSpecialType(SpecialType.System_Void), + RefKind.None, + [], + []); + + await Assert.That(functionPointer.Signature.ContainingType).IsNull(); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(functionPointer.Signature, RegisterMethodName)).IsFalse(); + } + + /// Tests IsSplatRegistrationsMethod returns false for an extension method declared on SplatRegistrations. + /// A task representing the asynchronous operation. + [Test] + public async Task IsSplatRegistrationsMethod_ExtensionMethodOnSplatRegistrations_ReturnsFalse() + { + var syntaxTree = CSharpSyntaxTree.ParseText(""" + namespace Splat { + public static class SplatRegistrations { + public static void Register(this string s) {} + } + } + """); + + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) + .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); + var splatReg = compilation.GetTypeByMetadataName(SplatRegistrationsMetadataName)!; + var extensionMethod = TestUtilities.FirstMethod(splatReg, RegisterMethodName); + + await Assert.That(extensionMethod.IsExtensionMethod).IsTrue(); + await Assert.That(AnalyzerHelpers.IsSplatRegistrationsMethod(extensionMethod, RegisterMethodName)).IsFalse(); } /// - /// Tests IsContainedInSplatRegistrations returns true for Splat.SplatRegistrations. + /// Tests IsConstructorMarked fallback path skips an attribute whose class could not be decoded, + /// which Roslyn reports as a null attribute class for malformed metadata attributes. /// /// A task representing the asynchronous operation. [Test] + public async Task IsConstructorMarked_FallbackPath_NullAttributeClass_ReturnsFalse() + { + var ctor = AttributeOverridingMethodProxy.Create([new NullClassAttributeData()]); + + await Assert.That(AnalyzerHelpers.IsConstructorMarked(ctor, null)).IsFalse(); + } + + /// Tests IsContainedInSplatRegistrations returns true for Splat.SplatRegistrations. + /// A task representing the asynchronous operation. + [Test] public async Task IsContainedInSplatRegistrations_SplatRegistrations_ReturnsTrue() { var syntaxTree = CSharpSyntaxTree.ParseText(""" @@ -365,15 +417,13 @@ public static class SplatRegistrations {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var type = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]); + var type = compilation.GetTypeByMetadataName(SplatRegistrationsMetadataName); await Assert.That(AnalyzerHelpers.IsContainedInSplatRegistrations(type)).IsTrue(); } - /// - /// Tests IsContainedInSplatRegistrations returns false for a type in the wrong namespace. - /// + /// Tests IsContainedInSplatRegistrations returns false for a type in the wrong namespace. /// A task representing the asynchronous operation. [Test] public async Task IsContainedInSplatRegistrations_WrongNamespace_ReturnsFalse() @@ -384,15 +434,13 @@ public static class SplatRegistrations {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]); var type = compilation.GetTypeByMetadataName("Other.SplatRegistrations"); await Assert.That(AnalyzerHelpers.IsContainedInSplatRegistrations(type)).IsFalse(); } - /// - /// Tests GetFirstLocation returns Location.None for an empty locations array. - /// + /// Tests GetFirstLocation returns Location.None for an empty locations array. /// A task representing the asynchronous operation. [Test] public async Task GetFirstLocation_EmptyArray_ReturnsLocationNone() @@ -402,15 +450,13 @@ public async Task GetFirstLocation_EmptyArray_ReturnsLocationNone() await Assert.That(result).IsEqualTo(Location.None); } - /// - /// Tests GetFirstLocation returns the first location when locations are present. - /// + /// Tests GetFirstLocation returns the first location when locations are present. /// A task representing the asynchronous operation. [Test] public async Task GetFirstLocation_WithLocations_ReturnsFirst() { var tree = CSharpSyntaxTree.ParseText("class C {}"); - var location = tree.GetRoot().GetLocation(); + var location = (await tree.GetRootAsync()).GetLocation(); var locations = ImmutableArray.Create(location); var result = AnalyzerHelpers.GetFirstLocation(locations); @@ -418,9 +464,7 @@ public async Task GetFirstLocation_WithLocations_ReturnsFirst() await Assert.That(result).IsEqualTo(location); } - /// - /// Tests ReportDiagnostics reports SPLATDI001 when multiple accessible constructors exist without marked constructor. - /// + /// Tests ReportDiagnostics reports SPLATDI001 when multiple accessible constructors exist without marked constructor. /// A task representing the asynchronous operation. [Test] public async Task ReportDiagnostics_MultipleAccessibleNoMarked_ReportsSPLATDI001() @@ -432,11 +476,12 @@ public TestClass(int i) {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var namedType = compilation.GetTypeByMetadataName("TestClass")!; - var analysis = new AnalyzerHelpers.ConstructorAnalysisResult(2, 0, null, null); + var namedType = compilation.GetTypeByMetadataName(TestClassName)!; + const int accessibleCount = 2; + var analysis = new AnalyzerHelpers.ConstructorAnalysisResult(accessibleCount, 0, null, null); var diagnostics = new List(); AnalyzerHelpers.ReportDiagnostics(analysis, namedType, null, diagnostics.Add); @@ -445,19 +490,17 @@ public TestClass(int i) {} await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); } - /// - /// Tests ReportDiagnostics reports nothing when only one accessible constructor exists. - /// + /// Tests ReportDiagnostics reports nothing when only one accessible constructor exists. /// A task representing the asynchronous operation. [Test] public async Task ReportDiagnostics_SingleAccessible_NoDiagnostic() { var syntaxTree = CSharpSyntaxTree.ParseText("public class TestClass { public TestClass() {} }"); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var namedType = compilation.GetTypeByMetadataName("TestClass")!; + var namedType = compilation.GetTypeByMetadataName(TestClassName)!; var analysis = new AnalyzerHelpers.ConstructorAnalysisResult(1, 0, null, null); var diagnostics = new List(); @@ -466,9 +509,7 @@ public async Task ReportDiagnostics_SingleAccessible_NoDiagnostic() await Assert.That(diagnostics).IsEmpty(); } - /// - /// Tests ReportDiagnostics reports SPLATDI004 when a single marked constructor is not accessible. - /// + /// Tests ReportDiagnostics reports SPLATDI004 when a single marked constructor is not accessible. /// A task representing the asynchronous operation. [Test] public async Task ReportDiagnostics_MarkedPrivateConstructor_ReportsSPLATDI004() @@ -483,11 +524,11 @@ private TestClass() {} } """); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) + var compilation = CSharpCompilation.Create(AssemblyName, [syntaxTree]) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var namedType = compilation.GetTypeByMetadataName("TestClass")!; - var privateCtor = namedType.Constructors.First(c => !c.IsImplicitlyDeclared); + var namedType = compilation.GetTypeByMetadataName(TestClassName)!; + var privateCtor = TestUtilities.FirstExplicitConstructor(namedType); var analysis = new AnalyzerHelpers.ConstructorAnalysisResult(0, 1, privateCtor, null); var diagnostics = new List(); diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerTestHelper.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerTestHelper.cs index 61e78188..d5981a4d 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerTestHelper.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AnalyzerTestHelper.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; @@ -10,37 +10,57 @@ namespace Splat.DependencyInjection.Analyzer.Tests; -/// -/// Helper for testing Roslyn analyzers without heavy testing framework dependencies. -/// -public static class AnalyzerTestHelper +/// Helper for testing Roslyn analyzers without heavy testing framework dependencies. +internal static class AnalyzerTestHelper { - /// - /// Runs an analyzer on the provided source code and returns diagnostics. - /// + /// Runs an analyzer on the provided source code and returns diagnostics. /// The type of analyzer to run. /// The source code to analyze. /// A task that represents the asynchronous operation. The task result contains the diagnostics. - public static async Task> GetDiagnosticsAsync(string source) + internal static async Task> GetDiagnosticsAsync(string source) where TAnalyzer : DiagnosticAnalyzer, new() { var compilation = CreateCompilation(source); var analyzer = new TAnalyzer(); var compilationWithAnalyzers = compilation.WithAnalyzers( - ImmutableArray.Create(analyzer)); + [analyzer]); var diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(); // Filter to only analyzer diagnostics (exclude compiler errors) - return diagnostics - .Where(d => analyzer.SupportedDiagnostics.Any(sd => sd.Id == d.Id)) - .ToImmutableArray(); + var builder = ImmutableArray.CreateBuilder(diagnostics.Length); + foreach (var diagnostic in diagnostics) + { + if (IsSupported(analyzer, diagnostic)) + { + builder.Add(diagnostic); + } + } + + return builder.ToImmutable(); + } + + /// Determines whether a diagnostic is one the analyzer declares as supported. + /// The analyzer. + /// The diagnostic to check. + /// if the analyzer supports the diagnostic's ID. + internal static bool IsSupported(DiagnosticAnalyzer analyzer, Diagnostic diagnostic) + { + foreach (var descriptor in analyzer.SupportedDiagnostics) + { + if (descriptor.Id == diagnostic.Id) + { + return true; + } + } + + return false; } - /// - /// Creates a CSharpCompilation from source code with necessary references. - /// + /// Creates a CSharpCompilation from source code with necessary references. + /// The source code to compile. + /// The compilation containing the source and the Splat stubs. private static CSharpCompilation CreateCompilation(string source) { // Add the attribute definitions and SplatRegistrations class so the analyzer can find them @@ -83,30 +103,27 @@ public static void RegisterConstant(T instance, string contract) { } var attributeTree = CSharpSyntaxTree.ParseText(attributeAndExtensionsSource); // Get references for the current runtime - var references = new List(); - - // Add core framework references - references.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - references.Add(MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)); - references.Add(MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)); - - // Add Splat reference for testing DI attributes - var splatAssembly = typeof(Splat.IReadonlyDependencyResolver).Assembly; - references.Add(MetadataReference.CreateFromFile(splatAssembly.Location)); + // Add core framework references, plus Splat for testing DI attributes + var references = new List + { + MetadataReference.CreateFromFile(typeof(object).Assembly.Location), + MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), + MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location), + MetadataReference.CreateFromFile(typeof(IReadonlyDependencyResolver).Assembly.Location), + }; // Add System.Runtime reference (needed for netstandard2.0 compatibility) - var systemRuntime = AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().Name == "System.Runtime"); - if (systemRuntime != null) + var systemRuntime = TestUtilities.FindSystemRuntimeAssembly(); + if (systemRuntime is not null) { references.Add(MetadataReference.CreateFromFile(systemRuntime.Location)); } return CSharpCompilation.Create( "TestAssembly", - new[] { syntaxTree, attributeTree }, + [syntaxTree, attributeTree], references, - new CSharpCompilationOptions( + new( OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable)); } diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/AttributeOverridingMethodProxy.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AttributeOverridingMethodProxy.cs new file mode 100644 index 00000000..c066fad2 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/AttributeOverridingMethodProxy.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.Immutable; +using System.Diagnostics; +using System.Reflection; + +using Microsoft.CodeAnalysis; + +namespace Splat.DependencyInjection.Analyzer.Tests; + +/// +/// A runtime proxy for that returns a fixed set of attributes, +/// used to feed attribute shapes the compiler only produces for malformed metadata. +/// Every member other than throws. +/// +[DebuggerDisplay("AttributeOverridingMethodProxy: {Attributes.Length} attribute(s)")] +public class AttributeOverridingMethodProxy : DispatchProxy +{ + /// Gets or sets the attributes returned from . + internal ImmutableArray Attributes { get; set; } = []; + + /// Creates a method symbol whose returns the given attributes. + /// The attributes to return. + /// The proxied method symbol. + internal static IMethodSymbol Create(ImmutableArray attributes) + { + var method = Create(); + ((AttributeOverridingMethodProxy)(object)method).Attributes = attributes; + return method; + } + + /// + protected override object? Invoke(MethodInfo? targetMethod, object?[]? args) => + targetMethod?.Name == nameof(ISymbol.GetAttributes) + ? Attributes + : throw new NotSupportedException($"{targetMethod?.Name} is not supported by this test proxy."); +} diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/CodeFixTestHelper.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/CodeFixTestHelper.cs index ecf1b5d0..98595090 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/CodeFixTestHelper.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/CodeFixTestHelper.cs @@ -1,13 +1,15 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using System.Collections.Immutable; +using System.Composition.Hosting; +using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; namespace Splat.DependencyInjection.Analyzer.Tests; @@ -16,8 +18,19 @@ namespace Splat.DependencyInjection.Analyzer.Tests; /// Helper for testing code fix providers by creating compilations and applying fixes. /// Provides lightweight testing without external test framework dependencies. /// -public static class CodeFixTestHelper +internal static class CodeFixTestHelper { + /// Applies the first code fix offered for the first diagnostic and returns the result. + /// The diagnostic analyzer that detects issues. + /// The code fix provider that fixes issues. + /// The source code containing the issue to be fixed. + /// A task representing the asynchronous operation containing the fixed source code. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Task ApplyCodeFixAsync(string source) + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFixProvider : CodeFixProvider => + ApplyCodeFixAsync(source, 0); + /// /// Applies a code fix to source code and returns the result. /// Creates a compilation, runs the analyzer to get diagnostics, then applies the specified code fix. @@ -27,27 +40,28 @@ public static class CodeFixTestHelper /// The source code containing the issue to be fixed. /// The zero-based index of the code action to apply when multiple fixes are offered. /// A task representing the asynchronous operation containing the fixed source code. - /// Thrown when no code actions are registered by the provider. - /// Thrown when the code action index is invalid. - public static async Task ApplyCodeFixAsync( + /// Thrown when no code actions are registered by the provider. + /// Thrown when the code action index is invalid. + internal static async Task ApplyCodeFixAsync( string source, - int codeActionIndex = 0) + int codeActionIndex) where TAnalyzer : DiagnosticAnalyzer, new() - where TCodeFixProvider : CodeFixProvider, new() + where TCodeFixProvider : CodeFixProvider { + ArgumentOutOfRangeException.ThrowIfNegative(codeActionIndex); + var (document, workspace) = CreateDocument(source); using var disposableWorkspace = workspace; var compilation = await document.Project.GetCompilationAsync(); var analyzer = new TAnalyzer(); - var codeFixProvider = new TCodeFixProvider(); + var codeFixProvider = GetExportedCodeFixProvider(); // Run analyzer to get diagnostics var compilationWithAnalyzers = compilation!.WithAnalyzers( - ImmutableArray.Create(analyzer)); + [analyzer]); var diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(); - var diagnostic = diagnostics.First(d => - analyzer.SupportedDiagnostics.Any(sd => sd.Id == d.Id)); + var diagnostic = FirstSupportedDiagnostic(analyzer, diagnostics); // Get code fixes var codeActions = new List(); @@ -59,33 +73,129 @@ public static async Task ApplyCodeFixAsync( await codeFixProvider.RegisterCodeFixesAsync(context); + // Apply the selected code fix + var operations = await SelectCodeAction(codeActions, codeActionIndex).GetOperationsAsync(CancellationToken.None); + var changedDocument = SingleApplyChangesOperation(operations).ChangedSolution.GetDocument(document.Id); + + // Get the fixed source code + var sourceText = await changedDocument!.GetTextAsync(); + return sourceText.ToString(); + } + + /// + /// Asks a code fix provider for fixes for a diagnostic reported at a chosen position in the source, + /// without running an analyzer, and returns the code actions it registered. + /// + /// The code fix provider under test. + /// The test source code. + /// The position in the diagnostic points at. + /// The descriptor of the diagnostic to report. + /// A task containing the code actions registered by the provider. + internal static async Task> RegisterCodeFixesAtAsync( + string source, + int position, + DiagnosticDescriptor descriptor) + where TCodeFixProvider : CodeFixProvider + { + var (document, workspace) = CreateDocument(source); + using var disposableWorkspace = workspace; + var syntaxTree = await document.GetSyntaxTreeAsync(); + var diagnostic = Diagnostic.Create(descriptor, Location.Create(syntaxTree!, new(position, 0)), "Test"); + + var codeActions = new List(); + var context = new CodeFixContext( + document, + diagnostic, + (action, _) => codeActions.Add(action), + CancellationToken.None); + + await GetExportedCodeFixProvider().RegisterCodeFixesAsync(context); + return codeActions; + } + + /// + /// Obtains a code fix provider from a MEF composition container, the way the IDE does, + /// so that its shared export is honored instead of being constructed directly. + /// + /// The exported code fix provider type. + /// The code fix provider instance created by the container. + internal static TCodeFixProvider GetExportedCodeFixProvider() + where TCodeFixProvider : CodeFixProvider + { + using var host = new ContainerConfiguration() + .WithPart() + .CreateContainer(); + return (TCodeFixProvider)host.GetExport(); + } + + /// Selects the code action at the requested index. + /// The registered code actions. + /// The zero-based index of the code action. + /// The selected code action. + /// Thrown when no code actions were registered. + /// Thrown when the index is out of range. + private static CodeAction SelectCodeAction(List codeActions, int codeActionIndex) + { if (codeActions.Count == 0) { - throw new System.InvalidOperationException("No code actions were registered by the code fix provider."); + throw new InvalidOperationException("No code actions were registered by the code fix provider."); } - if (codeActionIndex >= codeActions.Count) + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(codeActionIndex, codeActions.Count); + return codeActions[codeActionIndex]; + } + + /// Gets the first diagnostic that the analyzer declares as supported. + /// The analyzer that produced the diagnostics. + /// The diagnostics to search. + /// The first supported diagnostic. + /// Thrown when the analyzer reported no supported diagnostic. + private static Diagnostic FirstSupportedDiagnostic(DiagnosticAnalyzer analyzer, ImmutableArray diagnostics) + { + foreach (var diagnostic in diagnostics) { - throw new System.ArgumentOutOfRangeException( - nameof(codeActionIndex), - $"Code action index {codeActionIndex} is out of range. Only {codeActions.Count} code actions available."); + if (AnalyzerTestHelper.IsSupported(analyzer, diagnostic)) + { + return diagnostic; + } } - // Apply the selected code fix - var operations = await codeActions[codeActionIndex].GetOperationsAsync(CancellationToken.None); - var operation = operations.OfType().Single(); - var changedSolution = operation.ChangedSolution; - var changedDocument = changedSolution.GetDocument(document.Id); + throw new InvalidOperationException("The analyzer reported no supported diagnostic."); + } - // Get the fixed source code - var sourceText = await changedDocument!.GetTextAsync(); - return sourceText.ToString(); + /// Gets the single from a code action's operations. + /// The code action operations. + /// The single apply-changes operation. + /// Thrown when there is not exactly one apply-changes operation. + private static ApplyChangesOperation SingleApplyChangesOperation(ImmutableArray operations) + { + for (var i = 0; i < operations.Length; i++) + { + if (operations[i] is not ApplyChangesOperation applyChanges) + { + continue; + } + + for (var j = i + 1; j < operations.Length; j++) + { + if (operations[j] is ApplyChangesOperation) + { + throw new InvalidOperationException("More than one ApplyChangesOperation was produced."); + } + } + + return applyChanges; + } + + throw new InvalidOperationException("No ApplyChangesOperation was produced."); } /// /// Creates a Document from source code with necessary references. /// The caller is responsible for disposing the returned workspace. /// + /// The test source code. + /// The test document and the workspace that owns it. private static (Document Document, AdhocWorkspace Workspace) CreateDocument(string source) { // Add the attribute definitions and SplatRegistrations class so the analyzer can find them @@ -132,13 +242,12 @@ public static void RegisterConstant(T instance, string contract) { } .AddProject(projectId, projectName, projectName, LanguageNames.CSharp) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)) - .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(System.Attribute).Assembly.Location)) - .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(Splat.IReadonlyDependencyResolver).Assembly.Location)); + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location)) + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(IReadonlyDependencyResolver).Assembly.Location)); // Add System.Runtime reference - var systemRuntime = System.AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().Name == "System.Runtime"); - if (systemRuntime != null) + var systemRuntime = TestUtilities.FindSystemRuntimeAssembly(); + if (systemRuntime is not null) { solution = solution.AddMetadataReference(projectId, MetadataReference.CreateFromFile(systemRuntime.Location)); } diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorAnalyzerTests.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorAnalyzerTests.cs index 2cb284b6..76f10910 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorAnalyzerTests.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorAnalyzerTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace Splat.DependencyInjection.Analyzer.Tests; @@ -10,9 +10,13 @@ namespace Splat.DependencyInjection.Analyzer.Tests; /// public class ConstructorAnalyzerTests { - /// - /// Tests that Initialize throws ArgumentNullException when passed a null context. - /// + /// The diagnostic ID reported for multiple constructors without an attribute. + private const string MultipleConstructorsDiagnosticId = "SPLATDI001"; + + /// The service type name expected in diagnostic messages. + private const string ServiceTypeName = "MyService"; + + /// Tests that Initialize throws ArgumentNullException when passed a null context. /// A task representing the asynchronous test operation. [Test] public async Task Initialize_NullContext_ThrowsArgumentNullException() @@ -22,9 +26,7 @@ public async Task Initialize_NullContext_ThrowsArgumentNullException() await Assert.That(() => analyzer.Initialize(null!)).ThrowsExactly(); } - /// - /// Tests that Register with zero type arguments doesn't trigger analysis. - /// + /// Tests that Register with zero type arguments doesn't trigger analysis. /// A task representing the asynchronous test operation. [Test] public async Task RegisterWithZeroTypeArguments_NoDiagnostic() @@ -49,9 +51,7 @@ public void Configure() { await Assert.That(diagnostics.Length).IsEqualTo(0); } - /// - /// Tests that Register with three type arguments doesn't trigger analysis. - /// + /// Tests that Register with three type arguments doesn't trigger analysis. /// A task representing the asynchronous test operation. [Test] public async Task RegisterWithThreeTypeArguments_NoDiagnostic() @@ -114,7 +114,7 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); await Assert.That(diagnostics[0].GetMessage()).Contains("TestClass"); } @@ -202,7 +202,8 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); - await Assert.That(diagnostics.Length).IsEqualTo(2); + const int expectedDiagnosticCount = 2; + await Assert.That(diagnostics.Length).IsEqualTo(expectedDiagnosticCount); await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI003"); await Assert.That(diagnostics[1].Id).IsEqualTo("SPLATDI003"); } @@ -346,7 +347,7 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); } /// @@ -471,8 +472,8 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); - await Assert.That(diagnostics[0].GetMessage()).Contains("MyService"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); + await Assert.That(diagnostics[0].GetMessage()).Contains(ServiceTypeName); } /// @@ -515,8 +516,8 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); - await Assert.That(diagnostics[0].GetMessage()).Contains("MyService"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); + await Assert.That(diagnostics[0].GetMessage()).Contains(ServiceTypeName); } /// @@ -814,8 +815,8 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); - await Assert.That(diagnostics[0].GetMessage()).Contains("MyService"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); + await Assert.That(diagnostics[0].GetMessage()).Contains(ServiceTypeName); } /// @@ -862,7 +863,7 @@ public void ConfigureDI() var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI001"); - await Assert.That(diagnostics[0].GetMessage()).Contains("MyService"); + await Assert.That(diagnostics[0].Id).IsEqualTo(MultipleConstructorsDiagnosticId); + await Assert.That(diagnostics[0].GetMessage()).Contains(ServiceTypeName); } } diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorCodeFixProviderTests.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorCodeFixProviderTests.cs index c0b18d2e..a32e9a81 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorCodeFixProviderTests.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/ConstructorCodeFixProviderTests.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CodeFixes; using TUnit.Assertions; @@ -17,264 +17,256 @@ namespace Splat.DependencyInjection.Analyzer.Tests; /// public class ConstructorCodeFixProviderTests { - /// - /// Tests that the provider configuration is valid. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task Provider_Configuration_IsValid() - { - var provider = new CodeFixes.ConstructorCodeFixProvider(); + /// The attribute text the code fix inserts. + private const string ConstructorAttributeText = "[DependencyInjectionConstructor]"; - await Assert.That(provider.FixableDiagnosticIds).Contains(Splat.DependencyInjection.SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute.Id); - await Assert.That(provider.GetFixAllProvider()).IsEqualTo(WellKnownFixAllProviders.BatchFixer); - } - - /// - /// Tests that the code fix adds the DependencyInjectionConstructor attribute to the first (parameterless) constructor. - /// Verifies the code action at index 0 targets the constructor with zero parameters. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task AddAttributeToFirstConstructor_AppliesFix() - { - const string code = """ - using Splat; - using static Splat.SplatRegistrations; + /// Source with a parameterless constructor and a single-parameter constructor. + private const string TwoConstructorsSource = """ + using Splat; + using static Splat.SplatRegistrations; - namespace Test + namespace Test + { + public class TestClass { - public class TestClass + public TestClass() { - public TestClass() - { - } + } - public TestClass(IService service) - { - } + public TestClass(IService service) + { } + } - public interface IService { } + public interface IService { } - public class Startup + public class Startup + { + public void ConfigureDI() { - public void ConfigureDI() - { - Register(); - } + Register(); } } - """; + } + """; - const string expectedFixed = """ - using Splat; - using static Splat.SplatRegistrations; + /// Source with constructors taking zero, one and two parameters. + private const string ThreeConstructorsSource = """ + using Splat; + using static Splat.SplatRegistrations; - namespace Test + namespace Test + { + public class TestClass { - public class TestClass + public TestClass() { - [DependencyInjectionConstructor] - public TestClass() - { - } - - public TestClass(IService service) - { - } } - public interface IService { } + public TestClass(IService1 service1) + { + } - public class Startup + public TestClass(IService1 service1, IService2 service2) { - public void ConfigureDI() - { - Register(); - } } } - """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Select first constructor (0 parameters) + public interface IService1 { } + public interface IService2 { } - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); - } + public class Startup + { + public void ConfigureDI() + { + Register(); + } + } + } + """; - /// - /// Tests that the code fix adds the DependencyInjectionConstructor attribute to the second constructor. - /// Verifies the code action at index 1 targets the constructor with one parameter. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task AddAttributeToSecondConstructor_AppliesFix() - { - const string code = """ - using Splat; - using static Splat.SplatRegistrations; + /// Source with a static constructor alongside two instance constructors. + private const string StaticConstructorSource = """ + using Splat; + using static Splat.SplatRegistrations; - namespace Test + namespace Test + { + public class TestClass { - public class TestClass + static TestClass() { - public TestClass() - { - } + } - public TestClass(IService service) - { - } + public TestClass() + { } - public interface IService { } + public TestClass(IService service) + { + } + } - public class Startup + public interface IService { } + + public class Startup + { + public void ConfigureDI() { - public void ConfigureDI() - { - Register(); - } + Register(); } } - """; + } + """; - const string expectedFixed = """ - using Splat; - using static Splat.SplatRegistrations; + /// Source with a struct that has two constructors. + private const string StructSource = """ + using Splat; + using static Splat.SplatRegistrations; - namespace Test + namespace Test + { + public struct TestStruct { - public class TestClass + public TestStruct(IService service) { - public TestClass() - { - } + } - [DependencyInjectionConstructor] - public TestClass(IService service) - { - } + public TestStruct(IService service, int value) + { } + } - public interface IService { } + public interface IService { } - public class Startup + public class Startup + { + public void ConfigureDI() { - public void ConfigureDI() - { - Register(); - } + Register(); } } - """; + } + """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 1); // Select second constructor (1 parameter) + /// Source whose first constructor already has an [Obsolete] attribute. + private const string ObsoleteConstructorSource = """ + using Splat; + using static Splat.SplatRegistrations; + using System; - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); - } + namespace Test + { + public class TestClass + { + [Obsolete] + public TestClass() + { + } - /// - /// Tests that the code fix works with a class that has multiple constructors with different parameter counts. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task MultipleConstructorsWithDifferentParameterCounts_AppliesFix() - { - const string code = """ - using Splat; - using static Splat.SplatRegistrations; + public TestClass(IService service) + { + } + } - namespace Test + public interface IService { } + + public class Startup { - public class TestClass + public void ConfigureDI() { - public TestClass() - { - } + Register(); + } + } + } + """; - public TestClass(IService1 service1) - { - } + /// Source whose constructors have XML documentation. + private const string XmlDocumentedConstructorsSource = """ + using Splat; + using static Splat.SplatRegistrations; - public TestClass(IService1 service1, IService2 service2) - { - } + namespace Test + { + public class TestClass + { + /// + /// Default constructor. + /// + public TestClass() + { } - public interface IService1 { } - public interface IService2 { } - - public class Startup + /// + /// Constructor with service. + /// + public TestClass(IService service) { - public void ConfigureDI() - { - Register(); - } } } - """; - const string expectedFixed = """ - using Splat; - using static Splat.SplatRegistrations; + public interface IService { } - namespace Test + public class Startup { - public class TestClass + public void ConfigureDI() { - public TestClass() - { - } + Register(); + } + } + } + """; - public TestClass(IService1 service1) - { - } + /// Source with two internal constructors. + private const string InternalConstructorsSource = """ + using Splat; + using static Splat.SplatRegistrations; - [DependencyInjectionConstructor] - public TestClass(IService1 service1, IService2 service2) - { - } + namespace Test + { + public class TestClass + { + internal TestClass() + { } - public interface IService1 { } - public interface IService2 { } + internal TestClass(IService service) + { + } + } - public class Startup + public interface IService { } + + public class Startup + { + public void ConfigureDI() { - public void ConfigureDI() - { - Register(); - } + Register(); } } - """; + } + """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 2); // Select third constructor (2 parameters) + /// Tests that the provider configuration is valid. + /// A task representing the asynchronous operation. + [Test] + public async Task Provider_Configuration_IsValid() + { + var provider = CodeFixTestHelper.GetExportedCodeFixProvider(); - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + await Assert.That(provider.FixableDiagnosticIds).Contains(Splat.DependencyInjection.SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute.Id); + await Assert.That(provider.GetFixAllProvider()).IsEqualTo(WellKnownFixAllProviders.BatchFixer); } /// - /// Tests that static constructors are ignored by the code fix provider. + /// Tests that the code fix adds the DependencyInjectionConstructor attribute to the first (parameterless) constructor. + /// Verifies the code action at index 0 targets the constructor with zero parameters. /// /// A task representing the asynchronous test operation. [Test] - public async Task ClassWithStaticConstructor_IgnoresStaticConstructor() + public async Task AddAttributeToFirstConstructor_AppliesFix() { - const string code = """ + const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; @@ -282,10 +274,7 @@ namespace Test { public class TestClass { - static TestClass() - { - } - + [DependencyInjectionConstructor] public TestClass() { } @@ -307,6 +296,18 @@ public void ConfigureDI() } """; + // Select first constructor (0 parameters) + await AssertFixAppliedAsync(TwoConstructorsSource, expectedFixed, codeActionIndex: 0); + } + + /// + /// Tests that the code fix adds the DependencyInjectionConstructor attribute to the second constructor. + /// Verifies the code action at index 1 targets the constructor with one parameter. + /// + /// A task representing the asynchronous test operation. + [Test] + public async Task AddAttributeToSecondConstructor_AppliesFix() + { const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; @@ -315,15 +316,11 @@ namespace Test { public class TestClass { - static TestClass() - { - } - - [DependencyInjectionConstructor] public TestClass() { } + [DependencyInjectionConstructor] public TestClass(IService service) { } @@ -341,107 +338,72 @@ public void ConfigureDI() } """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Should select first non-static constructor - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + // Select second constructor (1 parameter) + await AssertFixAppliedAsync(TwoConstructorsSource, expectedFixed, codeActionIndex: 1); } - /// - /// Tests that the code fix works with structs that have multiple constructors. - /// + /// Tests that the code fix works with a class that has multiple constructors with different parameter counts. /// A task representing the asynchronous test operation. [Test] - public async Task StructWithMultipleConstructors_AppliesFix() + public async Task MultipleConstructorsWithDifferentParameterCounts_AppliesFix() { - const string code = """ + const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; namespace Test { - public struct TestStruct + public class TestClass { - public TestStruct(IService service) - { - } - - public TestStruct(IService service, int value) + public TestClass() { } - } - public interface IService { } - - public class Startup - { - public void ConfigureDI() + public TestClass(IService1 service1) { - Register(); } - } - } - """; - const string expectedFixed = """ - using Splat; - using static Splat.SplatRegistrations; - - namespace Test - { - public struct TestStruct - { [DependencyInjectionConstructor] - public TestStruct(IService service) - { - } - - public TestStruct(IService service, int value) + public TestClass(IService1 service1, IService2 service2) { } } - public interface IService { } + public interface IService1 { } + public interface IService2 { } public class Startup { public void ConfigureDI() { - Register(); + Register(); } } } """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Select first constructor - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + // Select third constructor (2 parameters) + await AssertFixAppliedAsync(ThreeConstructorsSource, expectedFixed, codeActionIndex: 2); } - /// - /// Tests that the code fix adds the attribute to a constructor that already has other attributes. - /// + /// Tests that static constructors are ignored by the code fix provider. /// A task representing the asynchronous test operation. [Test] - public async Task ConstructorWithExistingAttribute_AddsAttribute() + public async Task ClassWithStaticConstructor_IgnoresStaticConstructor() { - const string code = """ + const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; - using System; namespace Test { public class TestClass { - [Obsolete] + static TestClass() + { + } + + [DependencyInjectionConstructor] public TestClass() { } @@ -463,22 +425,29 @@ public void ConfigureDI() } """; + // Should select first non-static constructor + await AssertFixAppliedAsync(StaticConstructorSource, expectedFixed, codeActionIndex: 0); + } + + /// Tests that the code fix works with structs that have multiple constructors. + /// A task representing the asynchronous test operation. + [Test] + public async Task StructWithMultipleConstructors_AppliesFix() + { const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; - using System; namespace Test { - public class TestClass + public struct TestStruct { [DependencyInjectionConstructor] - [Obsolete] - public TestClass() + public TestStruct(IService service) { } - public TestClass(IService service) + public TestStruct(IService service, int value) { } } @@ -489,46 +458,36 @@ public class Startup { public void ConfigureDI() { - Register(); + Register(); } } } """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Select first constructor - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + // Select first constructor + await AssertFixAppliedAsync(StructSource, expectedFixed, codeActionIndex: 0); } - /// - /// Tests that the code fix works with constructors that have XML documentation. - /// + /// Tests that the code fix adds the attribute to a constructor that already has other attributes. /// A task representing the asynchronous test operation. [Test] - public async Task ConstructorWithXmlDocumentation_AppliesFix() + public async Task ConstructorWithExistingAttribute_AddsAttribute() { - const string code = """ + const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; + using System; namespace Test { public class TestClass { - /// - /// Default constructor. - /// + [DependencyInjectionConstructor] + [Obsolete] public TestClass() { } - /// - /// Constructor with service. - /// public TestClass(IService service) { } @@ -546,6 +505,15 @@ public void ConfigureDI() } """; + // Select first constructor + await AssertFixAppliedAsync(ObsoleteConstructorSource, expectedFixed, codeActionIndex: 0); + } + + /// Tests that the code fix works with constructors that have XML documentation. + /// A task representing the asynchronous test operation. + [Test] + public async Task ConstructorWithXmlDocumentation_AppliesFix() + { const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; @@ -582,51 +550,15 @@ public void ConfigureDI() } """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Select first constructor - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + // Select first constructor + await AssertFixAppliedAsync(XmlDocumentedConstructorsSource, expectedFixed, codeActionIndex: 0); } - /// - /// Tests that the code fix works with internal constructors. - /// + /// Tests that the code fix works with internal constructors. /// A task representing the asynchronous test operation. [Test] public async Task InternalConstructors_AppliesFix() { - const string code = """ - using Splat; - using static Splat.SplatRegistrations; - - namespace Test - { - public class TestClass - { - internal TestClass() - { - } - - internal TestClass(IService service) - { - } - } - - public interface IService { } - - public class Startup - { - public void ConfigureDI() - { - Register(); - } - } - } - """; - const string expectedFixed = """ using Splat; using static Splat.SplatRegistrations; @@ -657,13 +589,8 @@ public void ConfigureDI() } """; - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.ConstructorAnalyzer, - CodeFixes.ConstructorCodeFixProvider>( - code, - codeActionIndex: 0); // Select first constructor - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + // Select first constructor + await AssertFixAppliedAsync(InternalConstructorsSource, expectedFixed, codeActionIndex: 0); } /// @@ -694,12 +621,10 @@ public void Configure() { Analyzers.ConstructorAnalyzer, CodeFixes.ConstructorCodeFixProvider>(code); - await Assert.That(fixedCode).Contains("[DependencyInjectionConstructor]"); + await Assert.That(fixedCode).Contains(ConstructorAttributeText); } - /// - /// Tests that ConstructorCodeFixProvider works when constructor has existing attributes but no leading trivia. - /// + /// Tests that ConstructorCodeFixProvider works when constructor has existing attributes but no leading trivia. /// A task representing the asynchronous operation. [Test] public async Task ConstructorCodeFix_ExistingAttribute_NoLeadingTrivia() @@ -725,7 +650,7 @@ public void Configure() { Analyzers.ConstructorAnalyzer, CodeFixes.ConstructorCodeFixProvider>(code); - await Assert.That(fixedCode).Contains("[DependencyInjectionConstructor]"); + await Assert.That(fixedCode).Contains(ConstructorAttributeText); await Assert.That(fixedCode).Contains("[Obsolete]public TestClass()"); } @@ -768,7 +693,7 @@ public void ConfigureDI() Analyzers.ConstructorAnalyzer, CodeFixes.ConstructorCodeFixProvider>(code); - await Assert.That(fixedCode).Contains("[DependencyInjectionConstructor]"); + await Assert.That(fixedCode).Contains(ConstructorAttributeText); } /// @@ -790,12 +715,12 @@ public Foo() { } var (document, workspace) = CreateSimpleDocument(source); using var disposableWorkspace = workspace; var root = await document.GetSyntaxRootAsync(); - var constructor = root!.DescendantNodes().OfType().First(); + var constructor = TestUtilities.FirstDescendant(root!); var result = await CodeFixes.ConstructorCodeFixProvider.AddAttributeAsync(document, constructor, CancellationToken.None); var resultText = (await result.GetTextAsync()).ToString(); - await Assert.That(resultText).Contains("[DependencyInjectionConstructor]"); + await Assert.That(resultText).Contains(ConstructorAttributeText); await Assert.That(resultText).Contains("/// My ctor."); } @@ -812,12 +737,12 @@ public async Task AddAttributeAsync_ConstructorWithNoTrivia_AddsAttribute() var (document, workspace) = CreateSimpleDocument(source); using var disposableWorkspace = workspace; var root = await document.GetSyntaxRootAsync(); - var constructor = root!.DescendantNodes().OfType().First(); + var constructor = TestUtilities.FirstDescendant(root!); var result = await CodeFixes.ConstructorCodeFixProvider.AddAttributeAsync(document, constructor, CancellationToken.None); var resultText = (await result.GetTextAsync()).ToString(); - await Assert.That(resultText).Contains("[DependencyInjectionConstructor]"); + await Assert.That(resultText).Contains(ConstructorAttributeText); } /// @@ -841,15 +766,44 @@ public Foo() { } var (document, workspace) = CreateSimpleDocument(source); using var disposableWorkspace = workspace; var root = await document.GetSyntaxRootAsync(); - var constructor = root!.DescendantNodes().OfType().First(); + var constructor = TestUtilities.FirstDescendant(root!); var result = await CodeFixes.ConstructorCodeFixProvider.AddAttributeAsync(document, constructor, CancellationToken.None); var resultText = (await result.GetTextAsync()).ToString(); - await Assert.That(resultText).Contains("[DependencyInjectionConstructor]"); + await Assert.That(resultText).Contains(ConstructorAttributeText); await Assert.That(resultText).Contains("[Obsolete]"); } + /// Tests that no code fix is offered when the diagnostic points outside any type declaration. + /// A task representing the asynchronous operation. + [Test] + public async Task DiagnosticOutsideTypeDeclaration_RegistersNoFix() + { + var codeActions = await CodeFixTestHelper.RegisterCodeFixesAtAsync( + TwoConstructorsSource, + 0, + Splat.DependencyInjection.SourceGenerator.DiagnosticWarnings.MultipleConstructorNeedAttribute); + + await Assert.That(codeActions).IsEmpty(); + } + + /// Applies the constructor code fix and asserts the result matches the expected source. + /// The source code containing the diagnostic. + /// The expected source after the fix is applied. + /// The zero-based index of the code action to apply. + /// A task representing the asynchronous operation. + private static async Task AssertFixAppliedAsync(string code, string expectedFixed, int codeActionIndex) + { + var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< + Analyzers.ConstructorAnalyzer, + CodeFixes.ConstructorCodeFixProvider>( + code, + codeActionIndex); + + await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); + } + /// /// Creates a simple Document from source code for direct unit testing. /// The caller is responsible for disposing the returned workspace. @@ -858,15 +812,15 @@ public Foo() { } /// A tuple containing the Document and the AdhocWorkspace that must be disposed by the caller. private static (Document Document, AdhocWorkspace Workspace) CreateSimpleDocument(string source) { - var projectId = ProjectId.CreateNewId("TestProject"); + const string projectName = "TestProject"; + var projectId = ProjectId.CreateNewId(projectName); var workspace = new AdhocWorkspace(); var solution = workspace.CurrentSolution - .AddProject(projectId, "TestProject", "TestProject", LanguageNames.CSharp) + .AddProject(projectId, projectName, projectName, LanguageNames.CSharp) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - var systemRuntime = System.AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().Name == "System.Runtime"); - if (systemRuntime != null) + var systemRuntime = TestUtilities.FindSystemRuntimeAssembly(); + if (systemRuntime is not null) { solution = solution.AddMetadataReference(projectId, MetadataReference.CreateFromFile(systemRuntime.Location)); } @@ -876,4 +830,4 @@ private static (Document Document, AdhocWorkspace Workspace) CreateSimpleDocumen .AddDocument("Test.cs", source); return (document, workspace); } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/NullClassAttributeData.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/NullClassAttributeData.cs new file mode 100644 index 00000000..5e6fec25 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/NullClassAttributeData.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.Immutable; + +using Microsoft.CodeAnalysis; + +namespace Splat.DependencyInjection.Analyzer.Tests; + +/// +/// Attribute data with no attribute class or constructor, matching what the compiler produces +/// for a metadata attribute whose constructor cannot be decoded. +/// +internal sealed class NullClassAttributeData : AttributeData +{ + /// + protected override INamedTypeSymbol? CommonAttributeClass => null; + + /// + protected override IMethodSymbol? CommonAttributeConstructor => null; + + /// + protected override SyntaxReference? CommonApplicationSyntaxReference => null; + + /// + protected override ImmutableArray CommonConstructorArguments => []; + + /// + protected override ImmutableArray> CommonNamedArguments => []; +} diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyAnalyzerTests.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyAnalyzerTests.cs index a38648fd..189afd89 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyAnalyzerTests.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyAnalyzerTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using Microsoft.CodeAnalysis.Diagnostics; @@ -12,6 +12,9 @@ namespace Splat.DependencyInjection.Analyzer.Tests; /// public class PropertyAnalyzerTests { + /// The diagnostic ID reported for properties without an accessible setter. + private const string PropertySetterDiagnosticId = "SPLATDI002"; + /// /// Tests that a property with a private setter triggers diagnostic SPLATDI002. /// Properties marked for dependency injection must have accessible setters. @@ -39,7 +42,7 @@ public interface IService { } var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI002"); + await Assert.That(diagnostics[0].Id).IsEqualTo(PropertySetterDiagnosticId); await Assert.That(diagnostics[0].GetMessage()).Contains("TestClass.Service"); } @@ -70,7 +73,7 @@ public interface IService { } var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI002"); + await Assert.That(diagnostics[0].Id).IsEqualTo(PropertySetterDiagnosticId); } /// @@ -183,7 +186,7 @@ public interface IService { } var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI002"); + await Assert.That(diagnostics[0].Id).IsEqualTo(PropertySetterDiagnosticId); } /// @@ -242,12 +245,10 @@ public interface IService { } var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); await Assert.That(diagnostics.Length).IsEqualTo(1); - await Assert.That(diagnostics[0].Id).IsEqualTo("SPLATDI002"); + await Assert.That(diagnostics[0].Id).IsEqualTo(PropertySetterDiagnosticId); } - /// - /// Tests that multiple properties with issues all report diagnostics. - /// + /// Tests that multiple properties with issues all report diagnostics. /// A task representing the asynchronous test operation. [Test] public async Task MultiplePropertiesWithIssues_ReportMultipleDiagnostics() @@ -276,13 +277,15 @@ public interface IService { } var diagnostics = await AnalyzerTestHelper.GetDiagnosticsAsync(code); - await Assert.That(diagnostics.Length).IsEqualTo(2); - await Assert.That(diagnostics.All(d => d.Id == "SPLATDI002")).IsTrue(); + const int expectedDiagnosticCount = 2; + await Assert.That(diagnostics.Length).IsEqualTo(expectedDiagnosticCount); + foreach (var diagnostic in diagnostics) + { + await Assert.That(diagnostic.Id).IsEqualTo(PropertySetterDiagnosticId); + } } - /// - /// Tests that if the attribute is missing from compilation, no analysis happens. - /// + /// Tests that if the attribute is missing from compilation, no analysis happens. /// A task representing the asynchronous test operation. [Test] public async Task AttributeMissingFromCompilation_NoDiagnostic() @@ -306,8 +309,7 @@ public interface IService { } .AddReferences(Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); var compilationWithAnalyzers = compilation.WithAnalyzers( - System.Collections.Immutable.ImmutableArray.Create( - new Analyzers.PropertyAnalyzer())); + [new Analyzers.PropertyAnalyzer()]); var diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(); @@ -315,19 +317,15 @@ public interface IService { } await Assert.That(diagnostics).IsEmpty(); } - /// - /// Tests that Initialize throws ArgumentNullException when context is null. - /// + /// Tests that Initialize throws ArgumentNullException when context is null. [Test] public void Initialize_NullContext_ThrowsArgumentNullException() { var analyzer = new Analyzers.PropertyAnalyzer(); - Assert.Throws(() => analyzer.Initialize(null!)); + _ = Assert.Throws(() => analyzer.Initialize(null!)); } - /// - /// Tests that a property with a different attribute does not trigger diagnostics. - /// + /// Tests that a property with a different attribute does not trigger diagnostics. /// A task representing the asynchronous test operation. [Test] public async Task PropertyWithOtherAttribute_NoDiagnostic() diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyCodeFixProviderTests.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyCodeFixProviderTests.cs index 26ef69cf..a7a7822e 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyCodeFixProviderTests.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/PropertyCodeFixProviderTests.cs @@ -1,10 +1,13 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using Microsoft.CodeAnalysis.CodeFixes; +using System.Runtime.CompilerServices; + +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CodeFixes; namespace Splat.DependencyInjection.Analyzer.Tests; @@ -14,14 +17,21 @@ namespace Splat.DependencyInjection.Analyzer.Tests; /// public class PropertyCodeFixProviderTests { - /// - /// Tests that the provider configuration is valid. - /// + /// Source declaring a getter-only property. + private const string GetterOnlyPropertySource = "public class C { public int Foo { get; } }"; + + /// The text of the internal keyword. + private const string InternalKeywordText = "internal"; + + /// The number of accessors on a property with a getter and a setter. + private const int GetterAndSetterCount = 2; + + /// Tests that the provider configuration is valid. /// A task representing the asynchronous operation. [Test] public async Task Provider_Configuration_IsValid() { - var provider = new CodeFixes.PropertyCodeFixProvider(); + var provider = CodeFixTestHelper.GetExportedCodeFixProvider(); await Assert.That(provider.FixableDiagnosticIds).Contains(Splat.DependencyInjection.SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable.Id); await Assert.That(provider.GetFixAllProvider()).IsEqualTo(WellKnownFixAllProviders.BatchFixer); @@ -227,9 +237,7 @@ public interface IService { } await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); } - /// - /// Tests that the code fix adds an internal setter to an expression-bodied property. - /// + /// Tests that the code fix adds an internal setter to an expression-bodied property. /// A task representing the asynchronous test operation. [Test] public async Task ExpressionBodiedProperty_AddInternalSetter() @@ -279,9 +287,7 @@ public interface IService { } await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); } - /// - /// Tests that the code fix adds a setter to a property with internal modifier where setter doesn't need explicit modifier. - /// + /// Tests that the code fix adds a setter to a property with internal modifier where setter doesn't need explicit modifier. /// A task representing the asynchronous test operation. [Test] public async Task InternalPropertyWithNoSetter_AddSetterWithoutModifier() @@ -327,9 +333,7 @@ public interface IService { } await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); } - /// - /// Tests that the code fix adds an internal setter to a read-only property. - /// + /// Tests that the code fix adds an internal setter to a read-only property. /// A task representing the asynchronous test operation. [Test] public async Task PropertyWithNoSetter_AddInternalSetter() @@ -375,10 +379,7 @@ public interface IService { } await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); } - /// - /// Tests that the code fix changes a protected setter to public. - /// Validates the code fix can handle protected setters. - /// + /// Tests that the code fix changes a protected setter to public. Validates the code fix can handle protected setters. /// A task representing the asynchronous test operation. [Test] public async Task ProtectedSetter_ChangeToPublic() @@ -424,9 +425,7 @@ public interface IService { } await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); } - /// - /// Tests that the code fix changes a protected setter to internal. - /// + /// Tests that the code fix changes a protected setter to internal. /// A task representing the asynchronous test operation. [Test] public async Task ProtectedSetter_ChangeToInternal() @@ -478,118 +477,71 @@ public interface IService { } /// /// A task representing the asynchronous test operation. [Test] - public async Task PublicPropertyWithNoSetter_AddPublicSetterWithoutModifier() - { - const string code = """ - using Splat; - using static Splat.SplatRegistrations; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Task PublicPropertyWithNoSetter_AddPublicSetterWithoutModifier() => + PropertyWithNoSetter_AddPublicSetter(); - namespace Test - { - public class TestClass - { - [DependencyInjectionProperty] - public IService Service { get; } - } - - public interface IService { } - } - """; - - const string expectedFixed = """ - using Splat; - using static Splat.SplatRegistrations; - - namespace Test - { - public class TestClass - { - [DependencyInjectionProperty] - public IService Service { get; set; } - } - - public interface IService { } - } - """; - - var actualFixed = await CodeFixTestHelper.ApplyCodeFixAsync< - Analyzers.PropertyAnalyzer, - CodeFixes.PropertyCodeFixProvider>( - code, - codeActionIndex: 0); // "Add public setter" - - await Assert.That(TestUtilities.AreEquivalent(expectedFixed, actualFixed)).IsTrue(); - } - - /// - /// Verifies BuildSetterModifiers returns empty token list when property already has the same modifier. - /// + /// Verifies BuildSetterModifiers returns empty token list when property already has the same modifier. /// A task representing the asynchronous operation. [Test] public async Task BuildSetterModifiers_PropertyHasSameModifier_ReturnsEmpty() { - var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; } }"); + var tree = CSharpSyntaxTree.ParseText(GetterOnlyPropertySource); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var result = CodeFixes.PropertyCodeFixProvider.BuildSetterModifiers(property, SyntaxKind.PublicKeyword); await Assert.That(result.Count).IsEqualTo(0); } - /// - /// Verifies BuildSetterModifiers returns modifier when property has different accessibility. - /// + /// Verifies BuildSetterModifiers returns modifier when property has different accessibility. /// A task representing the asynchronous operation. [Test] public async Task BuildSetterModifiers_PropertyHasDifferentModifier_ReturnsModifier() { - var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; } }"); + var tree = CSharpSyntaxTree.ParseText(GetterOnlyPropertySource); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var result = CodeFixes.PropertyCodeFixProvider.BuildSetterModifiers(property, SyntaxKind.InternalKeyword); await Assert.That(result.Count).IsEqualTo(1); - await Assert.That(result[0].Text).IsEqualTo("internal"); + await Assert.That(result[0].Text).IsEqualTo(InternalKeywordText); } - /// - /// Verifies ConvertExpressionBodiedProperty transforms to accessor list with getter and setter. - /// + /// Verifies ConvertExpressionBodiedProperty transforms to accessor list with getter and setter. /// A task representing the asynchronous operation. [Test] public async Task ConvertExpressionBodiedProperty_CreatesGetterAndSetter() { var tree = CSharpSyntaxTree.ParseText("public class C { private int _f; public int Foo => _f; }"); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var setterModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.InternalKeyword)); var result = CodeFixes.PropertyCodeFixProvider.ConvertExpressionBodiedProperty(property, setterModifiers); await Assert.That(result.AccessorList).IsNotNull(); await Assert.That(result.ExpressionBody).IsNull(); - await Assert.That(result.AccessorList!.Accessors.Count).IsEqualTo(2); + await Assert.That(result.AccessorList!.Accessors.Count).IsEqualTo(GetterAndSetterCount); var getter = result.AccessorList.Accessors[0]; var setter = result.AccessorList.Accessors[1]; await Assert.That(getter.Kind()).IsEqualTo(SyntaxKind.GetAccessorDeclaration); await Assert.That(setter.Kind()).IsEqualTo(SyntaxKind.SetAccessorDeclaration); await Assert.That(setter.Modifiers.Count).IsEqualTo(1); - await Assert.That(setter.Modifiers[0].Text).IsEqualTo("internal"); + await Assert.That(setter.Modifiers[0].Text).IsEqualTo(InternalKeywordText); } - /// - /// Verifies ConvertExpressionBodiedProperty with empty modifiers produces setter without modifier. - /// + /// Verifies ConvertExpressionBodiedProperty with empty modifiers produces setter without modifier. /// A task representing the asynchronous operation. [Test] public async Task ConvertExpressionBodiedProperty_EmptyModifiers_NoSetterModifier() { var tree = CSharpSyntaxTree.ParseText("public class C { private int _f; public int Foo => _f; }"); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var setterModifiers = SyntaxFactory.TokenList(); var result = CodeFixes.PropertyCodeFixProvider.ConvertExpressionBodiedProperty(property, setterModifiers); @@ -599,38 +551,34 @@ public async Task ConvertExpressionBodiedProperty_EmptyModifiers_NoSetterModifie await Assert.That(setter.Modifiers.Count).IsEqualTo(0); } - /// - /// Verifies AddSetterToGetterOnlyProperty adds a setter to a getter-only property. - /// + /// Verifies AddSetterToGetterOnlyProperty adds a setter to a getter-only property. /// A task representing the asynchronous operation. [Test] public async Task AddSetterToGetterOnlyProperty_AddsSetter() { - var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; } }"); + var tree = CSharpSyntaxTree.ParseText(GetterOnlyPropertySource); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var setterModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.InternalKeyword)); var result = CodeFixes.PropertyCodeFixProvider.AddSetterToGetterOnlyProperty(property, setterModifiers); - await Assert.That(result.AccessorList!.Accessors.Count).IsEqualTo(2); + await Assert.That(result.AccessorList!.Accessors.Count).IsEqualTo(GetterAndSetterCount); var setter = result.AccessorList.Accessors[1]; await Assert.That(setter.Kind()).IsEqualTo(SyntaxKind.SetAccessorDeclaration); await Assert.That(setter.Modifiers.Count).IsEqualTo(1); - await Assert.That(setter.Modifiers[0].Text).IsEqualTo("internal"); + await Assert.That(setter.Modifiers[0].Text).IsEqualTo(InternalKeywordText); } - /// - /// Verifies AddSetterToGetterOnlyProperty with empty modifiers adds setter without modifier. - /// + /// Verifies AddSetterToGetterOnlyProperty with empty modifiers adds setter without modifier. /// A task representing the asynchronous operation. [Test] public async Task AddSetterToGetterOnlyProperty_EmptyModifiers_NoSetterModifier() { - var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; } }"); + var tree = CSharpSyntaxTree.ParseText(GetterOnlyPropertySource); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); + var property = TestUtilities.FirstDescendant(root); var setterModifiers = SyntaxFactory.TokenList(); var result = CodeFixes.PropertyCodeFixProvider.AddSetterToGetterOnlyProperty(property, setterModifiers); @@ -640,46 +588,78 @@ public async Task AddSetterToGetterOnlyProperty_EmptyModifiers_NoSetterModifier( await Assert.That(setter.Modifiers.Count).IsEqualTo(0); } - /// - /// Verifies UpdateExistingSetterModifiers changes a private setter to internal. - /// + /// Verifies UpdateExistingSetterModifiers changes a private setter to internal. /// A task representing the asynchronous operation. [Test] public async Task UpdateExistingSetterModifiers_PrivateToInternal() { var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; private set; } }"); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); - var existingSetter = property.AccessorList!.Accessors - .First(a => a.Kind() == SyntaxKind.SetAccessorDeclaration); + var property = TestUtilities.FirstDescendant(root); + var existingSetter = FindSetter(property); var setterModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.InternalKeyword)); var result = CodeFixes.PropertyCodeFixProvider.UpdateExistingSetterModifiers(property, existingSetter, setterModifiers); - var setter = result.AccessorList!.Accessors - .First(a => a.Kind() == SyntaxKind.SetAccessorDeclaration); + var setter = FindSetter(result); await Assert.That(setter.Modifiers.Count).IsEqualTo(1); - await Assert.That(setter.Modifiers[0].Text).IsEqualTo("internal"); + await Assert.That(setter.Modifiers[0].Text).IsEqualTo(InternalKeywordText); } - /// - /// Verifies UpdateExistingSetterModifiers with empty modifiers removes the existing modifier. - /// + /// Verifies UpdateExistingSetterModifiers with empty modifiers removes the existing modifier. /// A task representing the asynchronous operation. [Test] public async Task UpdateExistingSetterModifiers_RemovesModifier() { var tree = CSharpSyntaxTree.ParseText("public class C { public int Foo { get; private set; } }"); var root = await tree.GetRootAsync(); - var property = root.DescendantNodes().OfType().First(); - var existingSetter = property.AccessorList!.Accessors - .First(a => a.Kind() == SyntaxKind.SetAccessorDeclaration); + var property = TestUtilities.FirstDescendant(root); + var existingSetter = FindSetter(property); var setterModifiers = SyntaxFactory.TokenList(); var result = CodeFixes.PropertyCodeFixProvider.UpdateExistingSetterModifiers(property, existingSetter, setterModifiers); - var setter = result.AccessorList!.Accessors - .First(a => a.Kind() == SyntaxKind.SetAccessorDeclaration); + var setter = FindSetter(result); await Assert.That(setter.Modifiers.Count).IsEqualTo(0); } -} \ No newline at end of file + + /// Tests that no code fix is offered when the diagnostic points outside any property declaration. + /// A task representing the asynchronous operation. + [Test] + public async Task DiagnosticOutsideProperty_RegistersNoFix() + { + const string code = """ + namespace Test + { + public class TestClass + { + public int Value { get; private set; } + } + } + """; + + var codeActions = await CodeFixTestHelper.RegisterCodeFixesAtAsync( + code, + code.IndexOf("TestClass", StringComparison.Ordinal), + Splat.DependencyInjection.SourceGenerator.DiagnosticWarnings.PropertyMustPublicBeSettable); + + await Assert.That(codeActions).IsEmpty(); + } + + /// Finds the set accessor of a property. + /// The property declaration. + /// The set accessor. + /// Thrown when the property has no set accessor. + private static AccessorDeclarationSyntax FindSetter(PropertyDeclarationSyntax property) + { + foreach (var accessor in property.AccessorList!.Accessors) + { + if (accessor.IsKind(SyntaxKind.SetAccessorDeclaration)) + { + return accessor; + } + } + + throw new InvalidOperationException("The property has no set accessor."); + } +} diff --git a/src/tests/Splat.DependencyInjection.Analyzer.Tests/TestUtilities.cs b/src/tests/Splat.DependencyInjection.Analyzer.Tests/TestUtilities.cs index b5c81382..e6476378 100644 --- a/src/tests/Splat.DependencyInjection.Analyzer.Tests/TestUtilities.cs +++ b/src/tests/Splat.DependencyInjection.Analyzer.Tests/TestUtilities.cs @@ -1,13 +1,16 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System.Reflection; +using System.Runtime.CompilerServices; + +using Microsoft.CodeAnalysis; + namespace Splat.DependencyInjection.Analyzer.Tests; -/// -/// Utilities for testing analyzers and code fixes. -/// -public static class TestUtilities +/// Utilities for testing analyzers and code fixes. +internal static class TestUtilities { /// /// Normalizes whitespace and line endings in source code for comparison. @@ -15,54 +18,69 @@ public static class TestUtilities /// /// The source code to normalize. /// Normalized source code suitable for comparison. - public static string NormalizeWhitespace(string source) + internal static string NormalizeWhitespace(string source) { ArgumentException.ThrowIfNullOrWhiteSpace(source); - return string.Join( - "\n", - source.Split(new[] { "\r\n", "\r", "\n" }, System.StringSplitOptions.None) - .Select(line => line.Trim())); + var lines = source.Split(["\r\n", "\r", "\n"], StringSplitOptions.None); + for (var i = 0; i < lines.Length; i++) + { + lines[i] = lines[i].Trim(); + } + + return string.Join('\n', lines); } /// /// Compares two source code strings with whitespace normalization. /// Ignores differences in line endings and per-line leading/trailing whitespace. - /// Outputs expected and actual to console when they don't match for easier debugging. + /// Writes expected and actual to the current test's output when they don't match for easier debugging. + /// + /// The expected source code. + /// The actual source code. + /// True if the sources are equivalent after normalization. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AreEquivalent(string expected, string actual) => + AreEquivalent(expected, actual, TestContext.Current?.OutputWriter ?? TextWriter.Null); + + /// + /// Compares two source code strings with whitespace normalization. + /// Ignores differences in line endings and per-line leading/trailing whitespace. + /// Writes expected and actual to when they don't match for easier debugging. /// /// The expected source code. /// The actual source code. + /// The writer that receives the failure details. /// True if the sources are equivalent after normalization. - public static bool AreEquivalent(string expected, string actual) + internal static bool AreEquivalent(string expected, string actual, TextWriter output) { ArgumentException.ThrowIfNullOrWhiteSpace(expected); ArgumentException.ThrowIfNullOrWhiteSpace(actual); + ArgumentNullException.ThrowIfNull(output); var result = NormalizeWhitespace(expected) == NormalizeWhitespace(actual); if (!result) { - System.Console.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); - System.Console.WriteLine("║ TEST FAILURE: Source code comparison failed ║"); - System.Console.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); - System.Console.WriteLine(); - System.Console.WriteLine("=== EXPECTED ==="); - System.Console.WriteLine(expected); - System.Console.WriteLine(); - System.Console.WriteLine("=== ACTUAL ==="); - System.Console.WriteLine(actual); - System.Console.WriteLine(); - System.Console.WriteLine("═══════════════════════════════════════════════════════════════"); + output.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); + output.WriteLine("║ TEST FAILURE: Source code comparison failed ║"); + output.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); + output.WriteLine(); + output.WriteLine("=== EXPECTED ==="); + output.WriteLine(expected); + output.WriteLine(); + output.WriteLine("=== ACTUAL ==="); + output.WriteLine(actual); + output.WriteLine(); + output.WriteLine("═══════════════════════════════════════════════════════════════"); } return result; } - /// - /// Gets the first difference between two normalized source code strings for debugging. - /// + /// Gets the first difference between two normalized source code strings for debugging. /// The expected source code. /// The actual source code. /// Description of the first difference, or empty string if sources are equivalent. - public static string GetFirstDifference(string expected, string actual) + internal static string GetFirstDifference(string expected, string actual) { var normalizedExpected = NormalizeWhitespace(expected); var normalizedActual = NormalizeWhitespace(actual); @@ -88,4 +106,95 @@ public static string GetFirstDifference(string expected, string actual) return "Sources differ but no specific line difference found"; } + + /// Finds the loaded System.Runtime assembly, if any. + /// The System.Runtime assembly, or when it is not loaded. + internal static Assembly? FindSystemRuntimeAssembly() + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + if (assembly.GetName().Name == "System.Runtime") + { + return assembly; + } + } + + return null; + } + + /// Gets the first descendant node of the requested type. + /// The syntax node type to find. + /// The node to search beneath. + /// The first matching descendant. + /// Thrown when no matching node exists. + internal static TNode FirstDescendant(SyntaxNode root) + where TNode : SyntaxNode + { + ArgumentNullException.ThrowIfNull(root); + foreach (var node in root.DescendantNodes()) + { + if (node is TNode match) + { + return match; + } + } + + throw new InvalidOperationException($"No {typeof(TNode).Name} found."); + } + + /// Gets the first method with the given name declared on a type. + /// The type to search. + /// The method name. + /// The first matching method. + /// Thrown when no matching method exists. + internal static IMethodSymbol FirstMethod(INamespaceOrTypeSymbol type, string name) + { + ArgumentNullException.ThrowIfNull(type); + foreach (var member in type.GetMembers(name)) + { + if (member is IMethodSymbol method) + { + return method; + } + } + + throw new InvalidOperationException($"No method named {name} found."); + } + + /// Gets the first constructor with the given number of parameters. + /// The type to search. + /// The number of parameters the constructor must have. + /// The first matching constructor. + /// Thrown when no matching constructor exists. + internal static IMethodSymbol ConstructorWithParameterCount(INamedTypeSymbol type, int parameterCount) + { + ArgumentNullException.ThrowIfNull(type); + foreach (var constructor in type.Constructors) + { + if (constructor.Parameters.Length == parameterCount) + { + return constructor; + } + } + + throw new InvalidOperationException($"No constructor with {parameterCount} parameters found."); + } + + /// Gets the first constructor that is written in source rather than implicitly declared. + /// The type to search. + /// The first explicitly declared constructor. + /// Thrown when no explicit constructor exists. + internal static IMethodSymbol FirstExplicitConstructor(INamedTypeSymbol type) + { + ArgumentNullException.ThrowIfNull(type); + foreach (var constructor in type.Constructors) + { + if (!constructor.IsImplicitlyDeclared) + { + return constructor; + } + } + + throw new InvalidOperationException("No explicit constructor found."); + } } diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/AssemblySetup.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/AssemblySetup.cs new file mode 100644 index 00000000..d8b2be1b --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/AssemblySetup.cs @@ -0,0 +1,6 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +// Snapshot tests write received files beside the snapshots, so tests run one at a time. +[assembly: NotInParallel] diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/CodeGeneratorTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/CodeGeneratorTests.cs new file mode 100644 index 00000000..a8f51cb8 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/CodeGeneratorTests.cs @@ -0,0 +1,222 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; + +using Splat.DependencyInjection.SourceGenerator.CodeGeneration; +using Splat.DependencyInjection.SourceGenerator.Models; + +namespace Splat.DependencyInjection.SourceGenerator.Tests.CodeGeneration; + +/// Tests the code writes for each shape of registration. +public sealed class CodeGeneratorTests +{ + /// The indentation of a statement in the registration method. + private const string Body = " "; + + /// The start of the factory for , as a continuation line. + private const string FactoryOfA = " () => new global::T.A(\n"; + + /// The constructed type most tests register. + private const string TypeA = "global::T.A"; + + /// A second constructed type. + private const string TypeB = "global::T.B"; + + /// The dependency most tests resolve. + private const string DependencyX = "global::T.IX"; + + /// A registration with nothing to resolve is one line, whose lambda captures nothing. + /// A task representing the asynchronous test. + [Test] + public async Task WritesParameterlessTransientOnOneLine() + { + var source = Generate(Transient(TypeA), Transient(TypeB, contract: "\"c\"")); + + await Assert.That(source).Contains( + $"{Body}resolver.Register(() => new global::T.A());\n\n{Body}resolver.Register(() => new global::T.B(), \"c\");\n"); + await Assert.That(source).DoesNotContain(CodeGenerator.ThrowNotRegistered); + } + + /// Each dependency takes its own line, and a missing one throws through the helper. + /// A task representing the asynchronous test. + [Test] + public async Task WritesDependenciesOnePerLine() + { + var registration = Transient( + TypeA, + parameters: + [ + new(DependencyX, DependencyKind.Service, null), + new("global::System.Lazy", DependencyKind.Lazy, "global::T.IY"), + new("global::System.Collections.Generic.IEnumerable", DependencyKind.Collection, "global::T.IZ"), + ], + properties: [new("P", "global::T.IP")]); + + var source = Generate(registration); + + await Assert.That(source).Contains( + Body + "resolver.Register(\n" + + Body + FactoryOfA + + Body + " resolver.GetService() ?? ThrowNotRegistered(\"global::T.IX\"),\n" + + Body + " resolver.GetService>() ?? ThrowNotRegistered>(\"global::System.Lazy\"),\n" + + Body + " resolver.GetServices())\n" + + Body + " {\n" + + Body + " P = resolver.GetService() ?? ThrowNotRegistered(\"global::T.IP\"),\n" + + Body + " });\n"); + await Assert.That(source).Contains("private static T ThrowNotRegistered(string typeName)\n"); + await Assert.That(source).DoesNotContain("string typeName, string contract"); + } + + /// Every dependency is resolved under the registration's contract. + /// A task representing the asynchronous test. + [Test] + public async Task ResolvesDependenciesUnderContract() + { + var registration = Transient( + TypeA, + contract: "global::T.Keys.Key", + parameters: + [ + new(DependencyX, DependencyKind.Service, null), + new("global::System.Collections.Generic.IEnumerable", DependencyKind.Collection, "global::T.IZ"), + ]); + + var source = Generate(registration); + + await Assert.That(source).Contains( + Body + "resolver.Register(\n" + + Body + FactoryOfA + + Body + " resolver.GetService(global::T.Keys.Key) ?? ThrowNotRegistered(\"global::T.IX\", global::T.Keys.Key),\n" + + Body + " resolver.GetServices(global::T.Keys.Key)),\n" + + Body + " global::T.Keys.Key);\n"); + await Assert.That(source).Contains("private static T ThrowNotRegistered(string typeName, string contract)\n"); + await Assert.That(source).DoesNotContain("ThrowNotRegistered(string typeName)\n"); + } + + /// A type with injected properties and no constructor parameters keeps its empty argument list. + /// A task representing the asynchronous test. + [Test] + public async Task WritesPropertiesWithoutParameters() + { + var source = Generate(Transient(TypeA, properties: [new("P", "global::T.IP")])); + + await Assert.That(source).Contains( + $"{Body} () => new global::T.A()\n{Body} {{\n"); + } + + /// A lazy singleton registers the lazy and its value, sharing one lazy numbered by its position. + /// A task representing the asynchronous test. + [Test] + public async Task WritesLazySingleton() + { + var source = Generate(LazySingleton(TypeA), LazySingleton(TypeB, contract: "\"c\"", mode: "global::System.Threading.LazyThreadSafetyMode.PublicationOnly")); + + await Assert.That(source).Contains( + Body + "var lazy0 = new global::System.Lazy(() => new global::T.A());\n" + + Body + "resolver.Register>(() => lazy0);\n" + + Body + "resolver.Register(() => lazy0.Value);\n\n" + + Body + "var lazy1 = new global::System.Lazy(() => new global::T.B(), global::System.Threading.LazyThreadSafetyMode.PublicationOnly);\n" + + Body + "resolver.Register>(() => lazy1, \"c\");\n" + + Body + "resolver.Register(() => lazy1.Value, \"c\");\n"); + } + + /// A lazy singleton with dependencies writes its factory and mode as continuation arguments. + /// A task representing the asynchronous test. + [Test] + public async Task WritesLazySingletonWithDependencies() + { + var registration = LazySingleton( + TypeA, + mode: "global::System.Threading.LazyThreadSafetyMode.None", + parameters: [new(DependencyX, DependencyKind.Service, null)]); + + var source = Generate(registration); + + await Assert.That(source).Contains( + Body + "var lazy0 = new global::System.Lazy(\n" + + Body + FactoryOfA + + Body + " resolver.GetService() ?? ThrowNotRegistered(\"global::T.IX\")),\n" + + Body + " global::System.Threading.LazyThreadSafetyMode.None);\n"); + } + + /// Transients are written before lazy singletons, whatever order the calls came in. + /// A task representing the asynchronous test. + [Test] + public async Task WritesTransientsFirst() + { + var source = Generate(LazySingleton("global::T.L"), Transient(TypeA)); + + await Assert.That(source.IndexOf("new global::T.A()", StringComparison.Ordinal)) + .IsLessThan(source.IndexOf("new global::T.L()", StringComparison.Ordinal)); + } + + /// Both throw helpers are written when registrations with and without a contract both need one. + /// A task representing the asynchronous test. + [Test] + public async Task WritesBothThrowHelpers() + { + ConstructorParameter[] parameters = [new(DependencyX, DependencyKind.Service, null)]; + var source = Generate(Transient(TypeA, parameters: parameters), Transient(TypeB, contract: "\"c\"", parameters: parameters)); + + await Assert.That(source).Contains( + " }\n\n" + + " /// Throws for a dependency the resolver has no registration for.\n"); + await Assert.That(source).Contains("private static T ThrowNotRegistered(string typeName)\n"); + await Assert.That(source).EndsWith( + " throw new global::System.InvalidOperationException(\"Dependency '\" + typeName + \"' with contract \" + contract + \" not registered with Splat resolver.\");\n" + + " }\n" + + " }\n" + + "}\n"); + } + + /// Writes a file for the registrations. + /// The registrations. + /// The file. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string Generate(params RegistrationInfo[] registrations) => + CodeGenerator.Generate([.. registrations]); + + /// Describes a transient registration of I plus the type's short name. + /// The fully qualified constructed type. + /// The contract. + /// The constructor parameters. + /// The injected properties. + /// The registration. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static RegistrationInfo Transient(string concrete, string? contract = null, ConstructorParameter[]? parameters = null, PropertyInjection[]? properties = null) => + Create(RegistrationKind.Transient, concrete, contract, null, parameters, properties); + + /// Describes a lazy singleton registration of I plus the type's short name. + /// The fully qualified constructed type. + /// The contract. + /// The thread safety mode. + /// The constructor parameters. + /// The registration. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static RegistrationInfo LazySingleton(string concrete, string? contract = null, string? mode = null, ConstructorParameter[]? parameters = null) => + Create(RegistrationKind.LazySingleton, concrete, contract, mode, parameters, null); + + /// Describes a registration of I plus the type's short name. + /// The kind. + /// The fully qualified constructed type. + /// The contract. + /// The thread safety mode. + /// The constructor parameters. + /// The injected properties. + /// The registration. + private static RegistrationInfo Create(RegistrationKind kind, string concrete, string? contract, string? mode, ConstructorParameter[]? parameters, PropertyInjection[]? properties) + { + var dot = concrete.LastIndexOf('.'); + var service = string.Concat(concrete.AsSpan(0, dot + 1), "I", concrete.AsSpan(dot + 1)); + return new( + kind, + service, + concrete, + parameters is null ? EquatableArray.Empty : new(parameters), + properties is null ? EquatableArray.Empty : new(properties), + contract, + mode); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/PooledBuilderTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/PooledBuilderTests.cs new file mode 100644 index 00000000..5721fbad --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/PooledBuilderTests.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +namespace Splat.DependencyInjection.SourceGenerator.Tests.CodeGeneration; + +/// Tests that reuses builders on a thread and lets outsized ones go. +public sealed class PooledBuilderTests +{ + /// The capacity each rent asks for. + private const int Capacity = 16; + + /// A returned builder is handed out, empty, by the next rent on the same thread. + /// A task representing the asynchronous test. + [Test] + public async Task ReusesReturnedBuilder() + { + var first = PooledBuilder.Rent(Capacity); + _ = first.Append("text"); + var text = PooledBuilder.ToStringAndReturn(first); + + var second = PooledBuilder.Rent(Capacity); + var third = PooledBuilder.Rent(Capacity); + + await Assert.That(text).IsEqualTo("text"); + await Assert.That(second).IsSameReferenceAs(first); + await Assert.That(second.Length).IsEqualTo(0); + await Assert.That(third).IsNotSameReferenceAs(first); + } + + /// A builder grown past the retention limit is not kept. + /// A task representing the asynchronous test. + [Test] + public async Task DropsOutsizedBuilder() + { + var outsized = PooledBuilder.Rent(PooledBuilder.MaxRetainedCapacity + 1); + _ = PooledBuilder.ToStringAndReturn(outsized); + + var next = PooledBuilder.Rent(Capacity); + + await Assert.That(next).IsNotSameReferenceAs(outsized); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/SourceWriterTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/SourceWriterTests.cs new file mode 100644 index 00000000..62b0f0da --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneration/SourceWriterTests.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Splat.DependencyInjection.SourceGenerator.CodeGeneration; + +namespace Splat.DependencyInjection.SourceGenerator.Tests.CodeGeneration; + +/// Tests the layout rules applies. +public sealed class SourceWriterTests +{ + /// The capacity each rent asks for. + private const int Capacity = 16; + + /// A line is indented by the level it starts at, and text appended to it is not indented again. + /// A task representing the asynchronous test. + [Test] + public async Task IndentsEachLineOnce() + { + var writer = SourceWriter.Rent(Capacity).Line("a").Indent().Append("b").Append('c').Append("d").EndLine().Outdent().Line("e"); + + await Assert.That(writer.ToString()).IsEqualTo("a\n bcd\ne\n"); + await Assert.That(writer.Level).IsEqualTo(0); + } + + /// Blocks write their braces at the outer level and their content one level deeper. + /// A task representing the asynchronous test. + [Test] + public async Task OpensAndClosesBlocks() + { + var writer = SourceWriter.Rent(Capacity).OpenNamespace("N").Line("x").OpenBlock().CloseBlockInline().Line(";").CloseBlock(); + + await Assert.That(writer.ToStringAndReturn()).IsEqualTo("namespace N\n{\n x\n {\n };\n}\n"); + } + + /// A continuation moves the rest of an expression one level deeper and back. + /// A task representing the asynchronous test. + [Test] + public async Task WritesContinuations() + { + var writer = SourceWriter.Rent(Capacity).Append("f(").OpenContinuation().Append("a").ArgumentSeparator().Append("b").CloseContinuation(");").BlankLine().Line("g();"); + + await Assert.That(writer.ToString()).IsEqualTo("f(\n a,\n b);\n\ng();\n"); + await Assert.That(writer.Level).IsEqualTo(0); + } + + /// + /// A block of lines is written at the writer's level, keeping its own indentation, taking either line ending, + /// leaving empty lines empty, and finishing an unterminated last line. + /// + /// A task representing the asynchronous test. + [Test] + public async Task WritesBlocksOfLines() + { + var writer = SourceWriter.Rent(Capacity).Indent().Lines("a\r\n\n b\nc"); + + await Assert.That(writer.ToString()).IsEqualTo(" a\n\n b\n c\n"); + } + + /// A block of lines ending in a line break writes no extra blank line. + /// A task representing the asynchronous test. + [Test] + public async Task WritesTerminatedBlockWithoutExtraLine() + { + var writer = SourceWriter.Rent(Capacity).Lines("a\n"); + + await Assert.That(writer.ToString()).IsEqualTo("a\n"); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneratorTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneratorTests.cs deleted file mode 100644 index 0864ee6b..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/CodeGeneratorTests.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Collections.Immutable; -using System.Text; - -using Microsoft.CodeAnalysis; - -using Splat.DependencyInjection.SourceGenerator.CodeGeneration; -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests; - -/// -/// Tests for CodeGenerator. -/// -public class CodeGeneratorTests -{ - /// - /// Verifies GenerateSetupIOCMethod output structure. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GenerateSetupIOCMethod_BasicStructure() - { - var transients = ImmutableArray.Empty; - var lazySingletons = ImmutableArray.Empty; - - var result = CodeGenerator.GenerateSetupIOCMethod(transients, lazySingletons); - - await Assert.That(result).Contains("internal static partial class SplatRegistrations"); - await Assert.That(result).Contains("static partial void SetupIOCInternal(Splat.IDependencyResolver resolver)"); - } - - /// - /// Verifies GenerateTransientRegistration output with various options. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GenerateTransientRegistration_VariousScenarios() - { - var sb = new StringBuilder(); - - // 1. Simple registration - var reg1 = new TransientRegistrationInfo( - InterfaceTypeFullName: "IService", - ConcreteTypeFullName: "Service", - ConstructorParameters: new EquatableArray([]), - PropertyInjections: new EquatableArray([]), - ContractValue: null, - InvocationLocation: Location.None); - - CodeGenerator.GenerateTransientRegistration(sb, reg1); - var result1 = sb.ToString(); - await Assert.That(result1).Contains("resolver.Register(() => new Service());"); - - sb.Clear(); - - // 2. Complex registration with params, props and contract - var reg2 = new TransientRegistrationInfo( - InterfaceTypeFullName: "IService", - ConcreteTypeFullName: "Service", - ConstructorParameters: new EquatableArray([ - new ConstructorParameter("p1", "IParam1", false, null, false, null), - new ConstructorParameter("p2", "IEnumerable", false, null, true, "IParam2") - ]), - PropertyInjections: new EquatableArray([ - new PropertyInjection("Prop1", "IProp1", Location.None) - ]), - ContractValue: "\"MyContract\"", - InvocationLocation: Location.None); - - CodeGenerator.GenerateTransientRegistration(sb, reg2); - var result2 = sb.ToString(); - - await Assert.That(result2).Contains("resolver.GetService(\"MyContract\")"); - await Assert.That(result2).Contains("resolver.GetServices(\"MyContract\")"); - await Assert.That(result2).Contains("Prop1 = resolver.GetService(\"MyContract\")"); - await Assert.That(result2).Contains(", \"MyContract\");"); - } - - /// - /// Verifies GenerateLazySingletonRegistration output with various options. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GenerateLazySingletonRegistration_VariousScenarios() - { - var sb = new StringBuilder(); - - // 1. Complex registration - var reg = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "IService", - ConcreteTypeFullName: "Service", - ConstructorParameters: new EquatableArray([ - new ConstructorParameter("p1", "IParam1", false, null, false, null) - ]), - PropertyInjections: new EquatableArray([]), - ContractValue: null, - LazyThreadSafetyMode: "global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication", - InvocationLocation: Location.None); - - CodeGenerator.GenerateLazySingletonRegistration(sb, reg); - var result = sb.ToString(); - - await Assert.That(result).Contains("global::System.Lazy lazy = new global::System.Lazy"); - await Assert.That(result).Contains("global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication"); - await Assert.That(result).Contains("resolver.Register>(() => lazy);"); - await Assert.That(result).Contains("resolver.Register(() => lazy.Value);"); - } - - /// - /// Verifies GetResolutionString returns a GetService call for a simple type without contract. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetResolutionString_SimpleType_NoContract() - { - var result = CodeGenerator.GetResolutionString("global::MyApp.IService", false, null, null); - - await Assert.That(result).IsEqualTo( - "resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::MyApp.IService' not registered with Splat resolver.\")"); - } - - /// - /// Verifies GetResolutionString returns a GetService call with contract parameter. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetResolutionString_SimpleType_WithContract() - { - var result = CodeGenerator.GetResolutionString("global::MyApp.IService", false, null, "\"key1\""); - - await Assert.That(result).Contains("resolver.GetService(\"key1\")"); - await Assert.That(result).Contains("with contract"); - } - - /// - /// Verifies GetResolutionString returns a GetServices call for a collection type without contract. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetResolutionString_CollectionType_NoContract() - { - var result = CodeGenerator.GetResolutionString("global::System.Collections.Generic.IEnumerable", true, "global::MyApp.IService", null); - - await Assert.That(result).IsEqualTo("resolver.GetServices()"); - } - - /// - /// Verifies GetResolutionString returns a GetServices call for a collection type with contract. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetResolutionString_CollectionType_WithContract() - { - var result = CodeGenerator.GetResolutionString("global::System.Collections.Generic.IEnumerable", true, "global::MyApp.IService", "\"key1\""); - - await Assert.That(result).IsEqualTo("resolver.GetServices(\"key1\")"); - } - - /// - /// Verifies GetConstructorArguments returns empty string for no parameters. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetConstructorArguments_Empty_ReturnsEmpty() - { - var result = CodeGenerator.GetConstructorArguments(new EquatableArray([]), null); - - await Assert.That(result).IsEqualTo(string.Empty); - } - - /// - /// Verifies GetConstructorArguments produces comma-separated resolution strings for multiple parameters. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetConstructorArguments_MultipleParams_CommaSeparated() - { - var parameters = new EquatableArray([ - new ConstructorParameter("a", "IServiceA", false, null, false, null), - new ConstructorParameter("b", "IServiceB", false, null, false, null) - ]); - - var result = CodeGenerator.GetConstructorArguments(parameters, null); - - await Assert.That(result).Contains("resolver.GetService()"); - await Assert.That(result).Contains("resolver.GetService()"); - await Assert.That(result).Contains(", "); - } - - /// - /// Verifies GetConstructorArguments handles a collection parameter correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetConstructorArguments_CollectionParam_UsesGetServices() - { - var parameters = new EquatableArray([ - new ConstructorParameter("items", "global::System.Collections.Generic.IEnumerable", false, null, true, "IItem") - ]); - - var result = CodeGenerator.GetConstructorArguments(parameters, null); - - await Assert.That(result).IsEqualTo("resolver.GetServices()"); - } - - /// - /// Verifies GetPropertyInitializer returns empty string for no properties. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetPropertyInitializer_Empty_ReturnsEmpty() - { - var result = CodeGenerator.GetPropertyInitializer(new EquatableArray([]), null); - - await Assert.That(result).IsEqualTo(string.Empty); - } - - /// - /// Verifies GetPropertyInitializer produces correct object initializer syntax. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetPropertyInitializer_SingleProperty_ReturnsInitializer() - { - var properties = new EquatableArray([ - new PropertyInjection("Logger", "ILogger", Location.None) - ]); - - var result = CodeGenerator.GetPropertyInitializer(properties, null); - - await Assert.That(result).Contains("Logger = resolver.GetService()"); - await Assert.That(result).StartsWith(" { "); - await Assert.That(result).EndsWith(" }"); - } - - /// - /// Verifies GetPropertyInitializer uses contract value when provided. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetPropertyInitializer_WithContract_PassesContract() - { - var properties = new EquatableArray([ - new PropertyInjection("Logger", "ILogger", Location.None) - ]); - - var result = CodeGenerator.GetPropertyInitializer(properties, "\"named\""); - - await Assert.That(result).Contains("resolver.GetService(\"named\")"); - } - - /// - /// Verifies GetPropertyInitializer produces comma-separated initializers for multiple properties. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetPropertyInitializer_MultipleProperties_CommaSeparated() - { - var properties = new EquatableArray([ - new PropertyInjection("Logger", "ILogger", Location.None), - new PropertyInjection("Cache", "ICache", Location.None) - ]); - - var result = CodeGenerator.GetPropertyInitializer(properties, null); - - await Assert.That(result).Contains("Logger = "); - await Assert.That(result).Contains("Cache = "); - await Assert.That(result).Contains(", "); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/DiagnosticWarningsTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/DiagnosticWarningsTests.cs index 1641df37..1f4d4068 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/DiagnosticWarningsTests.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/DiagnosticWarningsTests.cs @@ -1,19 +1,15 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. using Microsoft.CodeAnalysis; namespace Splat.DependencyInjection.SourceGenerator.Tests; -/// -/// Tests for the DiagnosticWarnings class. -/// +/// Tests for the DiagnosticWarnings class. public class DiagnosticWarningsTests { - /// - /// Verifies that all diagnostic IDs are correctly defined. - /// + /// Verifies that all diagnostic IDs are correctly defined. /// A task representing the asynchronous operation. [Test] public async Task VerifyDiagnosticIds() diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/EquatableArrayTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/EquatableArrayTests.cs deleted file mode 100644 index 8c74286f..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/EquatableArrayTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Collections; - -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests; - -/// -/// Tests for EquatableArray. -/// -public class EquatableArrayTests -{ - /// - /// Verifies equality logic. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task Equality_Works() - { - var arr1 = new EquatableArray([1, 2, 3]); - var arr2 = new EquatableArray([1, 2, 3]); - var arr3 = new EquatableArray([1, 2, 4]); - var empty1 = new EquatableArray([]); - var null1 = new EquatableArray(null!); - var null2 = new EquatableArray(null!); - - await Assert.That(arr1 == arr2).IsTrue(); - await Assert.That(arr1.Equals(arr2)).IsTrue(); - await Assert.That(arr1.Equals((object)arr2)).IsTrue(); - await Assert.That(arr1 != arr3).IsTrue(); - await Assert.That(arr1.Equals(arr3)).IsFalse(); - await Assert.That(null1 == null2).IsTrue(); - await Assert.That(null1 == arr1).IsFalse(); - await Assert.That(arr1 == null1).IsFalse(); - - await Assert.That(arr1.Equals(null)).IsFalse(); - await Assert.That(arr1.Equals("not an array")).IsFalse(); - } - - /// - /// Verifies GetHashCode logic. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetHashCode_Works() - { - var arr1 = new EquatableArray([1, 2, 3]); - var arr2 = new EquatableArray([1, 2, 3]); - var nullArr = new EquatableArray(null!); - - await Assert.That(arr1.GetHashCode()).IsEqualTo(arr2.GetHashCode()); - await Assert.That(nullArr.GetHashCode()).IsEqualTo(0); - } - - /// - /// Verifies enumeration logic. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task Enumeration_Works() - { - var data = new[] { 1, 2, 3 }; - var arr = new EquatableArray(data); - var nullArr = new EquatableArray(null!); - - await Assert.That(arr.ToList()).Count().IsEqualTo(3); - await Assert.That(nullArr.ToList()).IsEmpty(); - - // Test non-generic enumerator - IEnumerable enumerable = arr; - var count = 0; - foreach (var item in enumerable) - { - count++; - } - - await Assert.That(count).IsEqualTo(3); - } - - /// - /// Verifies indexer and length. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task Indexer_And_Length_Work() - { - var arr = new EquatableArray([10, 20]); - await Assert.That(arr.Length).IsEqualTo(2); - await Assert.That(arr[0]).IsEqualTo(10); - await Assert.That(arr[1]).IsEqualTo(20); - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ExtractionTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ExtractionTests.cs new file mode 100644 index 00000000..445bba52 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ExtractionTests.cs @@ -0,0 +1,376 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +using Splat.DependencyInjection.SourceGenerator.Models; + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// Tests which calls become registrations, and what is read from each. +public sealed class ExtractionTests +{ + /// The registration of A as IA with nothing to resolve. + private const string RegistrationOfA = "resolver.Register(() => new global::T.A());"; + + /// A type from a reference as the base of C, with injected, plain and otherwise attributed properties. + private const string ReferencedBase = + "public sealed class C : System.Collections.ObjectModel.Collection, IA { [DependencyInjectionProperty] public IB P { get; internal set; } " + + "public IB Q { get; set; } [System.ComponentModel.Description(\"r\")] public IB R { get; set; } }"; + + /// A call through a using alias, a qualified name or a static import is a registration. + /// The call. + /// The directives the call needs. + /// A task representing the asynchronous test. + [Test] + [Arguments("SR.Register();", "using SR = Splat.SplatRegistrations;")] + [Arguments("Splat.SplatRegistrations.Register();", "")] + [Arguments("global::Splat.SplatRegistrations.Register();", "")] + [Arguments("Register();", "using static Splat.SplatRegistrations;")] + public async Task RecognisesEverySpelling(string call, string usings) + { + var run = TestHelper.Run(Source(call, usings: usings)); + + await Assert.That(run.RegistrationSource()).Contains(RegistrationOfA); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// + /// Calls that share a marker's name but are something else - Splat's own registrations, another class's method, + /// a class of the same name elsewhere, a call that does not bind - are not registrations. + /// + /// The call. + /// The declarations the call needs. + /// A task representing the asynchronous test. + [Test] + [Arguments("AppLocator.CurrentMutable.Register(() => new A());", "")] + [Arguments("AppLocator.CurrentMutable.Register();", "")] + [Arguments("AppLocator.CurrentMutable.Register(delegate { return new A(); });", "")] + [Arguments("Other.Register();", "")] + [Arguments("My.SplatRegistrations.Register();", "namespace My { public static class SplatRegistrations { public static void Register() { } } }")] + [Arguments("SplatRegistrations.Register(\"x\", 1);", "")] + [Arguments("SplatRegistrations.Register(1, 2, 3);", "")] + [Arguments("SplatRegistrations.Register();", "")] + [Arguments("SplatRegistrations.Unregister();", "")] + [Arguments("SplatRegistrations.RegisterConstant(new A());", "")] + [Arguments("SplatRegistrations.SetupIOC();", "")] + [Arguments("new Action[] { () => { } }[0]();", "")] + public async Task IgnoresOtherCalls(string call, string types) + { + var run = TestHelper.Run(Source(call, types: types)); + + await Assert.That(run.RegistrationSource()).IsNull(); + } + + /// A marker's name on an extension method declared on the marker class is not a registration. + /// A task representing the asynchronous test. + [Test] + public async Task IgnoresExtensionMethodOnMarkerClass() + { + const string Extension = """ + namespace Splat + { + internal static partial class SplatRegistrations + { + public static void Register(this string value) { } + } + } + """; + + var run = TestHelper.Run(Source("SplatRegistrations.Register(\"x\");"), Extension); + + await Assert.That(run.RegistrationSource()).IsNull(); + } + + /// + /// A call that binds to an extension method on the marker class, to a method of another class, or to a local + /// function of the same name is not a registration. + /// + /// The call. + /// The declarations the call needs. + /// The directives the call needs. + /// A task representing the asynchronous test. + [Test] + [Arguments("SplatRegistrations.Register(5);", "", "")] + [Arguments("Register();", "", "using static T.Other;")] + [Arguments("Register(); static void Register() { }", "", "")] + public async Task IgnoresMethodsOutsideMarkerClass(string call, string types, string usings) + { + const string Extension = """ + namespace Splat + { + internal static partial class SplatRegistrations + { + public static void Register(this int value) { } + } + } + """; + + var run = TestHelper.Run(Source(call, types, usings), Extension); + + await Assert.That(run.RegistrationSource()).IsNull(); + } + + /// A contract is written so it compiles from the generated file, whatever form the argument takes. + /// The contract argument. + /// The contract the generated code passes. + /// A task representing the asynchronous test. + [Test] + [Arguments("\"c\"", "\"c\"")] + [Arguments("@\"c\"", "@\"c\"")] + [Arguments("Keys.Field", "global::T.Keys.Field")] + [Arguments("Keys.Property", "global::T.Keys.Property")] + [Arguments("Keys.Get()", "global::T.Keys.Get()")] + [Arguments("Keys.Generic(1)", "global::T.Keys.Generic(1)")] + [Arguments("Local()", "global::T.Bootstrapper.Local()")] + [Arguments("\"a\" + \"b\"", "\"a\" + \"b\"")] + [Arguments("contract: \"c\"", "\"c\"")] + public async Task ReadsContract(string argument, string expected) + { + var run = TestHelper.Run(Source($"SplatRegistrations.Register({argument});")); + + await Assert.That(run.RegistrationSource()).Contains($"resolver.Register(() => new global::T.A(), {expected});"); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// A contract that binds to no symbol is left out, as it always has been. + /// A task representing the asynchronous test. + [Test] + public async Task DropsContractWithoutSymbol() + { + var run = TestHelper.Run(Source("SplatRegistrations.Register($\"c{1}\");")); + + await Assert.That(run.RegistrationSource()).Contains(RegistrationOfA); + } + + /// A thread safety mode is written so it compiles from the generated file, whatever form it takes. + /// The arguments. + /// The arguments the generated lazy is created with, after its factory. + /// A task representing the asynchronous test. + [Test] + [Arguments("LazyThreadSafetyMode.None", ", global::System.Threading.LazyThreadSafetyMode.None")] + [Arguments("LazyThreadSafetyMode.PublicationOnly", ", global::System.Threading.LazyThreadSafetyMode.PublicationOnly")] + [Arguments("LazyThreadSafetyMode.ExecutionAndPublication", ", global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication")] + [Arguments("Keys.Mode", ", global::T.Keys.Mode")] + [Arguments("Keys.ConstantMode", ", global::T.Keys.ConstantMode")] + [Arguments("(LazyThreadSafetyMode)1", "")] + [Arguments("mode: LazyThreadSafetyMode.None, contract: \"c\"", ", global::System.Threading.LazyThreadSafetyMode.None")] + public async Task ReadsMode(string arguments, string expected) + { + var run = TestHelper.Run(Source($"SplatRegistrations.RegisterLazySingleton({arguments});")); + + await Assert.That(run.RegistrationSource()).Contains($"var lazy0 = new global::System.Lazy(() => new global::T.A(){expected});"); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// A mode held in a local is copied as written. + /// A task representing the asynchronous test. + [Test] + public async Task CopiesLocalMode() + { + var run = TestHelper.Run(Source("var mode = LazyThreadSafetyMode.None; SplatRegistrations.RegisterLazySingleton(mode);")); + + await Assert.That(run.RegistrationSource()).Contains("var lazy0 = new global::System.Lazy(() => new global::T.A(), mode);"); + } + + /// An argument to a parameter that is neither the contract nor the mode is ignored. + /// A task representing the asynchronous test. + [Test] + public async Task IgnoresOtherParameters() + { + const string Overload = """ + namespace Splat + { + internal static partial class SplatRegistrations + { + public static void Register(int other) { } + } + } + """; + + var run = TestHelper.Run(Source("SplatRegistrations.Register(1);"), Overload); + + await Assert.That(run.RegistrationSource()).Contains(RegistrationOfA); + } + + /// A lazy, a collection, and any other type are each resolved their own way. + /// A task representing the asynchronous test. + [Test] + public async Task ResolvesEachParameterKind() + { + const string Types = """ + public sealed class Many : IA + { + public Many(Lazy lazy, IEnumerable all, List list, Dictionary map, IB[] array) { } + } + """; + + var run = TestHelper.Run(Source("SplatRegistrations.Register(); SplatRegistrations.RegisterLazySingleton();", types: Types)); + var source = run.RegistrationSource(); + + await Assert.That(source).Contains("resolver.GetService>() ?? "); + await Assert.That(source).Contains("resolver.GetServices(),"); + await Assert.That(source).Contains("resolver.GetService>() ?? "); + await Assert.That(source).Contains("resolver.GetService>() ?? "); + await Assert.That(source).Contains("resolver.GetService() ?? "); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// + /// The constructor chosen and the properties injected for C, and the registrations turned away for having + /// no usable constructor or a property that cannot be set. + /// + /// The declarations of C and its base. + /// Text the registration contains, or when it is turned away. + /// A task representing the asynchronous test. + [Test] + [Arguments("public sealed class C : IA { public C(IB b) { } }", "new global::T.C(\n")] + [Arguments("public struct C : IA { }", "new global::T.C()")] + [Arguments("public sealed class C : IA { private C() { } }", null)] + [Arguments("public sealed class C : IA { public C() { } public C(IB b) { } }", null)] + [Arguments("public sealed class C : IA { [DependencyInjectionConstructor] public C() { } [DependencyInjectionConstructor] public C(IB b) { } }", null)] + [Arguments("public sealed class C : IA { public C() { } [DependencyInjectionConstructor] public C(IB b) { } }", "new global::T.C(\n")] + [Arguments("public class Base { [DependencyInjectionProperty] public IB Inherited { get; set; } } public sealed class C : Base, IA { }", "Inherited = ")] + [Arguments(ReferencedBase, "P = ")] + [Arguments("public sealed class C : IA { [DependencyInjectionProperty] public IB P { get; private set; } }", null)] + [Arguments("public sealed class C : IA { [DependencyInjectionProperty] public IB P { get; } }", null)] + public async Task ExtractsConstructorAndProperties(string type, string? expected) + { + var source = TestHelper.Run(Source("SplatRegistrations.Register();", types: type)).RegistrationSource(); + + if (expected is null) + { + await Assert.That(source).IsNull(); + } + else + { + await Assert.That(source).Contains(expected); + } + } + + /// A type from a reference is constructed through its only constructor, without walking its members. + /// A task representing the asynchronous test. + [Test] + public async Task ConstructsReferencedType() + { + var run = TestHelper.Run(Source("SplatRegistrations.Register();")); + + await Assert.That(run.RegistrationSource()).Contains("resolver.Register(() => new object());"); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// A type from a reference with several constructors cannot mark one, so it is turned away. + /// A task representing the asynchronous test. + [Test] + public async Task TurnsAwayReferencedTypeWithSeveralConstructors() + { + var run = TestHelper.Run(Source("SplatRegistrations.Register();")); + + await Assert.That(run.RegistrationSource()).IsNull(); + } + + /// An interface or other type without constructors takes no constructor parameters. + /// A task representing the asynchronous test. + [Test] + public async Task ReadsNoParametersFromTypeWithoutConstructors() + { + var compilation = TestHelper.Run(Source(string.Empty)).Output; + var symbols = WellKnownSymbols.For(compilation); + + var extracted = MetadataExtractor.TryExtractConstructorParameters(compilation.GetTypeByMetadataName("T.IA")!, symbols, out var parameters); + + await Assert.That(extracted).IsTrue(); + await Assert.That(parameters.Length).IsEqualTo(0); + } + + /// + /// Without the injection attributes in the compilation, no property is injected and no constructor is marked, so a + /// type with several constructors is turned away. + /// + /// A task representing the asynchronous test. + [Test] + public async Task InjectsNothingWithoutAttributes() + { + const string Types = """ + public sealed class C : IA { public IB P { get; set; } } + public sealed class D : IB { public D() { } public D(IA a) { } } + """; + var compilation = TestHelper.CreateCompilation(Source(string.Empty, types: Types)); + var symbols = WellKnownSymbols.For(compilation); + var typeD = compilation.GetTypeByMetadataName("T.D")!; + + var injected = MetadataExtractor.TryExtractPropertyInjections(compilation.GetTypeByMetadataName("T.C")!, symbols, out var properties); + + await Assert.That(symbols.PropertyAttribute).IsNull(); + await Assert.That(injected).IsTrue(); + await Assert.That(properties.Length).IsEqualTo(0); + await Assert.That(MetadataExtractor.FindMarkedConstructor(typeD, typeD.GetMembers(".ctor"), symbols)).IsNull(); + } + + /// A registration naming one type uses one formatted name for both the service and the construction. + /// A task representing the asynchronous test. + [Test] + public async Task ReusesNameForSingleTypeRegistration() + { + var compilation = TestHelper.CreateCompilation(Source("SplatRegistrations.Register();")); + var output = (CSharpCompilation)TestHelper.Run(compilation).Output; + var invocation = await TestHelper.FindInvocationAsync(output.SyntaxTrees[0], "SplatRegistrations."); + var model = output.GetSemanticModel(invocation.SyntaxTree); + var method = (IMethodSymbol)model.GetSymbolInfo(invocation).Symbol!; + + var registration = MetadataExtractor.ExtractRegistration(method, invocation, model, WellKnownSymbols.For(output), CancellationToken.None); + + await Assert.That(registration!.Kind).IsEqualTo(RegistrationKind.Transient); + await Assert.That(registration.ConcreteTypeFullName).IsSameReferenceAs(registration.InterfaceTypeFullName); + } + + /// Builds a file that makes registrations. + /// The statements of the registering method. + /// Declarations added to the namespace. + /// Directives added to the file. + /// The file. + private static string Source(string registrations, string types = "", string usings = "") => $$""" + using System; + using System.Collections.Generic; + using System.Threading; + using Splat; + {{usings}} + + namespace T + { + public interface IA { } + public interface IB { } + public sealed class A : IA { } + public sealed class B : IB { } + + public static class Keys + { + public const string Field = "field"; + public const LazyThreadSafetyMode ConstantMode = LazyThreadSafetyMode.None; + public static readonly LazyThreadSafetyMode Mode = LazyThreadSafetyMode.None; + public static string Property => "property"; + public static string Get() => "get"; + public static string Generic(TValue value) => value.ToString(); + } + + public static class Other + { + public static void Register() { } + } + + {{types}} + + public static class Bootstrapper + { + public static void Register() + { + {{registrations}} + } + + internal static string Local() => "local"; + } + } + """; +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorCodeGenerationTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorCodeGenerationTests.cs deleted file mode 100644 index 8cdaa39f..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorCodeGenerationTests.cs +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Collections.Immutable; -using System.Text; - -using Microsoft.CodeAnalysis; - -using Splat.DependencyInjection.SourceGenerator.CodeGeneration; -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests; - -/// -/// Tests for Generator code generation methods. -/// Tests the internal code generation helpers directly for better coverage. -/// -public class GeneratorCodeGenerationTests -{ - /// - /// Tests that GenerateTransientRegistration generates correct code for a simple registration with no dependencies. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateTransientRegistration_NoDependencies_GeneratesCorrectCode() - { - var registration = new TransientRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: default, - ContractValue: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateTransientRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("resolver.Register"); - await Assert.That(result).Contains("new global::Test.Service()"); - } - - /// - /// Tests that GenerateTransientRegistration generates correct code with constructor parameters. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateTransientRegistration_WithConstructorParameters_GeneratesCorrectCode() - { - var registration = new TransientRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: new EquatableArray(new[] - { - new ConstructorParameter("dep1", "global::Test.IDep1", false, null, false, null), - new ConstructorParameter("dep2", "global::Test.IDep2", false, null, false, null) - }), - PropertyInjections: default, - ContractValue: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateTransientRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IDep1' not registered with Splat resolver.\")"); - await Assert.That(result).Contains("resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IDep2' not registered with Splat resolver.\")"); - } - - /// - /// Tests that GenerateTransientRegistration generates correct code with property injections. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateTransientRegistration_WithPropertyInjections_GeneratesCorrectCode() - { - var registration = new TransientRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: new EquatableArray(new[] - { - new PropertyInjection("Prop1", "global::Test.IProp1", Location.None), - new PropertyInjection("Prop2", "global::Test.IProp2", Location.None) - }), - ContractValue: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateTransientRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("{ Prop1 = resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IProp1' not registered with Splat resolver.\"), Prop2 = resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IProp2' not registered with Splat resolver.\") }"); - } - - /// - /// Tests that GenerateTransientRegistration generates correct code with a contract value. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateTransientRegistration_WithContract_GeneratesCorrectCode() - { - var registration = new TransientRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: default, - ContractValue: "\"MyContract\"", - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateTransientRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains(", \"MyContract\""); - } - - /// - /// Tests that GenerateLazySingletonRegistration generates correct code for a simple lazy singleton. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateLazySingletonRegistration_Simple_GeneratesCorrectCode() - { - var registration = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: default, - ContractValue: null, - LazyThreadSafetyMode: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateLazySingletonRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("global::System.Lazy lazy"); - await Assert.That(result).Contains("new global::System.Lazy"); - await Assert.That(result).Contains("resolver.Register>(() => lazy"); - await Assert.That(result).Contains("resolver.Register(() => lazy.Value"); - } - - /// - /// Tests that GenerateLazySingletonRegistration generates correct code with thread safety mode. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateLazySingletonRegistration_WithThreadSafetyMode_GeneratesCorrectCode() - { - var registration = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: default, - ContractValue: null, - LazyThreadSafetyMode: "global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication", - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateLazySingletonRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains(", global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication"); - } - - /// - /// Tests that GenerateSetupIOCMethod generates the full SetupIOCInternal method. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateSetupIOCMethod_Empty_GeneratesCorrectStructure() - { - var transients = ImmutableArray.Empty; - var lazySingletons = ImmutableArray.Empty; - - var result = CodeGenerator.GenerateSetupIOCMethod(transients, lazySingletons); - - await Assert.That(result).Contains("// "); - await Assert.That(result).Contains("#nullable enable annotations"); - await Assert.That(result).Contains("namespace Splat"); - await Assert.That(result).Contains("internal static partial class SplatRegistrations"); - await Assert.That(result).Contains("static partial void SetupIOCInternal(Splat.IDependencyResolver resolver)"); - } - - /// - /// Tests that the extension methods file (Constants.ExtensionMethodText) includes GeneratedCodeAttribute with version. - /// This is the ONLY place where GeneratedCodeAttribute should appear on the SplatRegistrations partial class. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ExtensionMethodText_IncludesGeneratedCodeAttribute() - { - var result = Constants.ExtensionMethodText; - - await Assert.That(result).Contains("[global::System.CodeDom.Compiler.GeneratedCodeAttribute("); - await Assert.That(result).Contains("Splat.DependencyInjection.SourceGenerator"); - await Assert.That(result).Contains("internal static partial class SplatRegistrations"); - } - - /// - /// Tests that GenerateSetupIOCMethod generates registrations for transients and lazy singletons. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateSetupIOCMethod_WithRegistrations_GeneratesAllRegistrations() - { - var transients = ImmutableArray.Create( - new TransientRegistrationInfo( - "global::Test.IService1", - "global::Test.Service1", - default, - default, - null, - Location.None)); - - var lazySingletons = ImmutableArray.Create( - new LazySingletonRegistrationInfo( - "global::Test.IService2", - "global::Test.Service2", - default, - default, - null, - null, - Location.None)); - - var result = CodeGenerator.GenerateSetupIOCMethod(transients, lazySingletons); - - await Assert.That(result).Contains("resolver.Register"); - await Assert.That(result).Contains("new global::Test.Service1()"); - await Assert.That(result).Contains("global::System.Lazy"); - await Assert.That(result).Contains("new global::Test.Service2()"); - } - - /// - /// Tests that GenerateLazySingletonRegistration generates correct code with property injections. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateLazySingletonRegistration_WithPropertyInjections_GeneratesCorrectCode() - { - var registration = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: new EquatableArray(new[] - { - new PropertyInjection("Prop1", "global::Test.IProp1", Location.None), - new PropertyInjection("Prop2", "global::Test.IProp2", Location.None) - }), - ContractValue: null, - LazyThreadSafetyMode: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateLazySingletonRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("{ Prop1 = resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IProp1' not registered with Splat resolver.\"), Prop2 = resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IProp2' not registered with Splat resolver.\") }"); - } - - /// - /// Tests that GenerateLazySingletonRegistration generates correct code with constructor parameters. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateLazySingletonRegistration_WithConstructorParameters_GeneratesCorrectCode() - { - var registration = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: new EquatableArray(new[] - { - new ConstructorParameter("dep1", "global::Test.IDep1", false, null, false, null), - new ConstructorParameter("dep2", "global::Test.IDep2", false, null, false, null) - }), - PropertyInjections: default, - ContractValue: null, - LazyThreadSafetyMode: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateLazySingletonRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains("resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IDep1' not registered with Splat resolver.\")"); - await Assert.That(result).Contains("resolver.GetService() ?? throw new global::System.InvalidOperationException(\"Dependency 'global::Test.IDep2' not registered with Splat resolver.\")"); - } - - /// - /// Tests that GenerateLazySingletonRegistration generates correct code with a contract value. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateLazySingletonRegistration_WithContract_GeneratesCorrectCode() - { - var registration = new LazySingletonRegistrationInfo( - InterfaceTypeFullName: "global::Test.IService", - ConcreteTypeFullName: "global::Test.Service", - ConstructorParameters: default, - PropertyInjections: default, - ContractValue: "\"MyContract\"", - LazyThreadSafetyMode: null, - InvocationLocation: Location.None); - - var sb = new StringBuilder(); - CodeGenerator.GenerateLazySingletonRegistration(sb, registration); - - var result = sb.ToString(); - await Assert.That(result).Contains(", \"MyContract\""); - } - - /// - /// Tests that GenerateSetupIOCMethod does NOT include GeneratedCodeAttribute to avoid duplication. - /// The GeneratedCodeAttribute should only appear once on the partial class (in Splat.DI.g.cs), - /// not on both partial class declarations, which would cause CS0579 duplicate attribute error. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task GenerateSetupIOCMethod_DoesNotIncludeDuplicateGeneratedCodeAttribute() - { - var transients = ImmutableArray.Empty; - var lazySingletons = ImmutableArray.Empty; - - var result = CodeGenerator.GenerateSetupIOCMethod(transients, lazySingletons); - - // The GeneratedCodeAttribute should NOT be in the Splat.DI.Reg.g.cs output - // It should only be in Splat.DI.g.cs (from Constants.ExtensionMethodText) - await Assert.That(result).DoesNotContain("[global::System.CodeDom.Compiler.GeneratedCodeAttribute("); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorRun.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorRun.cs new file mode 100644 index 00000000..a18b0a4d --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorRun.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.Immutable; +using System.Diagnostics; + +using Microsoft.CodeAnalysis; + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// One run of the generator. +/// The driver after the run, which carries its caches into the next. +/// The generator's result. +/// The compilation with the generated files added. +[DebuggerDisplay("GeneratorRun: {Result.GeneratedSources.Length} files")] +public sealed record GeneratorRun(GeneratorDriver Driver, GeneratorRunResult Result, Compilation Output) +{ + /// Gets the registrations file the run generated. + /// The file's text, or when none was generated. + public string? RegistrationSource() + { + foreach (var generated in Result.GeneratedSources) + { + if (generated.HintName == Constants.RegistrationFileName) + { + return generated.SourceText.ToString(); + } + } + + return null; + } + + /// Gets the errors in the output compilation, which includes the generated code. + /// The errors. + public ImmutableArray Errors() + { + var errors = ImmutableArray.CreateBuilder(); + foreach (var diagnostic in Output.GetDiagnostics()) + { + if (diagnostic.Severity == DiagnosticSeverity.Error) + { + errors.Add(diagnostic); + } + } + + return errors.ToImmutable(); + } + + /// Gets the hint names of the generated files. + /// The hint names. + public ImmutableArray HintNames() + { + var names = ImmutableArray.CreateBuilder(Result.GeneratedSources.Length); + foreach (var generated in Result.GeneratedSources) + { + names.Add(generated.HintName); + } + + return names.MoveToImmutable(); + } + + /// Gets the diagnostics the generator reported, as ID@line with lines counted from one. + /// The zero-based line counted as line one. + /// The diagnostics, space separated, in the order reported. + public string DiagnosticLines(int firstLine) + { + var text = new System.Text.StringBuilder(); + foreach (var diagnostic in Result.Diagnostics) + { + _ = (text.Length == 0 ? text : text.Append(' ')) + .Append(diagnostic.Id) + .Append('@') + .Append(diagnostic.Location.GetLineSpan().StartLinePosition.Line - firstLine + 1); + } + + return text.ToString(); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorSnapshot.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorSnapshot.cs new file mode 100644 index 00000000..73fbc89a --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorSnapshot.cs @@ -0,0 +1,198 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.Immutable; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; + +using Microsoft.CodeAnalysis; + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// Compares a generator run's output with the snapshots stored in the test project. +/// +/// +/// A generated file's snapshot is named {type}.{method}#{hint name}.verified.cs, and the generator's diagnostics +/// are stored as {type}.{method}#Diagnostics.verified.txt when there are any. An output that differs from its +/// snapshot, or has none, is written beside it as .received and fails the test, as does a snapshot the run no +/// longer produces. +/// +/// +/// To accept new or changed snapshots, run the tests with the ACCEPT_SNAPSHOTS=1 environment variable, then +/// run them again without it. +/// +/// +internal static class GeneratorSnapshot +{ + /// The suffix of a stored source snapshot. + internal const string VerifiedSourceSuffix = ".verified.cs"; + + /// The suffix of a stored diagnostics snapshot. + internal const string VerifiedDiagnosticsSuffix = ".verified.txt"; + + /// The environment variable that makes a run write its output over the snapshots. + private const string AcceptVariable = "ACCEPT_SNAPSHOTS"; + + /// The assembly metadata key the test project records its snapshot directory under. + private const string DirectoryMetadataKey = "GeneratorSnapshotDirectory"; + + /// The name that stands in for a hint name on the diagnostics snapshot. + private const string DiagnosticsName = "Diagnostics"; + + /// The suffix of the source output written beside a snapshot it does not match. + private const string ReceivedSourceSuffix = ".received.cs"; + + /// The suffix of the diagnostics written beside a snapshot they do not match. + private const string ReceivedDiagnosticsSuffix = ".received.txt"; + + /// Gets the directory holding the snapshots. + internal static string SnapshotDirectory { get; } = ReadSnapshotDirectory(); + + /// Asserts that the generated files and diagnostics match the stored snapshots. + /// The driver after the generator has run. + /// The snapshot name before the hint name, {type}.{method}. + /// + /// Whether to include the marker source and the embedded attribute, which are the same for every project and so + /// are stored once rather than by every test. + /// + /// A task that completes once every file has been compared. + internal static async Task VerifyAsync(GeneratorDriver driver, string name, bool includeFixedSources) + { + ArgumentNullException.ThrowIfNull(driver); + + var prefix = $"{name}#"; + var accept = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(AcceptVariable)); + var produced = new HashSet(StringComparer.Ordinal); + var failures = new List(); + + foreach (var result in driver.GetRunResult().Results) + { + foreach (var source in result.GeneratedSources) + { + if (!includeFixedSources && IsFixedSource(source.HintName)) + { + continue; + } + + var fileName = prefix + Path.GetFileNameWithoutExtension(source.HintName) + VerifiedSourceSuffix; + _ = produced.Add(fileName); + var output = $"//HintName: {source.HintName}\n{Normalize(source.SourceText.ToString())}"; + await CompareAsync(fileName, ReceivedSourceSuffix, output, accept, failures).ConfigureAwait(false); + } + + if (!result.Diagnostics.IsEmpty) + { + var fileName = prefix + DiagnosticsName + VerifiedDiagnosticsSuffix; + _ = produced.Add(fileName); + await CompareAsync(fileName, ReceivedDiagnosticsSuffix, FormatDiagnostics(result.Diagnostics), accept, failures).ConfigureAwait(false); + } + } + + RemoveStale(prefix, produced, accept, failures); + await Assert.That(failures).IsEmpty(); + } + + /// Renders diagnostics one per line, as the diagnostics snapshot stores them. + /// The diagnostics, in the order reported. + /// The rendered diagnostics. + internal static string FormatDiagnostics(ImmutableArray diagnostics) + { + var text = new StringBuilder(); + foreach (var diagnostic in diagnostics) + { + var span = diagnostic.Location.GetLineSpan(); + _ = text.Append(diagnostic.Id).Append(' ').Append(diagnostic.Severity).Append(' ') + .Append(span.Path).Append(span.Span.ToString()).Append(": ") + .Append(diagnostic.GetMessage(System.Globalization.CultureInfo.InvariantCulture)).Append('\n'); + } + + return text.ToString(); + } + + /// Tests whether a generated file is one of the fixed files every project gets. + /// The file's hint name. + /// for the marker source and the embedded attribute. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsFixedSource(string hintName) => hintName != Constants.RegistrationFileName; + + /// Settles one output against its snapshot, writing the received or accepted output as needed. + /// The snapshot's file name. + /// The suffix the received output is written under. + /// The output, in snapshot form. + /// Whether the output replaces the snapshot. + /// The failures so far, added to when the output differs. + /// A task that completes once the output is settled. + private static async Task CompareAsync(string fileName, string receivedSuffix, string output, bool accept, List failures) + { + var verifiedPath = Path.Combine(SnapshotDirectory, fileName); + var receivedPath = string.Concat(verifiedPath.AsSpan(0, verifiedPath.LastIndexOf(".verified.", StringComparison.Ordinal)), receivedSuffix); + + // Compared before accepting, so a matching snapshot keeps its bytes rather than being rewritten. + if (File.Exists(verifiedPath) && Normalize(await File.ReadAllTextAsync(verifiedPath).ConfigureAwait(false)) == output) + { + File.Delete(receivedPath); + return; + } + + if (accept) + { + await File.WriteAllTextAsync(verifiedPath, output).ConfigureAwait(false); + File.Delete(receivedPath); + return; + } + + await File.WriteAllTextAsync(receivedPath, output).ConfigureAwait(false); + failures.Add($"{fileName} does not match the output; see {Path.GetFileName(receivedPath)}"); + } + + /// Deletes or reports the snapshots under a name that the run no longer produced. + /// The snapshot name before the hint name. + /// The snapshot file names the run produced. + /// Whether stale snapshots are deleted rather than reported. + /// The failures so far, added to for each stale snapshot. + private static void RemoveStale(string prefix, HashSet produced, bool accept, List failures) + { + foreach (var snapshot in Directory.EnumerateFiles(SnapshotDirectory, $"{prefix}*.verified.*")) + { + var fileName = Path.GetFileName(snapshot); + if (produced.Contains(fileName)) + { + continue; + } + + if (accept) + { + File.Delete(snapshot); + } + else + { + failures.Add($"{fileName} is no longer produced"); + } + } + } + + /// Reads the snapshot directory the test project recorded when it was built. + /// The absolute path of the snapshot directory. + /// The test assembly records no snapshot directory. + private static string ReadSnapshotDirectory() + { + // Recorded at build time: a CI build maps caller file paths to /_/, which does not exist on disk. + foreach (var attribute in typeof(GeneratorSnapshot).Assembly.GetCustomAttributes()) + { + if (attribute.Key == DirectoryMetadataKey && !string.IsNullOrEmpty(attribute.Value)) + { + return attribute.Value; + } + } + + throw new InvalidOperationException($"The test assembly records no '{DirectoryMetadataKey}' assembly metadata."); + } + + /// Normalises line endings so a snapshot compares the same on every checkout. + /// The text to normalise. + /// The text with LF line endings. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string Normalize(string text) => text.Replace("\r\n", "\n", StringComparison.Ordinal); +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorTests.cs new file mode 100644 index 00000000..65ca6a73 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/GeneratorTests.cs @@ -0,0 +1,143 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// Tests the pipeline: what it adds, and what an edit makes it redo. +public sealed class GeneratorTests +{ + /// The file that makes the registrations. + private const string Registrations = """ + using Splat; + + namespace T + { + public interface IA { } + public interface IB { } + public sealed class A : IA { public A(IB b) { } } + public sealed class B : IB { } + + public static class Bootstrapper + { + public static void Register() + { + SplatRegistrations.Register(); + SplatRegistrations.RegisterLazySingleton(); + } + } + } + """; + + /// The path of the first file of a test compilation. + private const string FirstFile = "File0.cs"; + + /// A project with no registrations gets the marker source and no registrations file. + /// A task representing the asynchronous test. + [Test] + public async Task LeavesOutRegistrationsFileWithoutRegistrations() + { + var run = TestHelper.Run("namespace T { public static class C { public static void M() => Splat.SplatRegistrations.SetupIOC(); } }"); + + await Assert.That(run.RegistrationSource()).IsNull(); + await Assert.That(run.HintNames()).Contains(Constants.ExtensionMethodFileName); + await Assert.That(run.Errors()).IsEmpty(); + } + + /// The generated registrations compile against Splat. + /// A task representing the asynchronous test. + [Test] + public async Task GeneratesCompilingRegistrations() + { + var run = TestHelper.Run(Registrations); + + await Assert.That(run.RegistrationSource()).IsNotNull(); + await Assert.That(run.Errors()).IsEmpty(); + await Assert.That(run.Result.Diagnostics).IsEmpty(); + } + + /// An edit to a file without registrations reuses every registration and the generated file. + /// A task representing the asynchronous test. + [Test] + public async Task EditElsewhereReusesEverything() + { + var compilation = TestHelper.CreateCompilation([Registrations, "namespace T { public static class U { public static int V => 1; } }"]); + var first = TestHelper.Run(compilation); + + var edited = ReplaceFile(compilation, "File1.cs", "namespace T { public static class U { public static int V => 2; } }"); + var second = first.Driver.RunGenerators(edited).GetRunResult().Results[0]; + + await Assert.That(OutputReasons(second, Generator.CollectedRegistrationsStep)).IsEquivalentTo([IncrementalStepRunReason.Cached]); + await Assert.That(OutputReasons(second, Generator.RegistrationsStep)).DoesNotContain(IncrementalStepRunReason.Modified); + } + + /// An edit that only moves the registrations re-extracts them, but leaves the generated file as it was. + /// A task representing the asynchronous test. + [Test] + public async Task EditThatMovesRegistrationsKeepsGeneratedFile() + { + var compilation = TestHelper.CreateCompilation([Registrations]); + var first = TestHelper.Run(compilation); + + var edited = ReplaceFile(compilation, FirstFile, $"\n\n{Registrations}"); + var second = first.Driver.RunGenerators(edited).GetRunResult().Results[0]; + + await Assert.That(OutputReasons(second, Generator.SitesStep)).Contains(IncrementalStepRunReason.Modified); + await Assert.That(OutputReasons(second, Generator.RegistrationsStep)).DoesNotContain(IncrementalStepRunReason.Modified); + await Assert.That(OutputReasons(second, Generator.CollectedRegistrationsStep)).DoesNotContain(IncrementalStepRunReason.Modified); + } + + /// An edit that changes a registration regenerates the file. + /// A task representing the asynchronous test. + [Test] + public async Task EditThatChangesRegistrationRegenerates() + { + var compilation = TestHelper.CreateCompilation([Registrations]); + var first = TestHelper.Run(compilation); + + var edited = ReplaceFile(compilation, FirstFile, Registrations.Replace("Register();", "Register(\"c\");", StringComparison.Ordinal)); + var second = first.Driver.RunGenerators(edited).GetRunResult().Results[0]; + + await Assert.That(OutputReasons(second, Generator.CollectedRegistrationsStep)).IsEquivalentTo([IncrementalStepRunReason.Modified]); + } + + /// Gets the reasons each output of a tracked step was produced for. + /// The run. + /// The step's tracking name. + /// The reasons. + private static List OutputReasons(in GeneratorRunResult result, string stepName) + { + var reasons = new List(); + foreach (var step in result.TrackedSteps[stepName]) + { + foreach (var output in step.Outputs) + { + reasons.Add(output.Reason); + } + } + + return reasons; + } + + /// Replaces one file of a compilation. + /// The compilation. + /// The file's path. + /// The new text. + /// The edited compilation. + /// The compilation has no file at the path. + private static Compilation ReplaceFile(Compilation compilation, string path, string source) + { + foreach (var tree in compilation.SyntaxTrees) + { + if (tree.FilePath == path) + { + return compilation.ReplaceSyntaxTree(tree, CSharpSyntaxTree.ParseText(source, TestHelper.ParseOptions, path)); + } + } + + throw new InvalidOperationException($"The compilation has no file {path}."); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.Reg.g.verified.cs index 3a97bed6..db93dd3e 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1"))); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.Reg.g.verified.cs index 09d25994..74588cc2 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2"))); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.Reg.g.verified.cs index a59c280b..4ee0c256 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,21 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs index e48ec7fa..e5cbdddb 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs index 424a5359..68f8f7e4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs index 1f887e01..4f4e2f6d 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.Reg.g.verified.cs index b919f8b0..f5c0e44b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.Reg.g.verified.cs index 9e8b0655..dfd8066a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs index 51cd6b43..509b9d2c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs index b919f8b0..f5c0e44b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs index 9e8b0655..dfd8066a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs index 51cd6b43..509b9d2c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.Reg.g.verified.cs index a6058776..65a7b9cc 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, ExecutionAndPublication); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_EP#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.Reg.g.verified.cs index b4e75e2f..1900a9bc 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, None); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + global::System.Threading.LazyThreadSafetyMode.None); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_N#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.Reg.g.verified.cs index 69c56cbe..65cc89e2 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, PublicationOnly); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + global::System.Threading.LazyThreadSafetyMode.PublicationOnly); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test1_P#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.Reg.g.verified.cs index 4e873b21..cf87353a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, ExecutionAndPublication); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_EP#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.Reg.g.verified.cs index e21f2a05..18f44cfe 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, None); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + global::System.Threading.LazyThreadSafetyMode.None); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_N#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.Reg.g.verified.cs index 67bd8320..8a9be7f8 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, PublicationOnly); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + global::System.Threading.LazyThreadSafetyMode.PublicationOnly); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_Test2_P#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.Reg.g.verified.cs index 06acb71c..8decd424 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }, ExecutionAndPublication); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }, + global::System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_EP#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.Reg.g.verified.cs index 4ed56608..b0373334 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }, None); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }, + global::System.Threading.LazyThreadSafetyMode.None); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_N#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.Reg.g.verified.cs index e9b92349..8067d3c5 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }, PublicationOnly); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }, + global::System.Threading.LazyThreadSafetyMode.PublicationOnly); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPILM_contractParameter=_P#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.Reg.g.verified.cs index a9debc77..5dcb2dd2 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.Reg.g.verified.cs index 69e84f06..3f647529 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs index 939872dd..34d2ce13 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,26 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CMPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPIF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.Reg.g.verified.cs index b919f8b0..f5c0e44b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.Reg.g.verified.cs index 9e8b0655..dfd8066a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,25 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs index 51cd6b43..509b9d2c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..54ee982d --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,84): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,77): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs index fdb02e53..3729b9a4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,38 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.ITest2", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1"))); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy1); + resolver.Register(() => lazy1.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1.verified.txt deleted file mode 100644 index 8622a546..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test1.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton(); -*/ - : (10,12)-(10,84), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test1"); - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,77), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..54ee982d --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,84): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,77): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs index fb85643e..badb967e 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,38 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.ITest2", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2"))); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy1); + resolver.Register(() => lazy1.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2.verified.txt deleted file mode 100644 index c18f56d4..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_Test2.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton(); -*/ - : (10,12)-(10,84), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test2"); - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,77), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..e8c187e4 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,77): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,77): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs index 1634fbb7..e9223eb9 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest2"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy1); + resolver.Register(() => lazy1.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=.verified.txt deleted file mode 100644 index eb08bef8..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CircularDependencyF_contractParameter=.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton(); -*/ - : (10,12)-(10,77), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton(); - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,77), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.Reg.g.verified.cs index ba046d62..2f9a694d 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,9 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete()); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete()); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.Reg.g.verified.cs index 0f3c3fe2..eb8fcbaf 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,9 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete()); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete()); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs index 91d45508..1769efe0 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,9 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete()); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete()); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.EConstructor_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..8ea10657 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(12,12)-(12,68): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(13,12)-(13,68): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.Reg.g.verified.cs index c310f63f..388b702c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.Reg.g.verified.cs @@ -27,11 +27,11 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceB(), "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetServices("Test1"))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetServices("Test1"))); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1.verified.txt deleted file mode 100644 index 3aeca788..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test1.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test1"); - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test1"); -*/ - : (12,12)-(12,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test1"); - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (13,12)-(13,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..8ea10657 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(12,12)-(12,68): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(13,12)-(13,68): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.Reg.g.verified.cs index 3cbbe6f5..5dd0356b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.Reg.g.verified.cs @@ -27,11 +27,11 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceB(), "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetServices("Test2"))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetServices("Test2"))); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2.verified.txt deleted file mode 100644 index 269e936d..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_Test2.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test2"); - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test2"); -*/ - : (12,12)-(12,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test2"); - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (13,12)-(13,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..965b7b8e --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(12,12)-(12,61): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(13,12)-(13,61): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.Reg.g.verified.cs index 875df690..4c3cfea4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -27,11 +27,11 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceB()); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetServices())); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetServices())); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=.verified.txt deleted file mode 100644 index d81b8724..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IEnumerableDependencyInLSingleton_contractParameter=.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.RegisterLazySingleton(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (12,12)-(12,61), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (13,12)-(13,61), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..6e37d2d7 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,83): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,83): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.Reg.g.verified.cs index a5b15529..703304c4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,13 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1()); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete1()); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2()); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy1 = new global::System.Lazy(() => new global::Test.TestConcrete2()); + resolver.Register>(() => lazy1, "Test1"); + resolver.Register(() => lazy1.Value, "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1.verified.txt deleted file mode 100644 index 0b85bcf3..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test1.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton("Test1"); -*/ - : (10,12)-(10,83), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test1"); - SplatRegistrations.RegisterLazySingleton("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,83), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..6e37d2d7 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,83): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,83): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.Reg.g.verified.cs index c12f0982..86e74848 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,13 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1()); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete1()); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2()); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy1 = new global::System.Lazy(() => new global::Test.TestConcrete2()); + resolver.Register>(() => lazy1, "Test2"); + resolver.Register(() => lazy1.Value, "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2.verified.txt deleted file mode 100644 index 00b7482a..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_Test2.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton("Test2"); -*/ - : (10,12)-(10,83), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton("Test2"); - SplatRegistrations.RegisterLazySingleton("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,83), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..acd1e892 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,76): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,76): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs index 2d11299c..e588af3d 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,17 +23,13 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1()); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy(() => new global::Test.TestConcrete1()); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2()); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy1 = new global::System.Lazy(() => new global::Test.TestConcrete2()); + resolver.Register>(() => lazy1); + resolver.Register(() => lazy1.Value); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=.verified.txt deleted file mode 100644 index 8d452ecc..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.IRegMx_contractParameter=.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterLazySingleton(); -*/ - : (10,12)-(10,76), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.RegisterLazySingleton(); - SplatRegistrations.RegisterLazySingleton(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,76), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.Reg.g.verified.cs index fac9e3fc..088311e3 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.Reg.g.verified.cs @@ -23,15 +23,32 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService>("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService>("Test1") ?? ThrowNotRegistered>("global::System.Lazy", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + "Test1"); resolver.Register(() => new global::Test.Service1(), "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.Service2()); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.Service2()); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.Reg.g.verified.cs index 25f6d4f4..33a8224e 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.Reg.g.verified.cs @@ -23,15 +23,32 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService>("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService>("Test2") ?? ThrowNotRegistered>("global::System.Lazy", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + "Test2"); resolver.Register(() => new global::Test.Service1(), "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.Service2()); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy(() => new global::Test.Service2()); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.Reg.g.verified.cs index bd2125c5..56916d94 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,15 +23,30 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService>() ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService>() ?? ThrowNotRegistered>("global::System.Lazy")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }); resolver.Register(() => new global::Test.Service1()); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.Service2()); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy(() => new global::Test.Service2()); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.LPmRegL_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs index 8602fb43..46ea98f1 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,21 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"))); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs index 31e260a4..f573b2a9 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,21 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"))); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs index 778c0a54..bac74bba 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"))); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs index ba568b33..fb339a4b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs @@ -23,23 +23,36 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1"))); + resolver.Register>(() => lazy0, "Test1"); + resolver.Register(() => lazy0.Value, "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1"))); + resolver.Register>(() => lazy1, "Test1"); + resolver.Register(() => lazy1.Value, "Test1"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete3(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test1"); - resolver.Register(() => lazy.Value, "Test1"); - } + var lazy2 = new global::System.Lazy( + () => new global::Test.TestConcrete3( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1"))); + resolver.Register>(() => lazy2, "Test1"); + resolver.Register(() => lazy2.Value, "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs index ab84c81d..1981a53c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs @@ -23,23 +23,36 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2"))); + resolver.Register>(() => lazy0, "Test2"); + resolver.Register(() => lazy0.Value, "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2"))); + resolver.Register>(() => lazy1, "Test2"); + resolver.Register(() => lazy1.Value, "Test2"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete3(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver."))); - resolver.Register>(() => lazy, "Test2"); - resolver.Register(() => lazy.Value, "Test2"); - } + var lazy2 = new global::System.Lazy( + () => new global::Test.TestConcrete3( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2"))); + resolver.Register>(() => lazy2, "Test2"); + resolver.Register(() => lazy2.Value, "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs index 10ac5318..c342cc64 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,23 +23,35 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete1(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete1( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy0); + resolver.Register(() => lazy0.Value); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy1 = new global::System.Lazy( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy1); + resolver.Register(() => lazy1.Value); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete3(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); - resolver.Register>(() => lazy); - resolver.Register(() => lazy.Value); - } + var lazy2 = new global::System.Lazy( + () => new global::Test.TestConcrete3( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + resolver.Register>(() => lazy2); + resolver.Register(() => lazy2.Value); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.Reg.g.verified.cs index bda08ad8..44d8b355 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.Reg.g.verified.cs @@ -29,11 +29,25 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceProperty2(), "TestContract"); - { - global::System.Lazy lazy = new global::System.Lazy(() => new global::Test.TestConcrete(resolver.GetService("TestContract") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "TestContract" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("TestContract") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "TestContract" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("TestContract") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "TestContract" + " not registered with Splat resolver.") }); - resolver.Register>(() => lazy, "TestContract"); - resolver.Register(() => lazy.Value, "TestContract"); - } + var lazy0 = new global::System.Lazy( + () => new global::Test.TestConcrete( + resolver.GetService("TestContract") ?? ThrowNotRegistered("global::Test.IService1", "TestContract")) + { + ServiceProperty1 = resolver.GetService("TestContract") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "TestContract"), + ServiceProperty2 = resolver.GetService("TestContract") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "TestContract"), + }); + resolver.Register>(() => lazy0, "TestContract"); + resolver.Register(() => lazy0.Value, "TestContract"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.PIWithContractInLSingleton_TestContract#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/MetadataExtractorTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/MetadataExtractorTests.cs deleted file mode 100644 index 696468da..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/MetadataExtractorTests.cs +++ /dev/null @@ -1,771 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Collections.Immutable; - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Splat.DependencyInjection.SourceGenerator.Tests; - -/// -/// Tests for MetadataExtractor. -/// -public class MetadataExtractorTests -{ - /// - /// Verifies ExtractConstructorParameters handles empty constructor list. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractConstructorParameters_NoConstructors_ReturnsEmpty() - { - // Static class has no instance constructors - var syntaxTree = CSharpSyntaxTree.ParseText("public static class StaticClass {}"); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("StaticClass"); - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - var result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - - await Assert.That(result).IsNotNull(); - await Assert.That(result!).IsEmpty(); - } - - /// - /// Verifies ExtractPropertyInjections handles read-only properties (no setter). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractPropertyInjections_ReadOnly_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - namespace Splat { - public class DependencyInjectionPropertyAttribute : System.Attribute {} - } - public class TestClass { - [Splat.DependencyInjectionProperty] - public string Prop { get; } - } - "); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("TestClass"); - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - var result = MetadataExtractor.ExtractPropertyInjections(type!, symbols.PropertyAttribute); - - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractConstructorParameters handles multiple constructors correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractConstructorParameters_MultipleConstructors_Logic() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - } - public class SingleCtor { - public SingleCtor(int i) {} - } - public class PrivateCtor { - private PrivateCtor() {} - } - public class MultipleCtorNoAttr { - public MultipleCtorNoAttr() {} - public MultipleCtorNoAttr(int i) {} - } - public class MultipleCtorOneAttr { - public MultipleCtorOneAttr() {} - [Splat.DependencyInjectionConstructor] - public MultipleCtorOneAttr(int i) {} - } - public class MultipleCtorTwoAttr { - [Splat.DependencyInjectionConstructor] - public MultipleCtorTwoAttr() {} - [Splat.DependencyInjectionConstructor] - public MultipleCtorTwoAttr(int i) {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - // 1. Single public ctor - var type = compilation.GetTypeByMetadataName("SingleCtor"); - var result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - await Assert.That(result).IsNotNull(); - await Assert.That(result!).Count().IsEqualTo(1); - - // 2. Private ctor - type = compilation.GetTypeByMetadataName("PrivateCtor"); - result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - await Assert.That(result).IsNull(); - - // 3. Multiple ctors, no attribute - type = compilation.GetTypeByMetadataName("MultipleCtorNoAttr"); - result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - await Assert.That(result).IsNull(); - - // 4. Multiple ctors, one attribute - type = compilation.GetTypeByMetadataName("MultipleCtorOneAttr"); - result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - await Assert.That(result).IsNotNull(); - await Assert.That(result!).Count().IsEqualTo(1); - await Assert.That(result![0].ParameterName).IsEqualTo("i"); - - // 5. Multiple ctors, two attributes - type = compilation.GetTypeByMetadataName("MultipleCtorTwoAttr"); - result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractConstructorParameters handles special types like Lazy and IEnumerable. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractConstructorParameters_SpecialTypes() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System; - using System.Collections.Generic; - public class SpecialTypes { - public SpecialTypes(Lazy lazy, IEnumerable list) {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Lazy<>).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Collections.Generic.IEnumerable<>).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("SpecialTypes"); - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - var result = MetadataExtractor.ExtractConstructorParameters(type!, symbols); - - await Assert.That(result).IsNotNull(); - await Assert.That(result!).Count().IsEqualTo(2); - - await Assert.That(result![0].IsLazy).IsTrue(); - await Assert.That(result![0].LazyInnerType).Contains("string"); - - await Assert.That(result![1].IsCollection).IsTrue(); - await Assert.That(result![1].CollectionItemType).Contains("int"); - } - - /// - /// Verifies ExtractPropertyInjections handles various property scenarios. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractPropertyInjections_Logic() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionPropertyAttribute : System.Attribute {} - } - public class Base { - [Splat.DependencyInjectionProperty] - public string BaseProp { get; set; } - } - public class Derived : Base { - [Splat.DependencyInjectionProperty] - public int DerivedProp { get; set; } - - public double NoAttr { get; set; } - } - public class PrivateSetter { - [Splat.DependencyInjectionProperty] - public string Prop { get; private set; } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - // 1. Derived class (should get base prop too) - var type = compilation.GetTypeByMetadataName("Derived"); - var result = MetadataExtractor.ExtractPropertyInjections(type!, symbols.PropertyAttribute); - await Assert.That(result).IsNotNull(); - await Assert.That(result!).Count().IsEqualTo(2); - await Assert.That(result!.Any(p => p.PropertyName == "BaseProp")).IsTrue(); - await Assert.That(result!.Any(p => p.PropertyName == "DerivedProp")).IsTrue(); - - // 2. Private setter - type = compilation.GetTypeByMetadataName("PrivateSetter"); - result = MetadataExtractor.ExtractPropertyInjections(type!, symbols.PropertyAttribute); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies HasAttribute returns true when symbol comparison matches. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task HasAttribute_SymbolComparison_ReturnsTrue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - } - public class MyClass { - [Splat.DependencyInjectionConstructor] - public MyClass() {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var ctor = type.Constructors[0]; - var attributeSymbol = compilation.GetTypeByMetadataName(Constants.ConstructorAttributeMetadataName); - - var result = MetadataExtractor.HasAttribute(ctor, attributeSymbol, Constants.ConstructorAttribute); - - await Assert.That(result).IsTrue(); - } - - /// - /// Verifies HasAttribute returns false when attribute is not present. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task HasAttribute_NoAttribute_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public class MyClass { - public MyClass() {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var ctor = type.Constructors[0]; - - var result = MetadataExtractor.HasAttribute(ctor, null, Constants.ConstructorAttribute); - - await Assert.That(result).IsFalse(); - } - - /// - /// Verifies HasAttribute falls back to string comparison when symbol is null. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task HasAttribute_StringFallback_ReturnsTrue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - } - public class MyClass { - [Splat.DependencyInjectionConstructor] - public MyClass() {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var ctor = type.Constructors[0]; - - // Pass null symbol to force string fallback path - var result = MetadataExtractor.HasAttribute(ctor, null, Constants.ConstructorAttribute); - - await Assert.That(result).IsTrue(); - } - - /// - /// Verifies HasAttribute returns false via symbol comparison when attribute does not match. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task HasAttribute_SymbolPath_NonMatchingAttribute_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - } - public class MyClass { - [System.Obsolete] - public MyClass() {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var ctor = type.Constructors[0]; - var attributeSymbol = compilation.GetTypeByMetadataName(Constants.ConstructorAttributeMetadataName); - - // ctor has [Obsolete] but not [DependencyInjectionConstructor], with non-null symbol - var result = MetadataExtractor.HasAttribute(ctor, attributeSymbol, Constants.ConstructorAttribute); - - await Assert.That(result).IsFalse(); - } - - /// - /// Verifies HasAttribute returns false via string fallback when attribute does not match. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task HasAttribute_StringFallback_NonMatchingAttribute_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public class MyClass { - [System.Obsolete] - public MyClass() {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var ctor = type.Constructors[0]; - - // ctor has [Obsolete], null symbol forces string fallback - should not match - var result = MetadataExtractor.HasAttribute(ctor, null, Constants.ConstructorAttribute); - - await Assert.That(result).IsFalse(); - } - - /// - /// Verifies IsOriginalDefinition matches Lazy via string fallback when symbol is null. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsOriginalDefinition_StringFallback_LazyType_ReturnsTrue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System; - public class MyClass { - public MyClass(Lazy lazy) {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Lazy<>).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var param = type.Constructors[0].Parameters[0]; - var namedType = (INamedTypeSymbol)param.Type; - - // Pass null for symbol to force string fallback - var result = MetadataExtractor.IsOriginalDefinition(namedType, null, Constants.LazyOpenGenericTypeName); - - await Assert.That(result).IsTrue(); - } - - /// - /// Verifies IsOriginalDefinition matches Lazy via symbol comparison. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsOriginalDefinition_LazyType_MatchesViaSymbol() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System; - public class MyClass { - public MyClass(Lazy lazy) {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Lazy<>).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var param = type.Constructors[0].Parameters[0]; - var namedType = (INamedTypeSymbol)param.Type; - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - var result = MetadataExtractor.IsOriginalDefinition(namedType, symbols.LazyType, Constants.LazyOpenGenericTypeName); - - await Assert.That(result).IsTrue(); - } - - /// - /// Verifies IsOriginalDefinition does not match unrelated types. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsOriginalDefinition_NonLazyType_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public class MyClass { - public MyClass(string s) {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var type = compilation.GetTypeByMetadataName("MyClass")!; - var param = type.Constructors[0].Parameters[0]; - - // string is a NamedTypeSymbol but not Lazy - if (param.Type is INamedTypeSymbol namedType) - { - var result = MetadataExtractor.IsOriginalDefinition(namedType, null, Constants.LazyOpenGenericTypeName); - await Assert.That(result).IsFalse(); - } - } - - /// - /// Verifies ResolveWellKnownSymbols resolves all symbols from a compilation with appropriate references. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveWellKnownSymbols_WithReferences_ResolvesAll() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - public class DependencyInjectionPropertyAttribute : System.Attribute {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Lazy<>).Assembly.Location)); - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - await Assert.That(symbols.ConstructorAttribute).IsNotNull(); - await Assert.That(symbols.PropertyAttribute).IsNotNull(); - await Assert.That(symbols.LazyType).IsNotNull(); - await Assert.That(symbols.EnumerableType).IsNotNull(); - } - - /// - /// Verifies ResolveWellKnownSymbols returns nulls when types are not available. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveWellKnownSymbols_WithoutReferences_ReturnsNulls() - { - var syntaxTree = CSharpSyntaxTree.ParseText("public class Empty {}"); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - await Assert.That(symbols.ConstructorAttribute).IsNull(); - await Assert.That(symbols.PropertyAttribute).IsNull(); - await Assert.That(symbols.LazyType).IsNull(); - await Assert.That(symbols.EnumerableType).IsNull(); - } - - /// - /// Verifies ExtractRegisterMetadataFromSymbol returns null for a non-Splat method. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractRegisterMetadataFromSymbol_NonSplatMethod_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public static class Other { - public static void Register() {} - } - public class Usage { - public void M() { Other.Register(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = MetadataExtractor.ExtractRegisterMetadataFromSymbol( - methodSymbol, invocation, semanticModel, default, CancellationToken.None); - - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractRegisterMetadataFromSymbol returns null when method has zero type arguments. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractRegisterMetadataFromSymbol_ZeroTypeParams_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void Register() {} - } - } - public class Usage { - public void M() { Splat.SplatRegistrations.Register(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = MetadataExtractor.ExtractRegisterMetadataFromSymbol( - methodSymbol, invocation, semanticModel, default, CancellationToken.None); - - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractLazySingletonMetadataFromSymbol returns null for a non-Splat method. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazySingletonMetadataFromSymbol_NonSplatMethod_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public static class Other { - public static void RegisterLazySingleton() {} - } - public class Usage { - public void M() { Other.RegisterLazySingleton(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = MetadataExtractor.ExtractLazySingletonMetadataFromSymbol( - methodSymbol, invocation, semanticModel, default, CancellationToken.None); - - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractLazySingletonMetadataFromSymbol returns null when method has zero type arguments. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazySingletonMetadataFromSymbol_ZeroTypeParams_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton() {} - } - } - public class Usage { - public void M() { Splat.SplatRegistrations.RegisterLazySingleton(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = MetadataExtractor.ExtractLazySingletonMetadataFromSymbol( - methodSymbol, invocation, semanticModel, default, CancellationToken.None); - - await Assert.That(result).IsNull(); - } - - /// - /// Verifies GetFirstLocation returns Location.None for an empty locations array. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFirstLocation_EmptyArray_ReturnsLocationNone() - { - var result = MetadataExtractor.GetFirstLocation(ImmutableArray.Empty); - - await Assert.That(result).IsEqualTo(Location.None); - } - - /// - /// Verifies GetFirstLocation returns the first location when locations are present. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFirstLocation_WithLocations_ReturnsFirst() - { - var tree = CSharpSyntaxTree.ParseText("class C {}"); - var location = tree.GetRoot().GetLocation(); - var locations = ImmutableArray.Create(location); - - var result = MetadataExtractor.GetFirstLocation(locations); - - await Assert.That(result).IsEqualTo(location); - } - - /// - /// Verifies ResolveWellKnownSymbols returns the same result for the same compilation instance (cache hit). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveWellKnownSymbols_SameCompilation_ReturnsCachedResult() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - public class DependencyInjectionPropertyAttribute : System.Attribute {} - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Lazy<>).Assembly.Location)); - - var first = MetadataExtractor.ResolveWellKnownSymbols(compilation); - var second = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - // Struct equality — same symbols should be resolved both times - await Assert.That(first).IsEqualTo(second); - - // Verify the symbols are actually populated (not default) - await Assert.That(first.ConstructorAttribute).IsNotNull(); - await Assert.That(first.PropertyAttribute).IsNotNull(); - } - - /// - /// Verifies ResolveWellKnownSymbols returns independent results for different compilation instances. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveWellKnownSymbols_DifferentCompilations_ReturnsIndependentResults() - { - var syntaxTree1 = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - public class DependencyInjectionPropertyAttribute : System.Attribute {} - } - """); - - var compilation1 = CSharpCompilation.Create("TestAssembly1", [syntaxTree1]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var syntaxTree2 = CSharpSyntaxTree.ParseText("public class Empty {}"); - var compilation2 = CSharpCompilation.Create("TestAssembly2", [syntaxTree2]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var symbols1 = MetadataExtractor.ResolveWellKnownSymbols(compilation1); - var symbols2 = MetadataExtractor.ResolveWellKnownSymbols(compilation2); - - // First compilation has Splat attributes - await Assert.That(symbols1.ConstructorAttribute).IsNotNull(); - await Assert.That(symbols1.PropertyAttribute).IsNotNull(); - - // Second compilation does not - await Assert.That(symbols2.ConstructorAttribute).IsNull(); - await Assert.That(symbols2.PropertyAttribute).IsNull(); - } - - /// - /// Verifies ExtractRegisterMetadataFromSymbol uses the explicitly provided WellKnownSymbols parameter. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractRegisterMetadataFromSymbol_WithExplicitSymbols_UsesProvidedSymbols() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - public class DependencyInjectionPropertyAttribute : System.Attribute {} - public static class SplatRegistrations { - public static void Register() {} - } - } - public class MyService {} - public interface IMyService {} - public class Usage { - public void M() { Splat.SplatRegistrations.Register(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - var result = MetadataExtractor.ExtractRegisterMetadataFromSymbol( - methodSymbol, invocation, semanticModel, symbols, CancellationToken.None); - - await Assert.That(result).IsNotNull(); - await Assert.That(result!.InterfaceTypeFullName).Contains("IMyService"); - await Assert.That(result!.ConcreteTypeFullName).Contains("MyService"); - } - - /// - /// Verifies ExtractLazySingletonMetadataFromSymbol uses the explicitly provided WellKnownSymbols parameter. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazySingletonMetadataFromSymbol_WithExplicitSymbols_UsesProvidedSymbols() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public class DependencyInjectionConstructorAttribute : System.Attribute {} - public class DependencyInjectionPropertyAttribute : System.Attribute {} - public static class SplatRegistrations { - public static void RegisterLazySingleton() {} - } - } - public class MyService {} - public interface IMyService {} - public class Usage { - public void M() { Splat.SplatRegistrations.RegisterLazySingleton(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var invocation = syntaxTree.GetRoot().DescendantNodes() - .OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var symbols = MetadataExtractor.ResolveWellKnownSymbols(compilation); - - var result = MetadataExtractor.ExtractLazySingletonMetadataFromSymbol( - methodSymbol, invocation, semanticModel, symbols, CancellationToken.None); - - await Assert.That(result).IsNotNull(); - await Assert.That(result!.InterfaceTypeFullName).Contains("IMyService"); - await Assert.That(result!.ConcreteTypeFullName).Contains("MyService"); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/ConstructorParameterTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/ConstructorParameterTests.cs deleted file mode 100644 index 271dedc3..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/ConstructorParameterTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests.Models; - -/// -/// Tests for the ConstructorParameter model class. -/// Ensures proper equality and record behavior for constructor parameter metadata. -/// -public class ConstructorParameterTests -{ - /// - /// Tests that two ConstructorParameter instances with the same values are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_WithSameValues_AreEqual() - { - var param1 = new ConstructorParameter("service", "global::Test.IService", false, null, false, null); - var param2 = new ConstructorParameter("service", "global::Test.IService", false, null, false, null); - - await Assert.That(param1).IsEqualTo(param2); - await Assert.That(param1.GetHashCode()).IsEqualTo(param2.GetHashCode()); - } - - /// - /// Tests that two ConstructorParameter instances with different parameter names are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_WithDifferentParameterName_AreNotEqual() - { - var param1 = new ConstructorParameter("service1", "global::Test.IService", false, null, false, null); - var param2 = new ConstructorParameter("service2", "global::Test.IService", false, null, false, null); - - await Assert.That(param1).IsNotEqualTo(param2); - } - - /// - /// Tests that two ConstructorParameter instances with different type names are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_WithDifferentTypeName_AreNotEqual() - { - var param1 = new ConstructorParameter("service", "global::Test.IService1", false, null, false, null); - var param2 = new ConstructorParameter("service", "global::Test.IService2", false, null, false, null); - - await Assert.That(param1).IsNotEqualTo(param2); - } - - /// - /// Tests that two ConstructorParameter instances with different IsLazy values are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_WithDifferentIsLazy_AreNotEqual() - { - var param1 = new ConstructorParameter("service", "global::Test.IService", false, null, false, null); - var param2 = new ConstructorParameter("service", "global::Test.IService", true, "global::Test.IService", false, null); - - await Assert.That(param1).IsNotEqualTo(param2); - } - - /// - /// Tests that two ConstructorParameter instances with different LazyInnerType values are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_WithDifferentLazyInnerType_AreNotEqual() - { - var param1 = new ConstructorParameter("service", "global::System.Lazy", true, "global::Test.IService1", false, null); - var param2 = new ConstructorParameter("service", "global::System.Lazy", true, "global::Test.IService2", false, null); - - await Assert.That(param1).IsNotEqualTo(param2); - } - - /// - /// Tests that ConstructorParameter properties can be accessed correctly for non-lazy parameters. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_NonLazy_Properties_AreAccessible() - { - var param = new ConstructorParameter("myParam", "global::Test.IMyType", false, null, false, null); - - await Assert.That(param.ParameterName).IsEqualTo("myParam"); - await Assert.That(param.TypeFullName).IsEqualTo("global::Test.IMyType"); - await Assert.That(param.IsLazy).IsFalse(); - await Assert.That(param.LazyInnerType).IsNull(); - } - - /// - /// Tests that ConstructorParameter properties can be accessed correctly for lazy parameters. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task ConstructorParameter_Lazy_Properties_AreAccessible() - { - var param = new ConstructorParameter("myParam", "global::System.Lazy", true, "global::Test.IMyType", false, null); - - await Assert.That(param.ParameterName).IsEqualTo("myParam"); - await Assert.That(param.TypeFullName).IsEqualTo("global::System.Lazy"); - await Assert.That(param.IsLazy).IsTrue(); - await Assert.That(param.LazyInnerType).IsEqualTo("global::Test.IMyType"); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/EquatableArrayTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/EquatableArrayTests.cs index d9d8d4bd..6f6766a4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/EquatableArrayTests.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/EquatableArrayTests.cs @@ -1,271 +1,92 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -using System.Collections; - using Splat.DependencyInjection.SourceGenerator.Models; namespace Splat.DependencyInjection.SourceGenerator.Tests.Models; -/// -/// Tests for the EquatableArray struct. -/// Ensures proper value-equality semantics for arrays in incremental generator pipelines. -/// -public class EquatableArrayTests +/// Tests the value equality gives the pipeline models. +public sealed class EquatableArrayTests { - /// - /// Tests that two EquatableArray instances with the same values are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_WithSameValues_AreEqual() - { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "a", "b", "c" }); - - await Assert.That(array1.Equals(array2)).IsTrue(); - await Assert.That(array1 == array2).IsTrue(); - await Assert.That(array1 != array2).IsFalse(); - await Assert.That(array1.GetHashCode()).IsEqualTo(array2.GetHashCode()); - } + /// A first value. + private const int First = 1; - /// - /// Tests that two EquatableArray instances with different values are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_WithDifferentValues_AreNotEqual() - { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "a", "b", "d" }); + /// A second value. + private const int Second = 2; - await Assert.That(array1.Equals(array2)).IsFalse(); - await Assert.That(array1 == array2).IsFalse(); - await Assert.That(array1 != array2).IsTrue(); - } + /// A third value, and the length of a three-element array. + private const int Third = 3; - /// - /// Tests that two EquatableArray instances with different lengths are not equal. - /// - /// A task representing the asynchronous test operation. + /// Arrays with the same elements are equal and hash alike, whichever array holds them. + /// A task representing the asynchronous test. [Test] - public async Task EquatableArray_WithDifferentLengths_AreNotEqual() + public async Task EqualByContent() { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "a", "b" }); + var left = new EquatableArray(["a", "b"]); + var right = new EquatableArray(["a", "b"]); - await Assert.That(array1.Equals(array2)).IsFalse(); - await Assert.That(array1 == array2).IsFalse(); - await Assert.That(array1 != array2).IsTrue(); + await Assert.That(left.Equals(right)).IsTrue(); + await Assert.That(left == right).IsTrue(); + await Assert.That(left != right).IsFalse(); + await Assert.That(left.Equals((object)right)).IsTrue(); + await Assert.That(left.GetHashCode()).IsEqualTo(right.GetHashCode()); } - /// - /// Tests that two default EquatableArray instances are equal. - /// - /// A task representing the asynchronous test operation. + /// Arrays differing in length, or in an element, are unequal. + /// A task representing the asynchronous test. [Test] - public async Task EquatableArray_DefaultInstances_AreEqual() + public async Task UnequalByContent() { - var array1 = default(EquatableArray); - var array2 = default(EquatableArray); + var array = new EquatableArray(["a", "b"]); - await Assert.That(array1.Equals(array2)).IsTrue(); - await Assert.That(array1 == array2).IsTrue(); - await Assert.That(array1 != array2).IsFalse(); - await Assert.That(array1.GetHashCode()).IsEqualTo(array2.GetHashCode()); + await Assert.That(array.Equals(new(["a"]))).IsFalse(); + await Assert.That(array.Equals(new(["a", "c"]))).IsFalse(); + await Assert.That(array == new EquatableArray(["b", "a"])).IsFalse(); + await Assert.That(array.Equals("a")).IsFalse(); } - /// - /// Tests that default EquatableArray and one with null array are equal. - /// - /// A task representing the asynchronous test operation. + /// Two arrays that hash alike but differ are told apart by their elements. + /// A task representing the asynchronous test. [Test] - public async Task EquatableArray_NullArrays_AreEqual() + public async Task UnequalWithSameHash() { - var array1 = new EquatableArray(null!); - var array2 = default(EquatableArray); + var left = new EquatableArray([new(First), new(Second)]); + var right = new EquatableArray([new(First), new(Third)]); - await Assert.That(array1.Equals(array2)).IsTrue(); - await Assert.That(array1 == array2).IsTrue(); - await Assert.That(array1 != array2).IsFalse(); + await Assert.That(left.GetHashCode()).IsEqualTo(right.GetHashCode()); + await Assert.That(left.Equals(right)).IsFalse(); } - /// - /// Tests that EquatableArray with null array and one with values are not equal. - /// - /// A task representing the asynchronous test operation. + /// A default array is empty, and equal to an empty array. + /// A task representing the asynchronous test. [Test] - public async Task EquatableArray_NullVsNonNull_AreNotEqual() + public async Task DefaultIsEmpty() { - var array1 = new EquatableArray(null!); - var array2 = new EquatableArray(new[] { "a" }); + var empty = default(EquatableArray); - await Assert.That(array1.Equals(array2)).IsFalse(); - await Assert.That(array2.Equals(array1)).IsFalse(); + await Assert.That(empty.Length).IsEqualTo(0); + await Assert.That(empty.Equals(EquatableArray.Empty)).IsTrue(); + await Assert.That(empty.Equals(default)).IsTrue(); } - /// - /// Tests that Length property returns correct value. - /// - /// A task representing the asynchronous test operation. + /// The indexer reads the elements in order. + /// A task representing the asynchronous test. [Test] - public async Task EquatableArray_Length_ReturnsCorrectValue() + public async Task IndexesInOrder() { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = default(EquatableArray); - - await Assert.That(array1.Length).IsEqualTo(3); - await Assert.That(array2.Length).IsEqualTo(0); - } - - /// - /// Tests that indexer returns correct values. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_Indexer_ReturnsCorrectValue() - { - var array = new EquatableArray(new[] { "a", "b", "c" }); + var array = new EquatableArray(["a", "b", "c"]); await Assert.That(array[0]).IsEqualTo("a"); await Assert.That(array[1]).IsEqualTo("b"); - await Assert.That(array[2]).IsEqualTo("c"); + await Assert.That(array.Length).IsEqualTo(Third); } - /// - /// Tests that GetEnumerator returns all elements. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_GetEnumerator_ReturnsAllElements() - { - var array = new EquatableArray(new[] { "a", "b", "c" }); - var list = new List(array); - - await Assert.That(list.Count).IsEqualTo(3); - await Assert.That(list[0]).IsEqualTo("a"); - await Assert.That(list[1]).IsEqualTo("b"); - await Assert.That(list[2]).IsEqualTo("c"); - } - - /// - /// Tests that GetEnumerator works with null array. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_NullArray_GetEnumerator_ReturnsEmpty() - { - var array = new EquatableArray(null!); - var list = new List(array); - - await Assert.That(list.Count).IsEqualTo(0); - } - - /// - /// Tests that explicit IEnumerable.GetEnumerator works. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_ExplicitIEnumerable_GetEnumerator_Works() - { - var array = new EquatableArray(new[] { "a", "b", "c" }); - IEnumerable enumerable = array; - var list = enumerable.Cast().ToList(); - - await Assert.That(list.Count).IsEqualTo(3); - await Assert.That(list[0]).IsEqualTo("a"); - await Assert.That(list[1]).IsEqualTo("b"); - await Assert.That(list[2]).IsEqualTo("c"); - } - - /// - /// Tests that Equals with object parameter works correctly. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_EqualsObject_WorksCorrectly() + /// A value whose hash ignores its content, to force a hash collision. + /// The content. + private sealed record CollidingValue(int Value) { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "a", "b", "c" }); - object array2Obj = array2; - object nullObj = null!; - object stringObj = "test"; - - await Assert.That(array1.Equals(array2Obj)).IsTrue(); - await Assert.That(array1.Equals(nullObj)).IsFalse(); - await Assert.That(array1.Equals(stringObj)).IsFalse(); - } - - /// - /// Tests that GetHashCode returns 0 for null array. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_NullArray_GetHashCode_ReturnsZero() - { - var array = new EquatableArray(null!); - - await Assert.That(array.GetHashCode()).IsEqualTo(0); - } - - /// - /// Tests that GetHashCode is consistent. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_GetHashCode_IsConsistent() - { - var array = new EquatableArray(new[] { "a", "b", "c" }); - - var hash1 = array.GetHashCode(); - var hash2 = array.GetHashCode(); - - await Assert.That(hash1).IsEqualTo(hash2); - } - - /// - /// Tests that GetHashCode is different for arrays with different values. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_DifferentArrays_GetHashCode_IsDifferent() - { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "x", "y", "z" }); - - var hash1 = array1.GetHashCode(); - var hash2 = array2.GetHashCode(); - - // Different arrays should likely have different hash codes (though not guaranteed) - await Assert.That(hash1).IsNotEqualTo(hash2); - } - - /// - /// Tests that empty arrays are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_EmptyArrays_AreEqual() - { - var array1 = new EquatableArray(Array.Empty()); - var array2 = new EquatableArray(Array.Empty()); - - await Assert.That(array1.Equals(array2)).IsTrue(); - await Assert.That(array1 == array2).IsTrue(); - await Assert.That(array1.GetHashCode()).IsEqualTo(array2.GetHashCode()); - } - - /// - /// Tests that GetHashCode consistency is maintained across equal arrays. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task EquatableArray_EqualArrays_GetHashCode_AreEqual() - { - var array1 = new EquatableArray(new[] { "a", "b", "c" }); - var array2 = new EquatableArray(new[] { "a", "b", "c" }); - - await Assert.That(array1.GetHashCode()).IsEqualTo(array2.GetHashCode()); + /// + public override int GetHashCode() => 0; } } diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/LocationInfoTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/LocationInfoTests.cs new file mode 100644 index 00000000..5bb818cb --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/LocationInfoTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Microsoft.CodeAnalysis.CSharp; + +using Splat.DependencyInjection.SourceGenerator.Models; + +namespace Splat.DependencyInjection.SourceGenerator.Tests.Models; + +/// Tests that keeps a node's position as values and rebuilds it. +public sealed class LocationInfoTests +{ + /// The file every tree is parsed as. + private const string FilePath = "C.cs"; + + /// The start of the call each test locates. + private const string Call = "N()"; + + /// The captured location reports the same file, span and lines as the node. + /// A task representing the asynchronous test. + [Test] + public async Task RoundTripsNodeLocation() + { + var tree = CSharpSyntaxTree.ParseText("class C\n{\n void M() => N();\n}", path: FilePath); + var invocation = await TestHelper.FindInvocationAsync(tree, Call); + + var location = LocationInfo.From(invocation).ToLocation(); + + await Assert.That(location.GetLineSpan()).IsEqualTo(invocation.GetLocation().GetLineSpan()); + await Assert.That(location.SourceSpan).IsEqualTo(invocation.Span); + } + + /// The same position in two parses of a file compares equal, although the trees differ. + /// A task representing the asynchronous test. + [Test] + public async Task EqualAcrossTrees() + { + const string Source = "class C { void M() => N(); }"; + var first = await TestHelper.FindInvocationAsync(CSharpSyntaxTree.ParseText(Source, path: FilePath), Call); + var second = await TestHelper.FindInvocationAsync(CSharpSyntaxTree.ParseText(Source, path: FilePath), Call); + + await Assert.That(LocationInfo.From(first)).IsEqualTo(LocationInfo.From(second)); + await Assert.That(first.GetLocation()).IsNotEqualTo(second.GetLocation()); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/PropertyInjectionTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/PropertyInjectionTests.cs deleted file mode 100644 index 46542c93..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/PropertyInjectionTests.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using Microsoft.CodeAnalysis; - -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests.Models; - -/// -/// Tests for the PropertyInjection model class. -/// Ensures proper equality and record behavior for property injection metadata. -/// -public class PropertyInjectionTests -{ - /// - /// Tests that two PropertyInjection instances with the same values are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task PropertyInjection_WithSameValues_AreEqual() - { - var location = Location.None; - var prop1 = new PropertyInjection("Service", "global::Test.IService", location); - var prop2 = new PropertyInjection("Service", "global::Test.IService", location); - - await Assert.That(prop1).IsEqualTo(prop2); - await Assert.That(prop1.GetHashCode()).IsEqualTo(prop2.GetHashCode()); - } - - /// - /// Tests that two PropertyInjection instances with different property names are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task PropertyInjection_WithDifferentPropertyName_AreNotEqual() - { - var location = Location.None; - var prop1 = new PropertyInjection("Service1", "global::Test.IService", location); - var prop2 = new PropertyInjection("Service2", "global::Test.IService", location); - - await Assert.That(prop1).IsNotEqualTo(prop2); - } - - /// - /// Tests that two PropertyInjection instances with different type names are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task PropertyInjection_WithDifferentTypeName_AreNotEqual() - { - var location = Location.None; - var prop1 = new PropertyInjection("Service", "global::Test.IService1", location); - var prop2 = new PropertyInjection("Service", "global::Test.IService2", location); - - await Assert.That(prop1).IsNotEqualTo(prop2); - } - - /// - /// Tests that PropertyInjection properties can be accessed correctly. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task PropertyInjection_Properties_AreAccessible() - { - var location = Location.None; - var prop = new PropertyInjection("MyProperty", "global::Test.IMyType", location); - - await Assert.That(prop.PropertyName).IsEqualTo("MyProperty"); - await Assert.That(prop.TypeFullName).IsEqualTo("global::Test.IMyType"); - await Assert.That(prop.PropertyLocation).IsEqualTo(location); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/RegistrationInfoTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/RegistrationInfoTests.cs deleted file mode 100644 index 19183d49..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Models/RegistrationInfoTests.cs +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using Microsoft.CodeAnalysis; - -using Splat.DependencyInjection.SourceGenerator.Models; - -namespace Splat.DependencyInjection.SourceGenerator.Tests.Models; - -/// -/// Tests for the RegistrationInfo base record and its derived types. -/// Ensures proper equality and record behavior for registration metadata. -/// -public class RegistrationInfoTests -{ - /// - /// Tests that two TransientRegistrationInfo instances with the same values are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task TransientRegistrationInfo_WithSameValues_AreEqual() - { - var location = Location.None; - var constructorParams = new EquatableArray(new[] - { - new ConstructorParameter("param1", "global::System.String", false, null, false, null) - }); - var propertyInjections = new EquatableArray(new[] - { - new PropertyInjection("Prop1", "global::System.Int32", location) - }); - - var reg1 = new TransientRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - "contract1", - location); - - var reg2 = new TransientRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - "contract1", - location); - - await Assert.That(reg1).IsEqualTo(reg2); - await Assert.That(reg1.GetHashCode()).IsEqualTo(reg2.GetHashCode()); - } - - /// - /// Tests that two TransientRegistrationInfo instances with different interface types are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task TransientRegistrationInfo_WithDifferentInterfaceType_AreNotEqual() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - var reg1 = new TransientRegistrationInfo( - "global::Test.IService1", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - location); - - var reg2 = new TransientRegistrationInfo( - "global::Test.IService2", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - location); - - await Assert.That(reg1).IsNotEqualTo(reg2); - } - - /// - /// Tests that two LazySingletonRegistrationInfo instances with the same values are equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task LazySingletonRegistrationInfo_WithSameValues_AreEqual() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - var reg1 = new LazySingletonRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - "contract1", - "PublicationOnly", - location); - - var reg2 = new LazySingletonRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - "contract1", - "PublicationOnly", - location); - - await Assert.That(reg1).IsEqualTo(reg2); - await Assert.That(reg1.GetHashCode()).IsEqualTo(reg2.GetHashCode()); - } - - /// - /// Tests that two LazySingletonRegistrationInfo instances with different thread safety modes are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task LazySingletonRegistrationInfo_WithDifferentThreadSafetyMode_AreNotEqual() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - var reg1 = new LazySingletonRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - "PublicationOnly", - location); - - var reg2 = new LazySingletonRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - "ExecutionAndPublication", - location); - - await Assert.That(reg1).IsNotEqualTo(reg2); - } - - /// - /// Tests that TransientRegistrationInfo properties can be accessed correctly. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task TransientRegistrationInfo_Properties_AreAccessible() - { - var location = Location.None; - var constructorParams = new EquatableArray(new[] - { - new ConstructorParameter("param1", "global::System.String", false, null, false, null) - }); - var propertyInjections = new EquatableArray(new[] - { - new PropertyInjection("Prop1", "global::System.Int32", location) - }); - - var reg = new TransientRegistrationInfo( - "global::Test.IMyService", - "global::Test.MyService", - constructorParams, - propertyInjections, - "myContract", - location); - - await Assert.That(reg.InterfaceTypeFullName).IsEqualTo("global::Test.IMyService"); - await Assert.That(reg.ConcreteTypeFullName).IsEqualTo("global::Test.MyService"); - await Assert.That(reg.ConstructorParameters.Length).IsEqualTo(1); - await Assert.That(reg.PropertyInjections.Length).IsEqualTo(1); - await Assert.That(reg.ContractValue).IsEqualTo("myContract"); - await Assert.That(reg.InvocationLocation).IsEqualTo(location); - } - - /// - /// Tests that LazySingletonRegistrationInfo properties can be accessed correctly. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task LazySingletonRegistrationInfo_Properties_AreAccessible() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - var reg = new LazySingletonRegistrationInfo( - "global::Test.IMySingleton", - "global::Test.MySingleton", - constructorParams, - propertyInjections, - "mySingletonContract", - "PublicationOnly", - location); - - await Assert.That(reg.InterfaceTypeFullName).IsEqualTo("global::Test.IMySingleton"); - await Assert.That(reg.ConcreteTypeFullName).IsEqualTo("global::Test.MySingleton"); - await Assert.That(reg.ContractValue).IsEqualTo("mySingletonContract"); - await Assert.That(reg.LazyThreadSafetyMode).IsEqualTo("PublicationOnly"); - await Assert.That(reg.InvocationLocation).IsEqualTo(location); - } - - /// - /// Tests that registrations with null contract values are handled correctly. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task RegistrationInfo_WithNullContract_AreEqual() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - var reg1 = new TransientRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - location); - - var reg2 = new TransientRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - location); - - await Assert.That(reg1).IsEqualTo(reg2); - } - - /// - /// Tests that TransientRegistrationInfo and LazySingletonRegistrationInfo with same base properties are not equal. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task DifferentRegistrationTypes_AreNotEqual() - { - var location = Location.None; - var constructorParams = default(EquatableArray); - var propertyInjections = default(EquatableArray); - - RegistrationInfo reg1 = new TransientRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - location); - - RegistrationInfo reg2 = new LazySingletonRegistrationInfo( - "global::Test.IService", - "global::Test.Service", - constructorParams, - propertyInjections, - null, - null, - location); - - await Assert.That(reg1).IsNotEqualTo(reg2); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ModuleInitializer.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ModuleInitializer.cs deleted file mode 100644 index 1bd2b480..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/ModuleInitializer.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Runtime.CompilerServices; - -[assembly: NotInParallel] - -/// -/// Initialize for the module. -/// -[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1050:Declare types in namespaces", Justification = "By Design")] -[System.Diagnostics.CodeAnalysis.SuppressMessage("Roslynator", "RCS1110:Declare type inside namespace", Justification = "By Design")] -public static class ModuleInitializer -{ - /// - /// Initializes the source generators. - /// - [ModuleInitializer] - public static void Init() - { - VerifySourceGenerators.Initialize(); - VerifierSettings.UseSplitModeForUniqueDirectory(); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.Reg.g.verified.cs index 513b6fe8..c7f7918d 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,21 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")), + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.Reg.g.verified.cs index 2d483cc4..0b4f2120 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,21 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")), + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.Reg.g.verified.cs index dd1524dc..4341517b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,19 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs index 6057d6f6..916f0e11 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }, + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs index 03a6328a..fcdf4e1a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }, + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs index b0233e99..589e857d 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPITypeArgument_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.Reg.g.verified.cs index 0cdb340e..6fda9998 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }, + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.Reg.g.verified.cs index 2e50b484..8a3d0b34 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }, + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs index e2a62cfc..ac088f7a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs index 0cdb340e..6fda9998 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }, + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs index 2e50b484..8a3d0b34 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }, + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs index e2a62cfc..ac088f7a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CIntSetPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.Reg.g.verified.cs index 9dab9839..61c586e8 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,26 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.Reg.g.verified.cs index a2edacf0..b3b55d29 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,26 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs index 99253e73..10857995 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CMPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPIF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CNPPSetIF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.Reg.g.verified.cs index 0cdb340e..6fda9998 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")) + { + ServiceProperty = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test1"), + }, + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.Reg.g.verified.cs index 2e50b484..8a3d0b34 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")) + { + ServiceProperty = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty", "Test2"), + }, + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs index e2a62cfc..ac088f7a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver.")) { ServiceProperty = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2")) + { + ServiceProperty = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty"), + }); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CPI_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..c63587c2 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,71): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,64): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs index afdaffcb..5463edea 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,35 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.ITest2", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")), + "Test1"); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1.verified.txt deleted file mode 100644 index 8bc84b5b..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test1.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (10,12)-(10,71), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test1"); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,64), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..c63587c2 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,71): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,64): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs index 78ee8b75..b3dd7236 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,35 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.ITest2", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")), + "Test2"); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2.verified.txt deleted file mode 100644 index 52074e52..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_Test2.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (10,12)-(10,71), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test2"); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,64), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..4f62c415 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI005 Error File0.cs(10,12)-(10,64): Constructor parameters must not have a circular dependency to another registered resource +SPLATDI005 Error File0.cs(11,12)-(11,64): Constructor parameters must not have a circular dependency to another registered resource diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs index 9a21d816..28f0a666 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,24 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest2' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest2"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.ITest1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.ITest1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=.verified.txt deleted file mode 100644 index fe3ca8d6..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.CircularDependencyF_contractParameter=.verified.txt +++ /dev/null @@ -1,42 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (10,12)-(10,64), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,64), - Message: Constructor parameters must not have a circular dependency to another registered resource, - Severity: Error, - Descriptor: { - Id: SPLATDI005, - Title: Constructors must not have a circular dependency, - MessageFormat: Constructor parameters must not have a circular dependency to another registered resource, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.Reg.g.verified.cs index 544e61f9..d8298679 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceImpl(), global::Test.Constants.ServiceKey); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromConstField_MyServiceKey#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.Reg.g.verified.cs index 02e4f25d..70f32c90 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::ConsoleApp.NS2.Class1(), global::ConsoleApp.NS1.Keys.Key1); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespaceWithSimpleName_Key1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.Reg.g.verified.cs index 3b41eabc..d9d7e95b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Services.ServiceImpl(), global::Test.Keys.RegistrationKeys.Key1); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromDifferentNamespace_Key1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.Reg.g.verified.cs index a634eddd..49a77a1c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.ServiceImpl(), global::Test.ContractHelper.GetContractKey()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromMethodInvocation_MethodResult#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.Reg.g.verified.cs index 0b15db2c..a162a0f9 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Services.ServiceImpl(), global::Test.Config.Settings.ContractName); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.ContractKeyFromPInDifferentNamespace_ContractName#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.Reg.g.verified.cs index ede72ea1..606829f7 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete(), "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.Reg.g.verified.cs index ec330e1b..217f32bd 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete(), "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs index 4469455e..6e9564d6 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.EConstructor_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.Reg.g.verified.cs index 2e01385c..f7487480 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Cache(), "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.Reg.g.verified.cs index 69cb7e73..b4bc0648 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Cache(), "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.Reg.g.verified.cs index 785ad4d9..53f8ba91 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Cache()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_MTypePms_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.Reg.g.verified.cs index 642aa626..306f8856 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Repository>(), "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.Reg.g.verified.cs index 6951cf34..e8d815f6 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Repository>(), "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.Reg.g.verified.cs index 5401c64f..d73ac0e9 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -26,4 +26,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.Repository>()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_NestedGeneric_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.Reg.g.verified.cs index 60359cb4..202ab628 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.AppUpdateService(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IConfig' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.AppUpdateService( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IConfig", "Test1")), + "Test1"); resolver.Register(() => new global::Test.Config(), "Test1"); } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.Reg.g.verified.cs index 7f5fcbbe..4d4736c0 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,22 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.AppUpdateService(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IConfig' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.AppUpdateService( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IConfig", "Test2")), + "Test2"); resolver.Register(() => new global::Test.Config(), "Test2"); } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.Reg.g.verified.cs index 5ed9217b..34629d29 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,9 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.AppUpdateService(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IConfig' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.AppUpdateService( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IConfig"))); resolver.Register(() => new global::Test.Config()); } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.GenericConcreteType_SingleTypePm_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..d28917bc --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(11,12)-(11,68): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(12,12)-(12,68): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.Reg.g.verified.cs index ce96d22e..938f3ef4 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,14 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetServices("Test1")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetServices("Test1")), + "Test1"); resolver.Register(() => new global::Test.ServiceA(), "Test1"); resolver.Register(() => new global::Test.ServiceB(), "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1.verified.txt deleted file mode 100644 index 5bc58fed..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test1.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.Register("Test1"); - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test1"); -*/ - : (11,12)-(11,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test1"); - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (12,12)-(12,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..d28917bc --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(11,12)-(11,68): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(12,12)-(12,68): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.Reg.g.verified.cs index 9b4a5d11..d76c6db2 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,14 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetServices("Test2")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetServices("Test2")), + "Test2"); resolver.Register(() => new global::Test.ServiceA(), "Test2"); resolver.Register(() => new global::Test.ServiceB(), "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2.verified.txt deleted file mode 100644 index 48e2aa4b..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_Test2.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.Register("Test2"); - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test2"); -*/ - : (11,12)-(11,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test2"); - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (12,12)-(12,68), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..10bfe3ee --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(11,12)-(11,61): global::Test.IService has been registered in multiple places +SPLATDI006 Warning File0.cs(12,12)-(12,61): global::Test.IService has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.Reg.g.verified.cs index 06cf9379..bb4a15d8 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,13 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetServices())); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetServices())); resolver.Register(() => new global::Test.ServiceA()); resolver.Register(() => new global::Test.ServiceB()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=.verified.txt deleted file mode 100644 index 96dcfc77..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IEnumerableDependency_contractParameter=.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - SplatRegistrations.Register(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (11,12)-(11,61), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (12,12)-(12,61), - Message: global::Test.IService has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..65f20e83 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,70): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,70): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.Reg.g.verified.cs index f4ff73ec..4821017a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.Reg.g.verified.cs @@ -28,4 +28,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete2(), "Test1"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1.verified.txt deleted file mode 100644 index d67c84cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test1.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test1"); -*/ - : (10,12)-(10,70), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test1"); - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,70), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..65f20e83 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,70): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,70): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.Reg.g.verified.cs index f877dd26..f27ec8fb 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.Reg.g.verified.cs @@ -28,4 +28,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete2(), "Test2"); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2.verified.txt deleted file mode 100644 index e2af645e..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_Test2.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test2"); -*/ - : (10,12)-(10,70), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register("Test2"); - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,70), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..20751dd2 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1,2 @@ +SPLATDI006 Warning File0.cs(10,12)-(10,63): global::Test.ITest has been registered in multiple places +SPLATDI006 Warning File0.cs(11,12)-(11,63): global::Test.ITest has been registered in multiple places diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs index 2c765a12..8d69c576 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -28,4 +28,4 @@ static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) resolver.Register(() => new global::Test.TestConcrete2()); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=.verified.txt deleted file mode 100644 index 797429fb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.IRegMx_contractParameter=.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (10,12)-(10,63), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - }, - { - Location: /* - SplatRegistrations.Register(); - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - : (11,12)-(11,63), - Message: global::Test.ITest has been registered in multiple places, - Severity: Warning, - WarningLevel: 1, - Descriptor: { - Id: SPLATDI006, - Title: Interface has been registered before, - MessageFormat: {0} has been registered in multiple places, - Category: Compiler, - DefaultSeverity: Warning, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..0bb1a144 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,69): global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.Reg.g.verified.cs index a7030ac5..ceee71ef 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService>("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService>("Test1") ?? ThrowNotRegistered>("global::System.Lazy", "Test1")), + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1.verified.txt deleted file mode 100644 index c7cc8110..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test1.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterConstant(new Service1(), "Test1"); -*/ - : (10,12)-(10,69), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..0bb1a144 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,69): global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.Reg.g.verified.cs index 878b1c19..63e552c0 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService>("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService>("Test2") ?? ThrowNotRegistered>("global::System.Lazy", "Test2")), + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2.verified.txt deleted file mode 100644 index 596cb25e..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_Test2.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterConstant(new Service1(), "Test2"); -*/ - : (10,12)-(10,69), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..63d3d581 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,62): global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs index 4f7bf4ba..123ae980 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,18 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService>() ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService>() ?? ThrowNotRegistered>("global::System.Lazy"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=.verified.txt deleted file mode 100644 index 8cca10f2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmConstantNotRegLF_contractParameter=.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.RegisterConstant(new Service1()); -*/ - : (10,12)-(10,62), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.Service1 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Diagnostics.verified.txt new file mode 100644 index 00000000..deece5e9 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,69): global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.Reg.g.verified.cs index 9b71d885..4cd5e377 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,30 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService>("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test1" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test1" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test1" + " not registered with Splat resolver.") }, "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService>("Test1") ?? ThrowNotRegistered>("global::System.Lazy", "Test1")) + { + ServiceProperty1 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test1"), + ServiceProperty2 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test1"), + ServiceProperty3 = resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test1"), + }, + "Test1"); resolver.Register(() => new global::Test.Service1(), "Test1"); resolver.Register(() => new global::Test.Service2(), "Test1"); } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1.verified.txt deleted file mode 100644 index 81b69e94..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test1.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test1"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test1"); -*/ - : (10,12)-(10,69), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Diagnostics.verified.txt new file mode 100644 index 00000000..deece5e9 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,69): global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.Reg.g.verified.cs index bba11983..bb64c6ef 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,30 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService>("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' with contract " + "Test2" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty2 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' with contract " + "Test2" + " not registered with Splat resolver."), ServiceProperty3 = resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' with contract " + "Test2" + " not registered with Splat resolver.") }, "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService>("Test2") ?? ThrowNotRegistered>("global::System.Lazy", "Test2")) + { + ServiceProperty1 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "Test2"), + ServiceProperty2 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty2", "Test2"), + ServiceProperty3 = resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IServiceProperty3", "Test2"), + }, + "Test2"); resolver.Register(() => new global::Test.Service1(), "Test2"); resolver.Register(() => new global::Test.Service2(), "Test2"); } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2.verified.txt deleted file mode 100644 index 85e21ef7..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_Test2.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register("Test2"); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register("Test2"); -*/ - : (10,12)-(10,69), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Diagnostics.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Diagnostics.verified.txt new file mode 100644 index 00000000..f1f04624 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Diagnostics.verified.txt @@ -0,0 +1 @@ +SPLATDI007 Error File0.cs(10,12)-(10,62): global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs index 638b67bc..16adcf6f 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,28 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService>() ?? throw new global::System.InvalidOperationException("Dependency 'global::System.Lazy' not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' not registered with Splat resolver."), ServiceProperty2 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty2' not registered with Splat resolver."), ServiceProperty3 = resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty3' not registered with Splat resolver.") }); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService>() ?? ThrowNotRegistered>("global::System.Lazy")) + { + ServiceProperty1 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty1"), + ServiceProperty2 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty2"), + ServiceProperty3 = resolver.GetService() ?? ThrowNotRegistered("global::Test.IServiceProperty3"), + }); resolver.Register(() => new global::Test.Service1()); resolver.Register(() => new global::Test.Service2()); } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=.verified.txt b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=.verified.txt deleted file mode 100644 index ecaab64c..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.LPmNotRegLF_contractParameter=.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -{ - Diagnostics: [ - { - Location: /* - { - SplatRegistrations.Register(); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - SplatRegistrations.Register(); -*/ - : (10,12)-(10,62), - Message: global::Test.TestConcrete constructor has a lazy parameter global::Test.IService2 which is not registered with RegisterLazySingleton, - Severity: Error, - Descriptor: { - Id: SPLATDI007, - Title: Constructor has a lazy parameter, - MessageFormat: {0} constructor has a lazy parameter {1} which is not registered with RegisterLazySingleton, - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true - } - } - ] -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorNoAttrNonDIP_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs index 0194709a..a3714e4e 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1")), + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs index 448e8953..f024376f 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,20 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2")), + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs index 9b5ec9e0..b4b5454b 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,7 +23,18 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithAttr_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs deleted file mode 100644 index 10678902..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.Reg.g.verified.cs +++ /dev/null @@ -1,27 +0,0 @@ -//HintName: Splat.DI.Reg.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This partial class contains the generated implementation of dependency registrations. - /// - internal static partial class SplatRegistrations - { - /// - /// Internal implementation of dependency injection setup. - /// This method is generated at compile-time and contains all registrations - /// defined through the source generator marker methods. - /// - /// The instance to register dependencies with. - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) - { } - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MConstructorWithMAttrsF_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs index 4c4d4173..396dd6fa 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,33 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")), + "Test1"); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")), + "Test1"); - resolver.Register(() => new global::Test.TestConcrete3(resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test1" + " not registered with Splat resolver."), resolver.GetService("Test1") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test1" + " not registered with Splat resolver.")), "Test1"); + resolver.Register( + () => new global::Test.TestConcrete3( + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService1", "Test1"), + resolver.GetService("Test1") ?? ThrowNotRegistered("global::Test.IService2", "Test1")), + "Test1"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test1#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs index cd72900d..373f667a 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,33 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")), + "Test2"); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")), + "Test2"); - resolver.Register(() => new global::Test.TestConcrete3(resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "Test2" + " not registered with Splat resolver."), resolver.GetService("Test2") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' with contract " + "Test2" + " not registered with Splat resolver.")), "Test2"); + resolver.Register( + () => new global::Test.TestConcrete3( + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService1", "Test2"), + resolver.GetService("Test2") ?? ThrowNotRegistered("global::Test.IService2", "Test2")), + "Test2"); + } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_Test2#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs index 433576f4..eb4e46ac 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,29 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete1(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete1( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); - resolver.Register(() => new global::Test.TestConcrete2(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete2( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); - resolver.Register(() => new global::Test.TestConcrete3(resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' not registered with Splat resolver."), resolver.GetService() ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService2' not registered with Splat resolver."))); + resolver.Register( + () => new global::Test.TestConcrete3( + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService1"), + resolver.GetService() ?? ThrowNotRegistered("global::Test.IService2"))); + } + + /// Throws for a dependency the resolver has no registration for. + /// The type of the dependency. + /// The name of the dependency's type. + /// Never returns. + private static T ThrowNotRegistered(string typeName) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' not registered with Splat resolver."); } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.MultiClassesRegistrations_contractParameter=#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs deleted file mode 100644 index c1d563e2..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Microsoft.CodeAnalysis.EmbeddedAttribute.g.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Microsoft.CodeAnalysis -{ - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Interface | System.AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - [System.Diagnostics.Conditional("NEVER_DEFINED")] - internal sealed class EmbeddedAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.Reg.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.Reg.g.verified.cs index 770324cf..3d8c6f4c 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.Reg.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.Reg.g.verified.cs @@ -23,11 +23,27 @@ internal static partial class SplatRegistrations /// The instance to register dependencies with. static partial void SetupIOCInternal(Splat.IDependencyResolver resolver) { - resolver.Register(() => new global::Test.TestConcrete(resolver.GetService("TestContract") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IService1' with contract " + "TestContract" + " not registered with Splat resolver.")) { ServiceProperty1 = resolver.GetService("TestContract") ?? throw new global::System.InvalidOperationException("Dependency 'global::Test.IServiceProperty1' with contract " + "TestContract" + " not registered with Splat resolver.") }, "TestContract"); + resolver.Register( + () => new global::Test.TestConcrete( + resolver.GetService("TestContract") ?? ThrowNotRegistered("global::Test.IService1", "TestContract")) + { + ServiceProperty1 = resolver.GetService("TestContract") ?? ThrowNotRegistered("global::Test.IServiceProperty1", "TestContract"), + }, + "TestContract"); resolver.Register(() => new global::Test.Service1(), "TestContract"); resolver.Register(() => new global::Test.ServiceProperty1(), "TestContract"); } + + /// Throws for a dependency the resolver has no registration for under a contract. + /// The type of the dependency. + /// The name of the dependency's type. + /// The contract the dependency was asked for under. + /// Never returns. + private static T ThrowNotRegistered(string typeName, string contract) + { + throw new global::System.InvalidOperationException("Dependency '" + typeName + "' with contract " + contract + " not registered with Splat resolver."); + } } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.g.verified.cs deleted file mode 100644 index bc15c4cb..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/R.PIWithContract_TestContract#Splat.DI.g.verified.cs +++ /dev/null @@ -1,194 +0,0 @@ -//HintName: Splat.DI.g.cs -// - -#nullable enable annotations -#nullable disable warnings - -// Suppress warnings about [Obsolete] member usage in generated code. -#pragma warning disable CS0612, CS0618 - -namespace Splat -{ - /// - /// Provides extension methods for the Splat dependency injection source generator. - /// This class contains marker methods that are analyzed at compile-time to generate - /// dependency injection registrations. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Splat.DependencyInjection.SourceGenerator", "2.0.0.0")] - internal static partial class SplatRegistrations - { - /// - /// Registers a transient dependency mapping from to . - /// A new instance of will be created each time is resolved. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void Register() - { - } - - /// - /// Registers a transient dependency mapping from to with a contract. - /// A new instance of will be created each time is resolved with the specified contract. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - public static void RegisterLazySingleton() - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a lazy singleton dependency mapping from to with a contract and specified thread safety mode. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The interface or base type to register. - /// The concrete type that implements . - /// A unique string identifier to distinguish between multiple registrations of the same type. - /// The specifying how the singleton should be initialized in multi-threaded scenarios. - public static void RegisterLazySingleton(string contract, System.Threading.LazyThreadSafetyMode mode) - { - } - - /// - /// Registers a transient dependency for type . - /// A new instance of will be created each time it is resolved. - /// - /// The type to register. - public static void Register() - { - } - - - /// - /// Registers a transient dependency for type with a contract. - /// A new instance of will be created each time it is resolved with the specified contract. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void Register(string contract) - { - } - - /// - /// Registers a lazy singleton dependency for type . - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - public static void RegisterLazySingleton() - { - } - - - /// - /// Registers a lazy singleton dependency for type with a contract. - /// A single instance of will be created on first resolution and reused for all subsequent resolutions. - /// - /// The type to register. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterLazySingleton(string contract) - { - } - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - public static void RegisterConstant(T instance) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance); - - /// - /// Registers a constant (singleton) instance of type with the dependency resolver using a contract. - /// This method is a proxy for . - /// - /// The type of the instance to register. Must be a reference type. - /// The instance to register as a constant. - /// A unique string identifier to distinguish between multiple registrations of the same type. - public static void RegisterConstant(T instance, string contract) where T : class => Splat.AppLocator.CurrentMutable.RegisterConstant(instance, contract); - - /// - /// Initializes the dependency injection container by registering all dependencies with the default . - /// This method should be called once during application startup after all registration calls have been made. - /// - public static void SetupIOC() - { - SetupIOCInternal(Splat.AppLocator.GetLocator()); - } - - /// - /// Initializes the dependency injection container by registering all dependencies with the specified resolver. - /// This method should be called once during application startup after all registration calls have been made. - /// - /// The instance to register dependencies with. - public static void SetupIOC(Splat.IDependencyResolver resolver) - { - SetupIOCInternal(resolver); - } - - - static partial void SetupIOCInternal(Splat.IDependencyResolver resolver); - } - - /// - /// Marks a property to be injected by the dependency injection engine. - /// Properties marked with this attribute will have their values automatically - /// resolved and set by the DI container during object construction. - /// - /// - /// The property must have an accessible setter (public, internal, or internal protected). - /// The property type must be registered in the DI container, or resolution will fail at runtime. - /// - [System.AttributeUsage(System.AttributeTargets.Property), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionPropertyAttribute : System.Attribute - { - } - - /// - /// Marks a constructor as the preferred constructor for dependency injection. - /// When a class has multiple constructors, this attribute specifies which constructor - /// the DI engine should use for object construction. - /// - /// - /// Only one constructor per class should be marked with this attribute. - /// If multiple constructors exist without this attribute, the analyzer will generate - /// diagnostic warning SPLATDI001. - /// The constructor must be accessible (public, internal, or internal protected). - /// - [System.AttributeUsage(System.AttributeTargets.Constructor), Microsoft.CodeAnalysis.Embedded] - internal sealed class DependencyInjectionConstructorAttribute : System.Attribute - { - } -} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterLazySingletonTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterLazySingletonTests.cs index 2da8a9d9..572a98b1 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterLazySingletonTests.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterLazySingletonTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace Splat.DependencyInjection.SourceGenerator.Tests; @@ -9,11 +9,12 @@ namespace Splat.DependencyInjection.SourceGenerator.Tests; /// Validates lazy singleton registration scenarios with different thread safety modes and injection patterns. /// [InheritsTests] -public class RegisterLazySingletonTests() : TestBase("RegisterLazySingleton") +public class RegisterLazySingletonTests : TestBase { - /// - /// Validates that lazy singleton registration works with multiple property injection and different thread safety modes. - /// + /// + protected override string TestMethod => "RegisterLazySingleton"; + + /// Validates that lazy singleton registration works with multiple property injection and different thread safety modes. /// The lazy thread safety mode to test (PublicationOnly, ExecutionAndPublication, or None). /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. @@ -29,9 +30,9 @@ public class RegisterLazySingletonTests() : TestBase("RegisterLazySingleton") [Arguments(LazyThreadSafetyMode.None, "Test2")] public Task ConstructionAndMultiplePropertyInjectionWithLazyMode(LazyThreadSafetyMode mode, string contract) { - var arguments = string.IsNullOrWhiteSpace(contract) ? - $"LazyThreadSafetyMode.{mode}" : - $"\"{contract}\", LazyThreadSafetyMode.{mode}"; + var arguments = string.IsNullOrWhiteSpace(contract) + ? $"LazyThreadSafetyMode.{mode}" + : $"\"{contract}\", LazyThreadSafetyMode.{mode}"; var source = $$""" using System; @@ -76,9 +77,7 @@ public interface IServiceProperty3 { } return TestHelper.TestPass(source, contract, mode, GetType()); } - /// - /// Validates that lazy parameter injection works when the dependency is properly registered as a lazy singleton. - /// + /// Validates that lazy parameter injection works when the dependency is properly registered as a lazy singleton. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -87,9 +86,9 @@ public interface IServiceProperty3 { } [Arguments("Test2")] public Task LazyParameterRegisteredLazy(string contract) { - var arguments = string.IsNullOrWhiteSpace(contract) ? - string.Empty : - $"\"{contract}\""; + var arguments = string.IsNullOrWhiteSpace(contract) + ? string.Empty + : $"\"{contract}\""; var source = $$""" using System; @@ -138,9 +137,7 @@ public interface IServiceProperty3 { } return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that IEnumerable{T} dependency injection works in lazy singleton constructors. - /// + /// Validates that IEnumerable{T} dependency injection works in lazy singleton constructors. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -188,14 +185,12 @@ public class ServiceB : IService { } return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that property injection with contracts works in lazy singleton registrations. - /// + /// Validates that property injection with contracts works in lazy singleton registrations. /// A task representing the asynchronous test operation. [Test] public Task PropertyInjectionWithContractInLazySingleton() { - var source = """ + const string source = """ using System; using System.Threading; using Splat; diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterTests.cs index de237f29..45772e94 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterTests.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegisterTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. namespace Splat.DependencyInjection.SourceGenerator.Tests; @@ -9,8 +9,11 @@ namespace Splat.DependencyInjection.SourceGenerator.Tests; /// Validates transient registration scenarios including constructor injection, property injection, and contract parameters. /// [InheritsTests] -public sealed class RegisterTests() : TestBase("Register") +public sealed class RegisterTests : TestBase { + /// + protected override string TestMethod => "Register"; + /// /// Validates that lazy parameter injection fails when the dependency is registered as a constant instead of lazy singleton. /// @@ -61,9 +64,7 @@ public class Service1 { } return TestHelper.TestFail(source, contract, GetType()); } - /// - /// Validates that lazy parameter injection fails when the dependency is not registered as a lazy singleton. - /// + /// Validates that lazy parameter injection fails when the dependency is not registered as a lazy singleton. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -123,9 +124,7 @@ public interface IServiceProperty3 { } return TestHelper.TestFail(source, contract, GetType()); } - /// - /// Validates that IEnumerable{T} dependency injection generates GetServices{T}() calls. - /// + /// Validates that IEnumerable{T} dependency injection generates GetServices{T}() calls. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -172,9 +171,7 @@ public class ServiceB : IService { } return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that generic concrete types with single type parameter are handled correctly. - /// + /// Validates that generic concrete types with single type parameter are handled correctly. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -218,9 +215,7 @@ public class Config : IConfig { } return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that generic concrete types with multiple type parameters are handled correctly. - /// + /// Validates that generic concrete types with multiple type parameters are handled correctly. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -260,9 +255,7 @@ public Cache() return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that nested generic types are handled correctly. - /// + /// Validates that nested generic types are handled correctly. /// The contract name parameter to test (empty, "Test1", or "Test2"). /// A task representing the asynchronous test operation. [Test] @@ -303,14 +296,12 @@ public Repository() return TestHelper.TestPass(source, contract, GetType()); } - /// - /// Validates that property injection with contracts generates correct GetService calls. - /// + /// Validates that property injection with contracts generates correct GetService calls. /// A task representing the asynchronous test operation. [Test] public Task PropertyInjectionWithContract() { - var source = """ + const string source = """ using System; using Splat; @@ -356,7 +347,7 @@ public class ServiceProperty1 : IServiceProperty1 { } [Test] public Task ContractKeyFromDifferentNamespace() { - var source = """ + const string source = """ using System; using Splat; using Test.Keys; @@ -398,7 +389,7 @@ public class ServiceImpl : IService { } [Test] public Task ContractKeyFromDifferentNamespaceWithSimpleName() { - var source = """ + const string source = """ using System; using Splat; using ConsoleApp.NS1; @@ -439,7 +430,7 @@ static Class1() [Test] public Task ContractKeyFromMethodInvocation() { - var source = """ + const string source = """ using System; using Splat; @@ -475,7 +466,7 @@ public class ServiceImpl : IService { } [Test] public Task ContractKeyFromPropertyInDifferentNamespace() { - var source = """ + const string source = """ using System; using Splat; @@ -507,14 +498,12 @@ public class ServiceImpl : IService { } return TestHelper.TestPass(source, "ContractName", GetType()); } - /// - /// Validates that contract keys using const string fields are handled correctly. - /// + /// Validates that contract keys using const string fields are handled correctly. /// A task representing the asynchronous test operation. [Test] public Task ContractKeyFromConstField() { - var source = """ + const string source = """ using System; using Splat; @@ -540,4 +529,4 @@ public class ServiceImpl : IService { } return TestHelper.TestPass(source, "MyServiceKey", GetType()); } -} \ No newline at end of file +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegistrationValidatorTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegistrationValidatorTests.cs new file mode 100644 index 00000000..5e766e2d --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RegistrationValidatorTests.cs @@ -0,0 +1,114 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// Tests the diagnostics that need the whole registration graph. +public sealed class RegistrationValidatorTests +{ + /// The line of the registration calls are written after. + private const string Marker = "// registrations"; + + /// The file the registration calls are written into, after . + private const string Template = """ + using System; + using System.Collections.Generic; + using R = Splat.SplatRegistrations; + + namespace T + { + public interface IA { } + public interface IB { } + public sealed class A : IA { } + public sealed class B : IB { } + public sealed class LazyA : IB { } + + public interface ILazyUser { } + public sealed class LazyUser : ILazyUser { public LazyUser(Lazy a) { } } + + public interface ICycle1 { } + public interface ICycle2 { } + public sealed class Cycle1 : ICycle1 { public Cycle1(ICycle2 other) { } } + public sealed class Cycle2 : ICycle2 { public Cycle2(ICycle1 other) { } } + + public interface ISelf { } + public interface ISelfAlias { } + public sealed class Self : ISelf, ISelfAlias { public Self(ISelf self) { } } + + public interface ITop { } + public interface ILeft { } + public interface IRight { } + public sealed class Top : ITop { public Top(ILeft left, IRight right) { } } + public sealed class Left : ILeft { public Left(IA a) { } } + public sealed class Right : IRight { public Right(IA a) { } } + + public interface ITwice { } + public sealed class Twice : ITwice { public Twice(IA first, IA second) { } } + + public interface IMissing { } + public sealed class NeedsMissing : IB { public NeedsMissing(IMissing missing) { } } + + public interface ICollector { } + public sealed class Collector : ICollector { public Collector(IEnumerable all) { } } + + public static class Bootstrapper + { + public static void Register() + { + // registrations + } + } + } + """; + + /// The diagnostics reported for a set of registrations, in the order they are reported. + /// The registration calls, one per line. + /// The diagnostic IDs, each with the number of the registration line it is reported at. + /// A task representing the asynchronous test. + [Test] + [Arguments("R.Register();", "")] + [Arguments("R.Register(); R.Register(\"c\");", "")] + [Arguments("R.Register();\nR.Register();", "SPLATDI006@1 SPLATDI006@2")] + [Arguments("R.RegisterLazySingleton();\nR.Register();\nR.Register();", "SPLATDI006@3 SPLATDI006@1")] + [Arguments("R.Register();\nR.Register();\nR.Register();\nR.Register();", "SPLATDI006@1 SPLATDI006@3 SPLATDI006@2 SPLATDI006@4")] + [Arguments("R.Register();", "SPLATDI007@1")] + [Arguments("R.Register();\nR.RegisterLazySingleton();", "")] + [Arguments("R.Register();\nR.RegisterLazySingleton();", "SPLATDI007@1")] + [Arguments("R.Register();\nR.RegisterLazySingleton();", "SPLATDI007@1")] + [Arguments("R.Register();\nR.Register();", "SPLATDI005@1 SPLATDI005@2")] + [Arguments("R.Register();", "SPLATDI005@1")] + [Arguments("R.Register();\nR.Register();", "SPLATDI005@1")] + [Arguments("R.Register();\nR.Register();\nR.Register();\nR.Register();", "")] + [Arguments("R.Register();\nR.Register();", "")] + [Arguments("R.Register();", "")] + [Arguments("R.Register();\nR.Register();", "")] + public async Task ReportsGraphDiagnostics(string registrations, string expected) + { + var markerAt = Template.IndexOf(Marker, StringComparison.Ordinal); + var firstLine = CountLines(Template, markerAt) + 1; + var source = Template.Insert(markerAt + Marker.Length, $"\n{registrations}"); + + var run = TestHelper.Run(source); + + await Assert.That(run.DiagnosticLines(firstLine)).IsEqualTo(expected); + } + + /// Counts the line breaks before a position. + /// The text. + /// The position. + /// The zero-based line of the position. + private static int CountLines(string text, int end) + { + var lines = 0; + for (var i = 0; i < end; i++) + { + if (text[i] == '\n') + { + lines++; + } + } + + return lines; + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RoslynHelpersTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RoslynHelpersTests.cs deleted file mode 100644 index df6da142..00000000 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/RoslynHelpersTests.cs +++ /dev/null @@ -1,1285 +0,0 @@ -// Copyright (c) 2019-2026 ReactiveUI Association Incorporated. All rights reserved. -// ReactiveUI Association Incorporated licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using TUnit.Assertions; -using TUnit.Assertions.Extensions; - -namespace Splat.DependencyInjection.SourceGenerator.Tests; - -/// -/// Tests for the RoslynHelpers class. -/// -public class RoslynHelpersTests -{ - /// - /// Verifies that IsRegisterInvocation correctly identifies Register calls. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterInvocation_IdentifiesRegisterCalls() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - using Splat; - public class Test { - public void Run() { - SplatRegistrations.Register(); - Other.Register(); - } - } - "); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - await Assert.That(invocations).Count().IsEqualTo(2); - await Assert.That(RoslynHelpers.IsRegisterInvocation(invocations[0], CancellationToken.None)).IsTrue(); - await Assert.That(RoslynHelpers.IsRegisterInvocation(invocations[1], CancellationToken.None)).IsTrue(); // Matches name "Register" - } - - /// - /// Verifies that the generator recognizes registrations imported with a static using directive. - /// - /// A task representing the asynchronous test operation. - [Test] - public async Task Generator_RecognizesStaticImportedRegistrations() - { - var source = """ - using static Splat.SplatRegistrations; - - namespace Test - { - public static class DIRegister - { - static DIRegister() - { - Register(); - RegisterLazySingleton(); - } - } - - public interface IService { } - public class Service : IService { } - public interface ILazyService { } - public class LazyService : ILazyService { } - } - """; - - var compilation = TestHelper.CreateCompilation(source); - GeneratorDriver driver = CSharpGeneratorDriver.Create( - generators: new[] { new Generator().AsSourceGenerator() }); - driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _); - - var generated = driver.GetRunResult().Results - .SelectMany(result => result.GeneratedSources) - .Single(result => result.HintName == Constants.RegistrationFileName) - .SourceText - .ToString(); - - await Assert.That(generated).Contains("resolver.Register"); - await Assert.That(generated).Contains("global::System.Lazy"); - } - - /// - /// Verifies IsRegisterInvocation returns false for non-invocation nodes. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterInvocation_NonInvocation_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText("class Test {}"); - var root = await syntaxTree.GetRootAsync(); - var node = root.DescendantNodes().OfType().First(); - - await Assert.That(RoslynHelpers.IsRegisterInvocation(node, CancellationToken.None)).IsFalse(); - } - - /// - /// Verifies that IsRegisterInvocation returns false for non-matching invocations. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterInvocation_NonMatching_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - public class Test { - public void Run() { - Other(); // Simple name - this.Other(); // Member access but wrong name - } - public void Other() {} - } - "); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - - await Assert.That(RoslynHelpers.IsRegisterInvocation(invocations[0], CancellationToken.None)).IsFalse(); - await Assert.That(RoslynHelpers.IsRegisterInvocation(invocations[1], CancellationToken.None)).IsFalse(); - } - - /// - /// Verifies that IsSplatRegistrationsMethod correctly identifies methods from SplatRegistrations. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsSplatRegistrationsMethod_IdentifiesCorrectMethods() - { - // This test requires a compilation to get symbols - var syntaxTree = CSharpSyntaxTree.ParseText(@" - namespace Splat { - public static class SplatRegistrations { - public static void Register() {} - public static void Other() {} - } - } - namespace Other { - public static class SplatRegistrations { - public static void Register() {} - } - } - "); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - var otherMethod = splatReg.GetMembers("Other").OfType().First(); - await Assert.That(RoslynHelpers.IsSplatRegistrationsMethod(registerMethod, "Register")).IsTrue(); - await Assert.That(RoslynHelpers.IsSplatRegistrationsMethod(otherMethod, "Register")).IsFalse(); - - // Test with wrong namespace but same class name - var otherNamespaceType = compilation.GetTypeByMetadataName("Other.SplatRegistrations"); - await Assert.That(otherNamespaceType).IsNotNull(); - var wrongMethod = otherNamespaceType!.GetMembers("Register").OfType().First(); - await Assert.That(RoslynHelpers.IsSplatRegistrationsMethod(wrongMethod, "Register")).IsFalse(); - } - - /// - /// Verifies that IsSplatRegistrationsMethod handles null containing type. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsSplatRegistrationsMethod_NullContainingType_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - public delegate void MyDelegate(); - "); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var delegateType = (INamedTypeSymbol)compilation.GetTypeByMetadataName("MyDelegate")!; - var invokeMethod = delegateType.DelegateInvokeMethod!; - - await Assert.That(RoslynHelpers.IsSplatRegistrationsMethod(invokeMethod, "Register")).IsFalse(); - } - - /// - /// Verifies that IsRegisterLazySingletonInvocation correctly identifies RegisterLazySingleton calls. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterLazySingletonInvocation_IdentifiesCorrectCalls() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - using Splat; - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(); - Other.RegisterLazySingleton(); - } - } - "); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - await Assert.That(invocations).Count().IsEqualTo(2); - await Assert.That(RoslynHelpers.IsRegisterLazySingletonInvocation(invocations[0], CancellationToken.None)).IsTrue(); - await Assert.That(RoslynHelpers.IsRegisterLazySingletonInvocation(invocations[1], CancellationToken.None)).IsTrue(); - } - - /// - /// Verifies IsRegisterLazySingletonInvocation returns false for non-invocation nodes. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterLazySingletonInvocation_NonInvocation_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText("class Test {}"); - var root = await syntaxTree.GetRootAsync(); - var node = root.DescendantNodes().OfType().First(); - - await Assert.That(RoslynHelpers.IsRegisterLazySingletonInvocation(node, CancellationToken.None)).IsFalse(); - } - - /// - /// Verifies that IsRegisterLazySingletonInvocation returns false for non-matching invocations. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterLazySingletonInvocation_NonMatching_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - public class Test { - public void Run() { - Other(); // Simple name - } - public void Other() {} - } - "); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - await Assert.That(RoslynHelpers.IsRegisterLazySingletonInvocation(invocation, CancellationToken.None)).IsFalse(); - } - - /// - /// Verifies that ExtractContractParameter correctly extracts the contract value. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_ExtractsValue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract = null) {} - } - } - namespace TestNamespace { - public class Constants { - public const string MyContract = "MyConstantContract"; - } - } - public class Test { - public void Run() { - SplatRegistrations.Register("LiteralContract"); - SplatRegistrations.Register(contract: "NamedLiteralContract"); - SplatRegistrations.Register(TestNamespace.Constants.MyContract); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - // 1. Literal "LiteralContract" - var literalContract = RoslynHelpers.ExtractContractParameter(registerMethod, invocations[0], semanticModel, CancellationToken.None); - await Assert.That(literalContract).IsEqualTo("\"LiteralContract\""); - - // 2. Named Literal - var namedLiteralContract = RoslynHelpers.ExtractContractParameter(registerMethod, invocations[1], semanticModel, CancellationToken.None); - await Assert.That(namedLiteralContract).IsEqualTo("\"NamedLiteralContract\""); - - // 3. Constant - should be fully qualified for use in generated code - var constantContract = RoslynHelpers.ExtractContractParameter(registerMethod, invocations[2], semanticModel, CancellationToken.None); - await Assert.That(constantContract).IsEqualTo("global::TestNamespace.Constants.MyContract"); - } - - /// - /// Verifies ExtractContractParameter returns null if parameter not found. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_NoContractParam_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register(int other) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.Register(123); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - var result = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies that ExtractLazyThreadSafetyMode correctly extracts the mode. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazyThreadSafetyMode_ExtractsValue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - using System.Threading; - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(LazyThreadSafetyMode mode) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(LazyThreadSafetyMode.ExecutionAndPublication); - SplatRegistrations.RegisterLazySingleton(mode: LazyThreadSafetyMode.None); - } - } - "); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Threading.LazyThreadSafetyMode).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var mode1 = RoslynHelpers.ExtractLazyThreadSafetyMode(registerMethod, invocations[0], semanticModel, CancellationToken.None); - await Assert.That(mode1).Contains("ExecutionAndPublication"); - - var mode2 = RoslynHelpers.ExtractLazyThreadSafetyMode(registerMethod, invocations[1], semanticModel, CancellationToken.None); - await Assert.That(mode2).Contains("None"); - } - - /// - /// Verifies that GetBaseTypesAndThis returns the inheritance chain correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetBaseTypesAndThis_ReturnsInheritanceChain() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - public class Base {} - public class Derived : Base {} - public class Leaf : Derived {} - "); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var leafType = compilation.GetTypeByMetadataName("Leaf"); - await Assert.That(leafType).IsNotNull(); - var hierarchy = RoslynHelpers.GetBaseTypesAndThis(leafType!); - - // Order is Leaf -> Derived -> Base -> Object - await Assert.That(hierarchy).Count().IsEqualTo(4); - await Assert.That(hierarchy[0].Name).IsEqualTo("Leaf"); - await Assert.That(hierarchy[1].Name).IsEqualTo("Derived"); - await Assert.That(hierarchy[2].Name).IsEqualTo("Base"); - await Assert.That(hierarchy[3].Name).IsEqualTo("Object"); - } - - /// - /// Verifies GetBaseTypesAndThis handles interfaces (BaseType is null). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetBaseTypesAndThis_Interface_ReturnsSelf() - { - var syntaxTree = CSharpSyntaxTree.ParseText("interface ITest {}"); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var type = compilation.GetTypeByMetadataName("ITest"); - await Assert.That(type).IsNotNull(); - - var result = RoslynHelpers.GetBaseTypesAndThis(type!); - - // Interface has no base class, so result should be just [ITest] - await Assert.That(result).Count().IsEqualTo(1); - await Assert.That(result[0].Name).IsEqualTo("ITest"); - } - - /// - /// Verifies that IsRegisterInvocation identifies MemberBindingExpression correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterInvocation_MemberBinding_ReturnsTrue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - public class Test { - public void Run(SplatRegistrations r) { - r?.Register(); - } - } - """); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - - await Assert.That(invocations).Count().IsGreaterThan(0); - await Assert.That(RoslynHelpers.IsRegisterInvocation(invocations[0], CancellationToken.None)).IsTrue(); - } - - /// - /// Verifies that IsRegisterLazySingletonInvocation identifies MemberBindingExpression correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsRegisterLazySingletonInvocation_MemberBinding_ReturnsTrue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - public class Test { - public void Run(SplatRegistrations r) { - r?.RegisterLazySingleton(); - } - } - """); - var root = await syntaxTree.GetRootAsync(); - var invocations = root.DescendantNodes().OfType().ToList(); - - await Assert.That(invocations).Count().IsGreaterThan(0); - await Assert.That(RoslynHelpers.IsRegisterLazySingletonInvocation(invocations[0], CancellationToken.None)).IsTrue(); - } - - /// - /// Verifies ExtractLazyThreadSafetyMode returns null when no mode parameter exists. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazyThreadSafetyMode_NoModeParam_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(int other) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(123); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var result = RoslynHelpers.ExtractLazyThreadSafetyMode(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractContractParameter handles local variable references. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_LocalVariable_ReturnsExpression() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract = null) {} - } - } - public class Test { - public void Run() { - var unknownVar = "test"; - SplatRegistrations.Register(unknownVar); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - var result = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - - // Local variable reference should be preserved - await Assert.That(result).IsEqualTo("unknownVar"); - } - - /// - /// Verifies IsSplatRegistrationsMethod returns false for extension methods. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task IsSplatRegistrationsMethod_ExtensionMethod_ReturnsFalse() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" - namespace Splat { - public static class SplatRegistrations { - public static void Register(this object obj) {} - } - } - "); - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]); - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("Register").OfType().First(); - - await Assert.That(method.IsExtensionMethod).IsTrue(); - await Assert.That(RoslynHelpers.IsSplatRegistrationsMethod(method, "Register")).IsFalse(); - } - - /// - /// Verifies GetBaseTypesAndThis returns empty array for null input. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetBaseTypesAndThis_Null_ReturnsEmpty() - { - var result = RoslynHelpers.GetBaseTypesAndThis(null!); - await Assert.That(result).IsEmpty(); - } - - /// - /// Verifies ExtractContractParameter returns null when symbol is unresolved. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_UnresolvedSymbol_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract = null) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.Register(undeclaredVar); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - var result = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies ExtractLazyThreadSafetyMode returns null when symbol is unresolved. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazyThreadSafetyMode_UnresolvedSymbol_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System.Threading; - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(LazyThreadSafetyMode mode) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(undeclaredVar); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Threading.LazyThreadSafetyMode).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var result = RoslynHelpers.ExtractLazyThreadSafetyMode(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(result).IsNull(); - } - - /// - /// Verifies GetFullyQualifiedMemberReference returns fully qualified reference for static field. - /// This is a regression test for the issue where contract keys from different namespaces - /// were not fully qualified in generated code. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMemberReference_StaticField_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace MyNamespace.Keys - { - public static class RegistrationKeys - { - public static string Key1 = "Key1"; - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var keysType = compilation.GetTypeByMetadataName("MyNamespace.Keys.RegistrationKeys"); - await Assert.That(keysType).IsNotNull(); - - var fieldSymbol = keysType!.GetMembers("Key1").OfType().First(); - var result = RoslynHelpers.GetFullyQualifiedMemberReference(fieldSymbol); - - await Assert.That(result).IsEqualTo("global::MyNamespace.Keys.RegistrationKeys.Key1"); - } - - /// - /// Verifies GetFullyQualifiedMemberReference returns fully qualified reference for static property. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMemberReference_StaticProperty_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Config - { - public static class Settings - { - public static string ConnectionString { get; } = "test"; - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var settingsType = compilation.GetTypeByMetadataName("Config.Settings"); - await Assert.That(settingsType).IsNotNull(); - - var propertySymbol = settingsType!.GetMembers("ConnectionString").OfType().First(); - var result = RoslynHelpers.GetFullyQualifiedMemberReference(propertySymbol); - - await Assert.That(result).IsEqualTo("global::Config.Settings.ConnectionString"); - } - - /// - /// Verifies GetFullyQualifiedMemberReference returns fully qualified reference for const field. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMemberReference_ConstField_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Constants - { - public static class ContractNames - { - public const string DefaultContract = "Default"; - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var constantsType = compilation.GetTypeByMetadataName("Constants.ContractNames"); - await Assert.That(constantsType).IsNotNull(); - - var fieldSymbol = constantsType!.GetMembers("DefaultContract").OfType().First(); - var result = RoslynHelpers.GetFullyQualifiedMemberReference(fieldSymbol); - - await Assert.That(result).IsEqualTo("global::Constants.ContractNames.DefaultContract"); - } - - /// - /// Verifies GetFullyQualifiedMemberReference handles nested classes correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMemberReference_NestedClass_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Outer - { - public class Container - { - public static class Inner - { - public static string Value = "test"; - } - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var innerType = compilation.GetTypeByMetadataName("Outer.Container+Inner"); - await Assert.That(innerType).IsNotNull(); - - var fieldSymbol = innerType!.GetMembers("Value").OfType().First(); - var result = RoslynHelpers.GetFullyQualifiedMemberReference(fieldSymbol); - - await Assert.That(result).IsEqualTo("global::Outer.Container.Inner.Value"); - } - - /// - /// Verifies GetFullyQualifiedMemberReference handles local variables. - /// Local variables don't have a containing type in the same way as fields/properties. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMemberReference_LocalVariable_ReturnsDisplayString() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - public class Test - { - public void Run() - { - var localVar = "test"; - System.Console.WriteLine(localVar); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Console).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - - // Find the reference to localVar in Console.WriteLine(localVar) - var identifiers = root.DescendantNodes().OfType() - .Where(id => id.Identifier.Text == "localVar") - .ToList(); - - // Get the second occurrence (the usage, not the declaration) - var localVarUsage = identifiers.Last(); - var symbolInfo = semanticModel.GetSymbolInfo(localVarUsage); - - await Assert.That(symbolInfo.Symbol).IsNotNull(); - var result = RoslynHelpers.GetFullyQualifiedMemberReference(symbolInfo.Symbol!); - - // Local variables return their simple name via ToDisplayString - await Assert.That(result).IsEqualTo("localVar"); - } - - /// - /// Verifies that ExtractContractParameter correctly extracts the contract value - /// when named arguments are provided out of the positional order. - /// This is a regression test for the bug where positional indexing broke - /// named argument resolution (e.g., RegisterLazySingleton(mode: ..., contract: "key")). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_NamedArgumentOutOfOrder_ExtractsValue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System.Threading; - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(string contract, LazyThreadSafetyMode mode) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(mode: LazyThreadSafetyMode.None, contract: "MyKey"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Threading.LazyThreadSafetyMode).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var contract = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(contract).IsEqualTo("\"MyKey\""); - } - - /// - /// Verifies that ExtractLazyThreadSafetyMode correctly extracts the mode value - /// when named arguments are provided out of the positional order. - /// This is a regression test for the bug where positional indexing broke - /// named argument resolution (e.g., RegisterLazySingleton(contract: "key", mode: ...)). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractLazyThreadSafetyMode_NamedArgumentOutOfOrder_ExtractsValue() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using System.Threading; - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(string contract, LazyThreadSafetyMode mode) {} - } - } - public class Test { - public void Run() { - SplatRegistrations.RegisterLazySingleton(mode: LazyThreadSafetyMode.None, contract: "MyKey"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) - .AddReferences(MetadataReference.CreateFromFile(typeof(System.Threading.LazyThreadSafetyMode).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var mode = RoslynHelpers.ExtractLazyThreadSafetyMode(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(mode).Contains("None"); - } - - /// - /// Verifies that ResolveParameterForArgument returns the correct parameter - /// for a positional argument (no named colon syntax). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveParameterForArgument_PositionalArgument_ReturnsCorrectParameter() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(string contract, int mode) {} - } - } - public class Test { - public void Run() { - Splat.SplatRegistrations.RegisterLazySingleton("key", 42); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - var arg0 = invocation.ArgumentList.Arguments[0]; - var param0 = RoslynHelpers.ResolveParameterForArgument(arg0, method, 0); - await Assert.That(param0).IsNotNull(); - await Assert.That(param0!.Name).IsEqualTo("contract"); - - var arg1 = invocation.ArgumentList.Arguments[1]; - var param1 = RoslynHelpers.ResolveParameterForArgument(arg1, method, 1); - await Assert.That(param1).IsNotNull(); - await Assert.That(param1!.Name).IsEqualTo("mode"); - } - - /// - /// Verifies that ResolveParameterForArgument returns the correct parameter - /// for a named argument, even when passed out of positional order. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveParameterForArgument_NamedArgumentOutOfOrder_ReturnsCorrectParameter() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void RegisterLazySingleton(string contract, int mode) {} - } - } - public class Test { - public void Run() { - Splat.SplatRegistrations.RegisterLazySingleton(mode: 42, contract: "key"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("RegisterLazySingleton").OfType().First(); - - // arg[0] is "mode: 42" but positional index 0 is "contract" — named resolution should win - var arg0 = invocation.ArgumentList.Arguments[0]; - var param0 = RoslynHelpers.ResolveParameterForArgument(arg0, method, 0); - await Assert.That(param0).IsNotNull(); - await Assert.That(param0!.Name).IsEqualTo("mode"); - - // arg[1] is "contract: \"key\"" but positional index 1 is "mode" — named resolution should win - var arg1 = invocation.ArgumentList.Arguments[1]; - var param1 = RoslynHelpers.ResolveParameterForArgument(arg1, method, 1); - await Assert.That(param1).IsNotNull(); - await Assert.That(param1!.Name).IsEqualTo("contract"); - } - - /// - /// Verifies that ResolveParameterForArgument returns null when a named argument - /// references a parameter name that does not exist on the method. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveParameterForArgument_UnknownNamedArgument_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract) {} - } - } - public class Test { - public void Run() { - Splat.SplatRegistrations.Register(nonexistent: "key"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("Register").OfType().First(); - - var arg = invocation.ArgumentList.Arguments[0]; - var param = RoslynHelpers.ResolveParameterForArgument(arg, method, 0); - await Assert.That(param).IsNull(); - } - - /// - /// Verifies that ResolveParameterForArgument returns null when the positional index - /// exceeds the number of method parameters (bounds check). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveParameterForArgument_IndexExceedsBounds_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract) {} - } - } - public class Test { - public void Run() { - Splat.SplatRegistrations.Register("key"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("Register").OfType().First(); - - // Method has 1 parameter (contract), but pass positional index 5 - var arg = invocation.ArgumentList.Arguments[0]; - var param = RoslynHelpers.ResolveParameterForArgument(arg, method, 5); - await Assert.That(param).IsNull(); - } - - /// - /// Verifies that ResolveParameterForArgument returns null when the positional index is negative. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ResolveParameterForArgument_NegativeIndex_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract) {} - } - } - public class Test { - public void Run() { - Splat.SplatRegistrations.Register("key"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var method = splatReg!.GetMembers("Register").OfType().First(); - - var arg = invocation.ArgumentList.Arguments[0]; - var param = RoslynHelpers.ResolveParameterForArgument(arg, method, -1); - await Assert.That(param).IsNull(); - } - - /// - /// Verifies that GetFullyQualifiedMethodInvocation fully qualifies a basic static method call. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMethodInvocation_BasicStaticCall_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Test { - public static class ContractHelper { - public static string GetContractKey() => "key"; - } - } - public class Usage { - public void M() { Test.ContractHelper.GetContractKey(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = RoslynHelpers.GetFullyQualifiedMethodInvocation(methodSymbol, invocation); - - await Assert.That(result).IsEqualTo("global::Test.ContractHelper.GetContractKey()"); - } - - /// - /// Verifies that GetFullyQualifiedMethodInvocation handles nested classes correctly. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMethodInvocation_NestedClass_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Ns { - public class Outer { - public static class Inner { - public static string GetKey() => "key"; - } - } - } - public class Usage { - public void M() { Ns.Outer.Inner.GetKey(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = RoslynHelpers.GetFullyQualifiedMethodInvocation(methodSymbol, invocation); - - await Assert.That(result).IsEqualTo("global::Ns.Outer.Inner.GetKey()"); - } - - /// - /// Verifies that GetFullyQualifiedMethodInvocation preserves generic type arguments on the method name. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMethodInvocation_GenericMethod_PreservesTypeArguments() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Ns { - public static class Helper { - public static string GetKey() => typeof(T).Name; - } - } - public class Usage { - public void M() { Ns.Helper.GetKey(); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = RoslynHelpers.GetFullyQualifiedMethodInvocation(methodSymbol, invocation); - - await Assert.That(result).IsEqualTo("global::Ns.Helper.GetKey()"); - } - - /// - /// Verifies that GetFullyQualifiedMethodInvocation preserves the original arguments. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task GetFullyQualifiedMethodInvocation_WithArguments_PreservesArguments() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - namespace Ns { - public static class Helper { - public static string GetKey(string arg) => arg; - } - } - public class Usage { - public void M() { Ns.Helper.GetKey("arg"); } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - var methodSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(invocation).Symbol!; - - var result = RoslynHelpers.GetFullyQualifiedMethodInvocation(methodSymbol, invocation); - - await Assert.That(result).IsEqualTo("global::Ns.Helper.GetKey(\"arg\")"); - } - - /// - /// Verifies that ExtractContractParameter fully qualifies method invocation contract keys. - /// This is a regression test for the issue where method invocation contract keys - /// were emitted unqualified in generated code. - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_MethodInvocation_ReturnsFullyQualified() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register(string contract = null) {} - } - } - namespace Test { - public static class ContractHelper { - public static string GetContractKey() => "key"; - } - } - public class Usage { - public void Run() { - SplatRegistrations.Register(Test.ContractHelper.GetContractKey()); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType() - .First(i => i.Expression.ToString().Contains("Register")); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - var result = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - - await Assert.That(result).IsEqualTo("global::Test.ContractHelper.GetContractKey()"); - } - - /// - /// Verifies that ExtractContractParameter returns null gracefully when there are - /// more arguments than method parameters (bounds check via ResolveParameterForArgument). - /// - /// A task representing the asynchronous operation. - [Test] - public async Task ExtractContractParameter_MoreArgsThanParams_ReturnsNull() - { - var syntaxTree = CSharpSyntaxTree.ParseText(""" - using Splat; - namespace Splat { - public static class SplatRegistrations { - public static void Register() {} - } - } - public class Test { - public void Run() { - SplatRegistrations.Register("extra", "args"); - } - } - """); - - var compilation = CSharpCompilation.Create("TestAssembly", [syntaxTree]) - .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); - - var semanticModel = compilation.GetSemanticModel(syntaxTree); - var root = await syntaxTree.GetRootAsync(); - var invocation = root.DescendantNodes().OfType().First(); - - var splatReg = compilation.GetTypeByMetadataName("Splat.SplatRegistrations"); - await Assert.That(splatReg).IsNotNull(); - var registerMethod = splatReg!.GetMembers("Register").OfType().First(); - - // Method has 0 parameters but invocation has 2 arguments (malformed code). - // Should not throw IndexOutOfRangeException. - var result = RoslynHelpers.ExtractContractParameter(registerMethod, invocation, semanticModel, CancellationToken.None); - await Assert.That(result).IsNull(); - } -} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Microsoft.CodeAnalysis.EmbeddedAttribute.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Microsoft.CodeAnalysis.EmbeddedAttribute.verified.cs new file mode 100644 index 00000000..0a2179b1 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Microsoft.CodeAnalysis.EmbeddedAttribute.verified.cs @@ -0,0 +1,7 @@ +//HintName: Microsoft.CodeAnalysis.EmbeddedAttribute.cs +namespace Microsoft.CodeAnalysis +{ + internal sealed partial class EmbeddedAttribute : global::System.Attribute + { + } +} \ No newline at end of file diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Splat.DI.g.verified.cs similarity index 99% rename from src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs rename to src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Splat.DI.g.verified.cs index bc15c4cb..125dec40 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/LS.CIntPITypeArgument_Test1#Splat.DI.g.verified.cs +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.WritesFixedSources#Splat.DI.g.verified.cs @@ -1,4 +1,4 @@ -//HintName: Splat.DI.g.cs +//HintName: Splat.DI.g.cs // #nullable enable annotations diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.cs b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.cs new file mode 100644 index 00000000..943a53d6 --- /dev/null +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/SnapshotTests.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2019-2026 ReactiveUI and Contributors. All rights reserved. +// ReactiveUI and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace Splat.DependencyInjection.SourceGenerator.Tests; + +/// Tests the files every project gets, and that the stored snapshots can be checked out on Windows. +public sealed class SnapshotTests +{ + /// + /// The deepest checkout root a Windows CI runner uses: D:\a\{repository}\{repository}\. A path under it must + /// stay within the Windows path limit, or the checkout and the received files fail on that runner only. + /// + private const string WindowsCheckoutRoot = @"D:\a\Splat.DI.SourceGenerator\Splat.DI.SourceGenerator\"; + + /// The longest path Windows accepts without long-path support. + private const int WindowsPathLimit = 256; + + /// The marker source and the embedded attribute are stored once, as every project gets the same files. + /// A task representing the asynchronous test. + [Test] + public Task WritesFixedSources() + { + var run = TestHelper.Run("namespace T { public static class C { public static void M() => Splat.SplatRegistrations.SetupIOC(); } }"); + + return GeneratorSnapshot.VerifyAsync(run.Driver, $"{nameof(SnapshotTests)}.{nameof(WritesFixedSources)}", includeFixedSources: true); + } + + /// Every snapshot, and the received file written beside it, fits the Windows path limit on a CI runner. + /// A task representing the asynchronous test. + [Test] + public async Task SnapshotPathsFitWindowsLimit() + { + var directory = GeneratorSnapshot.SnapshotDirectory; + var repositoryRelative = directory[(directory.LastIndexOf($"{Path.DirectorySeparatorChar}src{Path.DirectorySeparatorChar}", StringComparison.Ordinal) + 1)..]; + var tooLong = new List(); + foreach (var snapshot in Directory.EnumerateFiles(directory, "*.verified.*")) + { + var windowsPath = WindowsCheckoutRoot + Path.Combine(repositoryRelative, Path.GetFileName(snapshot)); + if (windowsPath.Length >= WindowsPathLimit) + { + tooLong.Add($"{windowsPath.Length}: {Path.GetFileName(snapshot)}"); + } + } + + await Assert.That(tooLong).IsEmpty(); + } +} diff --git a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Splat.DependencyInjection.SourceGenerator.Tests.csproj b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Splat.DependencyInjection.SourceGenerator.Tests.csproj index 090c3257..fee57832 100644 --- a/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Splat.DependencyInjection.SourceGenerator.Tests.csproj +++ b/src/tests/Splat.DependencyInjection.SourceGenerator.Tests/Splat.DependencyInjection.SourceGenerator.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 @@ -10,14 +10,26 @@ - - + + + + + + + + + + + + + +