77// - Generate diagnostic warnings for types implementing interfaces with private visibility?
88// - Improve generated type name generation to guarantee no clash.
99
10+ using System . Collections . Generic ;
1011using System . Collections . Immutable ;
1112using System . Text ;
1213using Microsoft . CodeAnalysis ;
1617
1718namespace Unity . InputSystem . SourceGenerator ;
1819
19- /// <summary>
20- /// Syntax and symbol helpers.
21- /// </summary>
2220static class Helpers
2321{
22+ private static readonly HashSet < string > ExcludedAssemblies =
23+ [
24+ "Unity.InputSystem"
25+ ] ;
26+
27+ public static bool IsAcceptedAssembly ( INamedTypeSymbol symbol )
28+ {
29+ return ! ExcludedAssemblies . Contains ( symbol . ContainingAssembly . Identity . Name ) ;
30+ }
31+
2432 public static bool IsEffectivelyPublic ( INamedTypeSymbol type )
2533 {
2634 // The type itself must be public
2735 if ( type . DeclaredAccessibility != Accessibility . Public )
2836 return false ;
2937
3038 // Every containing type must also be public
31- for ( var container = type . ContainingType ; container is not null ; container = container . ContainingType )
39+ for ( var container = type . ContainingType ;
40+ container is not null ;
41+ container = container . ContainingType )
3242 {
3343 if ( container . DeclaredAccessibility != Accessibility . Public )
3444 return false ;
@@ -40,9 +50,6 @@ public static bool IsEffectivelyPublic(INamedTypeSymbol type)
4050 public static bool ImplementsInterface ( INamedTypeSymbol type , INamedTypeSymbol interfaceSymbol )
4151 => type . AllInterfaces . Contains ( interfaceSymbol ) ;
4252
43- public static bool ExtendsClass ( INamedTypeSymbol type , INamedTypeSymbol baseSymbol )
44- => SymbolEqualityComparer . Default . Equals ( type , baseSymbol ) ;
45-
4653 public static bool IsOrInheritsFrom ( INamedTypeSymbol type , INamedTypeSymbol baseSymbol )
4754 {
4855 // If you *don't* want to match A itself, start from type.BaseType instead.
@@ -57,7 +64,7 @@ public static bool IsOrInheritsFrom(INamedTypeSymbol type, INamedTypeSymbol base
5764}
5865
5966[ Generator ]
60- public class InterfaceTypeRegistrationGenerator : IIncrementalGenerator
67+ public class TypeRegistrationGenerator : IIncrementalGenerator
6168{
6269 internal const string RegistrationTemplateBegin = @"using System;
6370using UnityEngine;
@@ -72,10 +79,10 @@ class @C
7279 static @C() { Register(); }
7380#endif
7481
75- [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad )]
82+ [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen )]
7683 static void Register()
7784 {
78- Debug.Log(""Auto-registering @T via source generated type @C"");" ;
85+ Debug.Log(""Registering @T (@A) via generated type @C"");" ;
7986
8087 internal const string RegistrationTemplateEnd = @"
8188 }
@@ -86,7 +93,7 @@ static void Register()
8693 private readonly string _template ;
8794 private readonly System . Func < INamedTypeSymbol , INamedTypeSymbol , bool > _accept ;
8895
89- protected InterfaceTypeRegistrationGenerator ( string @interface , string template ,
96+ protected TypeRegistrationGenerator ( string @interface , string template ,
9097 System . Func < INamedTypeSymbol , INamedTypeSymbol , bool > accept )
9198 {
9299 _interface = @interface ;
@@ -134,30 +141,27 @@ private static void Process(SourceProductionContext context, Compilation compila
134141 continue ;
135142
136143 // Generate type registration code and add to source
137- var source = GenerateFor ( typeSymbol , template ) ;
144+ var fullyQualifiedTypeName = typeSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
145+ var source = template . Replace ( "@C" , typeSymbol . Name + "Registration" )
146+ . Replace ( "@T" , fullyQualifiedTypeName )
147+ . Replace ( "@A" , typeSymbol . ContainingAssembly . Identity . Name ) ;
148+
149+ // Finally, add source to compilation context
138150 context . AddSource ( $ "{ typeSymbol . Name } _Generated.g.cs", SourceText . From ( source , Encoding . UTF8 ) ) ;
139151 }
140152 }
141-
142-
143-
144- private static string GenerateFor ( INamedTypeSymbol type , string template )
145- {
146- var fullyQualifiedTypeName = type . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
147- return template . Replace ( "@C" , type . Name + "Registration" ) . Replace ( "@T" , fullyQualifiedTypeName ) ;
148- }
149153}
150154
151155/// <summary>
152- /// Source generator that registers public types implementing IInputProcessor .
156+ /// Source generator that registers public types extending InputProcessor .
153157/// </summary>
154158[ Generator ]
155- public sealed class ProcessorRegistration ( ) : InterfaceTypeRegistrationGenerator ( Base , Template ,
156- static ( symbol , baseSymbol ) => Helpers . IsEffectivelyPublic ( symbol ) &&
159+ public sealed class InputProcessorRegistration ( ) : TypeRegistrationGenerator ( Base , Template ,
160+ static ( symbol , baseSymbol ) => Helpers . IsAcceptedAssembly ( symbol ) &&
161+ Helpers . IsEffectivelyPublic ( symbol ) &&
157162 Helpers . IsOrInheritsFrom ( symbol , baseSymbol ) )
158163{
159164 private const string Base = "UnityEngine.InputSystem.InputProcessor" ;
160-
161165 private const string Template = RegistrationTemplateBegin +
162166 " InputSystem.RegisterProcessor(typeof(@T));" +
163167 RegistrationTemplateEnd ;
@@ -167,13 +171,28 @@ public sealed class ProcessorRegistration() : InterfaceTypeRegistrationGenerator
167171/// Source generator that registers public types implementing IInputInteraction.
168172/// </summary>
169173[ Generator ]
170- public sealed class InteractionRegistration ( ) : InterfaceTypeRegistrationGenerator ( Interface , Template ,
171- static ( symbol , @interface ) => Helpers . IsEffectivelyPublic ( symbol ) &&
174+ public sealed class InputInteractionRegistration ( ) : TypeRegistrationGenerator ( Interface , Template ,
175+ static ( symbol , @interface ) => Helpers . IsAcceptedAssembly ( symbol ) &&
176+ Helpers . IsEffectivelyPublic ( symbol ) &&
172177 Helpers . ImplementsInterface ( symbol , @interface ) )
173178{
174179 private const string Interface = "UnityEngine.InputSystem.IInputInteraction" ;
175-
176180 private const string Template = RegistrationTemplateBegin +
177181 " InputSystem.RegisterInteraction(typeof(@T));" +
178182 RegistrationTemplateEnd ;
179183}
184+
185+ /// <summary>
186+ /// Source generator that registers public types derived from InputBindingComposite.
187+ /// </summary>
188+ [ Generator ]
189+ public sealed class InputBindingCompositeRegistration ( ) : TypeRegistrationGenerator ( Base , Template ,
190+ static ( symbol , baseSymbol ) => Helpers . IsAcceptedAssembly ( symbol ) &&
191+ Helpers . IsEffectivelyPublic ( symbol ) &&
192+ Helpers . IsOrInheritsFrom ( symbol , baseSymbol ) )
193+ {
194+ private const string Base = "UnityEngine.InputSystem.InputBindingComposite" ;
195+ private const string Template = RegistrationTemplateBegin +
196+ " InputSystem.RegisterBindingComposite(typeof(@T), null);" +
197+ RegistrationTemplateEnd ;
198+ }
0 commit comments