using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace Unity.VisualScripting
{
[AotStubWriter(typeof(FieldInfo))]
public class FieldInfoStubWriter : AccessorInfoStubWriter<FieldInfo>
{
public FieldInfoStubWriter(FieldInfo fieldInfo) : base(fieldInfo) { }
protected override IOptimizedAccessor GetOptimizedAccessor(FieldInfo fieldInfo)
{
return fieldInfo.Prewarm();
}
public override IEnumerable<CodeStatement> GetStubStatements()
{
if (stub.IsPublic && stub.IsLiteral && !stub.IsInitOnly && stub.DeclaringType != null)
{
if (manipulator.isPubliclyGettable)
{
var targetType = new CodeTypeReference(manipulator.targetType, CodeTypeReferenceOptions.GlobalReference);
var accessorType = new CodeTypeReference(manipulator.type, CodeTypeReferenceOptions.GlobalReference);
var property = new CodeTypeReferenceExpression(targetType);
var propertyReference = new CodePropertyReferenceExpression(property, manipulator.name);
yield return new CodeVariableDeclarationStatement(accessorType, "accessor", propertyReference);
}
const string variableName = "optimized";
var optimizedAccessorType = new CodeTypeReference(
GetOptimizedAccessor(stub).GetType(), CodeTypeReferenceOptions.GlobalReference);
yield return new CodeVariableDeclarationStatement(optimizedAccessorType,
variableName,
new CodeObjectCreateExpression(optimizedAccessorType,
new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(
new CodeTypeOfExpression(
new CodeTypeReference(stub.DeclaringType, CodeTypeReferenceOptions.GlobalReference)),
nameof(Type.GetField)),
new CodePrimitiveExpression(stub.Name),
new CodeSnippetExpression("System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static"))));
if (manipulator.isGettable)
{
var target = new CodePrimitiveExpression(null);
yield return new CodeExpressionStatement(
new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(variableName),
nameof(IOptimizedAccessor.GetValue),
target));
}
yield break;
}
foreach (var statement in base.GetStubStatements())
yield return statement;
}
// RuntimeAccessModifiersILPP makes NetworkManager.__rpc_func_table and NetworkManager.__rpc_name_table public
// which causes a problem when AotStubs are generated as it leads to a compilation error. There is no way to
// identify that those fields have changed their accessors so we just deny those APIs.
/// <summary>
/// Don't use this field. It is for Unity Visual Scripting internal usage only.
/// </summary>
public override bool skip =>
stub.ReflectedType is { Name: "NetworkManager", Namespace: "Unity.Netcode" }
&& stub.Name is "__rpc_func_table" or "__rpc_name_table";
}
}