feat(codegen): validate contracts and unify Unity weaving
This commit is contained in:
@@ -57,6 +57,14 @@ public static class ShrinkAssemblyWeaver
|
||||
|
||||
var module = assembly.MainModule;
|
||||
var marker = FindType(module, "ShrinkSDK.Runtime.ShrinkCodeGenWovenAttribute", "ShrinkRuntime.Abstractions");
|
||||
// Unity passes transitive reference paths even when C# emitted no direct reference.
|
||||
// All Unity postprocessors must see the same marker before another pass runs.
|
||||
if (marker == null)
|
||||
{
|
||||
var runtime = resolver.Resolve(new AssemblyNameReference("ShrinkRuntime.Abstractions", new System.Version(0, 0, 0, 0)));
|
||||
var definition = runtime?.MainModule.GetType("ShrinkSDK.Runtime.ShrinkCodeGenWovenAttribute");
|
||||
if (definition != null) marker = module.ImportReference(definition);
|
||||
}
|
||||
var existingMarker = marker == null ? null : assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == marker.FullName);
|
||||
if (existingMarker != null)
|
||||
{
|
||||
@@ -140,14 +148,13 @@ public static class ShrinkAssemblyWeaver
|
||||
if (type.Fields.Any(field => field.Name == bindingFieldName))
|
||||
throw new InvalidOperationException($"Reserved generated field already exists on {type.FullName}: {bindingFieldName}.");
|
||||
|
||||
var disposableType = module.ImportReference(typeof(IDisposable));
|
||||
var disposableType = new TypeReference("System", "IDisposable", module, module.TypeSystem.CoreLibrary);
|
||||
var bindingField = new FieldDefinition(bindingFieldName, FieldAttributes.Private, disposableType);
|
||||
type.Fields.Add(bindingField);
|
||||
var eventBusType = RequireType(module, "ShrinkEventBus.EventBus", EventRuntime);
|
||||
var attachMethod = ImportMethod(module, eventBusType,
|
||||
method => method.Name == "Attach" && method.IsStatic && method.Parameters.Count == 2);
|
||||
var disposeMethod = module.ImportReference(typeof(IDisposable).GetMethod(nameof(IDisposable.Dispose))
|
||||
?? throw new InvalidOperationException("IDisposable.Dispose was not found."));
|
||||
var disposeMethod = new MethodReference("Dispose", module.TypeSystem.Void, disposableType) { HasThis = true };
|
||||
InjectAwake(type, module, bindingField, attachMethod);
|
||||
InjectOnDestroy(type, module, bindingField, disposeMethod);
|
||||
}
|
||||
@@ -638,10 +645,14 @@ public static class ShrinkAssemblyWeaver
|
||||
{
|
||||
var opcode = Convert.ToInt32(attribute.ConstructorArguments[0].Value);
|
||||
var route = attribute.ConstructorArguments.Count > 1 ? attribute.ConstructorArguments[1].Value as string ?? string.Empty : string.Empty;
|
||||
var key = $"{opcode}:{route}";
|
||||
if (seen.TryGetValue(key, out var previous))
|
||||
throw new InvalidOperationException($"Duplicate network opcode/route {key}: {previous} and {type.FullName}.");
|
||||
seen[key] = type.FullName;
|
||||
Check("opcode:" + opcode);
|
||||
if (!string.IsNullOrWhiteSpace(route)) Check("route:" + route.Trim());
|
||||
void Check(string key)
|
||||
{
|
||||
if (seen.TryGetValue(key, out var previous))
|
||||
throw new InvalidOperationException($"SHRINK002 Duplicate {key}: {previous} and {type.FullName}. Assign unique opcodes and nonempty routes.");
|
||||
seen[key] = type.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user