@@ -78,7 +78,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
78
78
} ) ;
79
79
80
80
// 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 =
82
82
context . ForAttributeWithMetadataNameAndOptions (
83
83
"CommunityToolkit.AppServices.AppServiceAttribute" ,
84
84
static ( node , _ ) => node is InterfaceDeclarationSyntax ,
@@ -105,6 +105,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
105
105
106
106
token . ThrowIfCancellationRequested ( ) ;
107
107
108
+ // Gather all methods for the app service type
108
109
ImmutableArray < MethodInfo > methods = MethodInfo . From ( typeSymbol , token ) ;
109
110
110
111
token . ThrowIfCancellationRequested ( ) ;
@@ -113,8 +114,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
113
114
} )
114
115
. Where ( static item => item . Hierarchy is not null ) ;
115
116
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 )
118
158
{
119
159
ConstructorDeclarationSyntax constructorSyntax = Host . GetConstructorSyntax ( item . Hierarchy , item . Info ) ;
120
160
ImmutableArray < MethodDeclarationSyntax > methodDeclarations = Host . GetMethodDeclarationsSyntax ( item . Info ) ;
@@ -126,6 +166,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
126
166
$ "/// <summary>A generated host implementation for the <see cref=\" { item . Info . InterfaceFullyQualifiedName } \" /> interface.</summary>") ;
127
167
128
168
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 ) ;
130
174
}
131
175
}
0 commit comments