Skip to content

Commit 989707c

Browse files
committed
Source generator tweaks and improvements.
1 parent 7d5022f commit 989707c

File tree

1 file changed

+46
-27
lines changed

1 file changed

+46
-27
lines changed

Tools/Unity.InputSystem.SourceGenerator/InterfaceTypeRegistrationGenerator.cs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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;
1011
using System.Collections.Immutable;
1112
using System.Text;
1213
using Microsoft.CodeAnalysis;
@@ -16,19 +17,28 @@
1617

1718
namespace Unity.InputSystem.SourceGenerator;
1819

19-
/// <summary>
20-
/// Syntax and symbol helpers.
21-
/// </summary>
2220
static 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;
6370
using 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

Comments
 (0)