@@ -78,7 +78,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7878 } ) ;
7979
8080 // Gather all interfaces, and only enable this branch if the target is a UWP app (the host)
81- IncrementalValuesProvider < ( HierarchyInfo Hierarchy , AppServiceInfo Info ) > appServiceHostInfo =
81+ IncrementalValuesProvider < ( HierarchyInfo , AppServiceInfo ) > appServiceHostInfo =
8282 context . ForAttributeWithMetadataNameAndOptions (
8383 "CommunityToolkit.AppServices.AppServiceAttribute" ,
8484 static ( node , _ ) => node is InterfaceDeclarationSyntax ,
@@ -105,6 +105,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
105105
106106 token . ThrowIfCancellationRequested ( ) ;
107107
108+ // Gather all methods for the app service type
108109 ImmutableArray < MethodInfo > methods = MethodInfo . From ( typeSymbol , token ) ;
109110
110111 token . ThrowIfCancellationRequested ( ) ;
@@ -113,8 +114,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
113114 } )
114115 . Where ( static item => item . Hierarchy is not null ) ;
115116
116- // Produce the host type
117- context . RegisterSourceOutput ( appServiceHostInfo , static ( context , item ) =>
117+ // Also gather all explicitly requested host implementation types
118+ IncrementalValuesProvider < ( HierarchyInfo , AppServiceInfo ) > additionalAppServiceHostInfo =
119+ context . ForAttributeWithMetadataNameAndOptions (
120+ "CommunityToolkit.AppServices.GeneratedAppServiceHostAttribute" ,
121+ static ( node , _ ) => true ,
122+ static ( context , token ) =>
123+ {
124+ // Only retrieve host info if the target is a UWP application
125+ if ( ! Helpers . IsUwpTarget ( context . SemanticModel . Compilation , context . GlobalOptions ) )
126+ {
127+ return default ;
128+ }
129+
130+ // Get the target interface
131+ if ( context . Attributes [ 0 ] . ConstructorArguments is not [ { Kind : TypedConstantKind . Type , Value : INamedTypeSymbol appServiceType } ] )
132+ {
133+ return default ;
134+ }
135+
136+ // Check if the current interface is in fact an app service type
137+ if ( ! appServiceType . TryGetAppServicesNameFromAttribute ( out string ? appServiceName ) )
138+ {
139+ return default ;
140+ }
141+
142+ token . ThrowIfCancellationRequested ( ) ;
143+
144+ HierarchyInfo hierarchy = HierarchyInfo . From ( appServiceType , appServiceType . Name . Substring ( 1 ) ) ;
145+
146+ token . ThrowIfCancellationRequested ( ) ;
147+
148+ ImmutableArray < MethodInfo > methods = MethodInfo . From ( appServiceType , token ) ;
149+
150+ token . ThrowIfCancellationRequested ( ) ;
151+
152+ return ( Hierarchy : hierarchy , new AppServiceInfo ( methods , appServiceName , appServiceType . GetFullyQualifiedName ( ) ) ) ;
153+ } )
154+ . Where ( static item => item . Hierarchy is not null ) ;
155+
156+ // Shared helper to emit all discovered types
157+ static void GenerateAppServiceHostType ( SourceProductionContext context , ( HierarchyInfo Hierarchy , AppServiceInfo Info ) item )
118158 {
119159 ConstructorDeclarationSyntax constructorSyntax = Host . GetConstructorSyntax ( item . Hierarchy , item . Info ) ;
120160 ImmutableArray < MethodDeclarationSyntax > methodDeclarations = Host . GetMethodDeclarationsSyntax ( item . Info ) ;
@@ -126,6 +166,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
126166 $ "/// <summary>A generated host implementation for the <see cref=\" { item . Info . InterfaceFullyQualifiedName } \" /> interface.</summary>") ;
127167
128168 context . AddSource ( $ "{ item . Hierarchy . FilenameHint } .g.cs", compilationUnit . GetText ( Encoding . UTF8 ) ) ;
129- } ) ;
169+ }
170+
171+ // Produce the host types
172+ context . RegisterSourceOutput ( appServiceHostInfo , GenerateAppServiceHostType ) ;
173+ context . RegisterSourceOutput ( additionalAppServiceHostInfo , GenerateAppServiceHostType ) ;
130174 }
131175}
0 commit comments