mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
misc fixes
adds meansimplicitassignment
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
@@ -30,6 +31,10 @@ namespace Robust.Client.GameObjects.Components.UserInterface
|
||||
_interfaceData[data.UiKey] = data;
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return _interfaceData.Values.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Robust.Client.Placement
|
||||
|
||||
if (value.Components.TryGetValue("Physics", out var physicsComp)
|
||||
&& physicsComp is PhysicsComponent_AUTODATA physicsComponentAutodata
|
||||
&& physicsComponentAutodata._physShapes is { } shapes)
|
||||
&& physicsComponentAutodata._physShapes_field is { } shapes)
|
||||
{
|
||||
_colliderAABB = shapes.FirstOrDefault()?.CalculateLocalBounds(0f) ?? new Box2(0f, 0f, 0f, 0f);
|
||||
return;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Robust.Generators
|
||||
var autoDataRegistrations = allResolvedClasses.Where(IsAutoDataReg).RemoveDuplicates().ToList();
|
||||
|
||||
var customDataClassRegistrations = receiver.CustomDataClassRegistrations.Select(ResolveRegistration)
|
||||
.Where(sym => sym.GetAttribute(dataClassAttribute)?.ConstructorArguments.Length > 0)
|
||||
.Where(sym => sym.GetAttribute(dataClassAttribute)?.ConstructorArguments.Length > 0).RemoveDuplicates()
|
||||
.ToDictionary(sym => sym,
|
||||
sym => (INamedTypeSymbol) (sym.GetAttribute(dataClassAttribute).ConstructorArguments[0].Value));
|
||||
|
||||
@@ -211,12 +211,12 @@ namespace Robust.Generators
|
||||
case IFieldSymbol fieldSymbol:
|
||||
var ftypeStr = fieldSymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
fieldStr += (ftypeStr.EndsWith("?") ? ftypeStr : ftypeStr+"?" )+" ";
|
||||
fieldStr += fieldSymbol.Name+";";
|
||||
fieldStr += fieldSymbol.Name+"_field;";
|
||||
break;
|
||||
case IPropertySymbol propertySymbol:
|
||||
var ptypeStr = propertySymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
fieldStr += (ptypeStr.EndsWith("?") ? ptypeStr : ptypeStr+"?" )+" ";
|
||||
fieldStr += propertySymbol.Name+";";
|
||||
fieldStr += propertySymbol.Name+"_field;";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace Robust.Generators
|
||||
public static Diagnostic DebugDiag(string msg, Location loc = null) => Diagnostic.Create(
|
||||
new DiagnosticDescriptor("RADC9999", "", msg, "Usage", DiagnosticSeverity.Error, true), loc ?? Location.None);
|
||||
|
||||
public static SuppressionDescriptor YamlMeansImplicitUse =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Used by ComponentDataManager.");
|
||||
public static SuppressionDescriptor MeansImplicitAssignment =>
|
||||
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
|
||||
|
||||
public static DiagnosticDescriptor InvalidYamlAttrTarget = new DiagnosticDescriptor(
|
||||
"RADC0000",
|
||||
|
||||
41
Robust.Generators/MeansImplicitAssigmentSuppressor.cs
Normal file
41
Robust.Generators/MeansImplicitAssigmentSuppressor.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace Robust.Generators
|
||||
{
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public class MeansImplicitAssigmentSuppressor : DiagnosticSuppressor
|
||||
{
|
||||
const string MeansImplicitAssignmentAttribute = "Robust.Shared.MeansImplicitAssignmentAttribute";
|
||||
|
||||
public override void ReportSuppressions(SuppressionAnalysisContext context)
|
||||
{
|
||||
var implAttr = context.Compilation.GetTypeByMetadataName(MeansImplicitAssignmentAttribute);
|
||||
foreach (var reportedDiagnostic in context.ReportedDiagnostics)
|
||||
{
|
||||
if(reportedDiagnostic.Id != Diagnostics.MeansImplicitAssignment.SuppressedDiagnosticId) continue;
|
||||
|
||||
var node = reportedDiagnostic.Location.SourceTree?.GetRoot(context.CancellationToken).FindNode(reportedDiagnostic.Location.SourceSpan);
|
||||
if (node == null) continue;
|
||||
|
||||
var symbol = context.GetSemanticModel(reportedDiagnostic.Location.SourceTree).GetDeclaredSymbol(node);
|
||||
|
||||
if (symbol == null || !symbol.GetAttributes().Any(a =>
|
||||
a.AttributeClass?.GetAttributes().Any(attr =>
|
||||
SymbolEqualityComparer.Default.Equals(attr.AttributeClass, implAttr)) == true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
context.ReportSuppression(Suppression.Create(
|
||||
Diagnostics.MeansImplicitAssignment,
|
||||
reportedDiagnostic));
|
||||
}
|
||||
}
|
||||
|
||||
public override ImmutableArray<SuppressionDescriptor> SupportedSuppressions => ImmutableArray.Create(Diagnostics.MeansImplicitAssignment);
|
||||
}
|
||||
}
|
||||
@@ -644,6 +644,7 @@ namespace Robust.Server.Maps
|
||||
// See engine#636 for why the Distinct() call.
|
||||
foreach (var component in entity.GetAllComponents())
|
||||
{
|
||||
CurrentWritingComponent = component.Name;
|
||||
var compMapping = new YamlMappingNode();
|
||||
serv3Mgr.Serialize(component.GetType(), component,
|
||||
YamlObjectSerializer.NewWriter(compMapping, this));
|
||||
|
||||
6
Robust.Shared/MeansImplicitAssignmentAttribute.cs
Normal file
6
Robust.Shared/MeansImplicitAssignmentAttribute.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Robust.Shared
|
||||
{
|
||||
public class MeansImplicitAssignmentAttribute : Attribute { }
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
namespace Robust.Shared.Prototypes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
[MeansImplicitAssignment]
|
||||
public class DataClassTargetAttribute : BaseDataFieldAttribute
|
||||
{
|
||||
public DataClassTargetAttribute([NotNull] string tag, int priority = 1) : base(tag, priority)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -17,8 +18,8 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
private List<LinkEntry> _actualFields = new();
|
||||
private List<LinkEntry> _dataclassFields = new();
|
||||
|
||||
public readonly Action<object, DataClass> PopulateObjectDelegate;
|
||||
public readonly Action<object, DataClass> PopulateDataclassDelegate;
|
||||
public readonly Action<object, DataClass, ISerializationManager> PopulateObjectDelegate;
|
||||
public readonly Action<object, DataClass, ISerializationManager> PopulateDataclassDelegate;
|
||||
public readonly Func<DataClass, string, object> GetFieldDelegate;
|
||||
|
||||
public DataClassLink(Type type, Type dataClassType)
|
||||
@@ -62,7 +63,7 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
|
||||
foreach (var dataclassField in _dataclassFields)
|
||||
{
|
||||
var notIt = new Label();
|
||||
var notIt = generator.DefineLabel();
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.Emit(OpCodes.Ldstr, dataclassField.DataFieldAttribute.Tag);
|
||||
generator.Emit(OpCodes.Brfalse_S, notIt);
|
||||
@@ -80,12 +81,12 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
return dynamicMethod.CreateDelegate<Func<DataClass, string, object?>>();
|
||||
}
|
||||
|
||||
private Action<object, DataClass> EmitPopulateObjectDelegate()
|
||||
private Action<object, DataClass, ISerializationManager> EmitPopulateObjectDelegate()
|
||||
{
|
||||
var dynamicMethod = new DynamicMethod(
|
||||
$"_populateObjectFromDC<>{Type}<>{DataClassType}",
|
||||
typeof(void),
|
||||
new[] {typeof(object), typeof(DataClass), typeof(SerializationManager)},
|
||||
new[] {typeof(object), typeof(DataClass), typeof(ISerializationManager)},
|
||||
Type,
|
||||
true);
|
||||
dynamicMethod.DefineParameter(1, ParameterAttributes.In, "obj");
|
||||
@@ -109,20 +110,20 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
throw new InvalidOperationException(
|
||||
"Could not find field-counterpart while generating PopulateObjectDelegate!");
|
||||
|
||||
generator.EmitCopy(1, counterPart.FieldInfo, 0, actualField.FieldInfo, 2);
|
||||
generator.EmitCopy(1, counterPart.FieldInfo, 0, actualField.FieldInfo, 2, true);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return dynamicMethod.CreateDelegate<Action<object, DataClass>>();
|
||||
return dynamicMethod.CreateDelegate<Action<object, DataClass, ISerializationManager>>();
|
||||
}
|
||||
|
||||
private Action<object, DataClass> EmitPopulateDataclassDelegate()
|
||||
private Action<object, DataClass, ISerializationManager> EmitPopulateDataclassDelegate()
|
||||
{
|
||||
var dynamicMethod = new DynamicMethod(
|
||||
$"_populateDCFromObject<>{Type}<>{DataClassType}",
|
||||
typeof(void),
|
||||
new[] {typeof(object), typeof(DataClass), typeof(SerializationManager)},
|
||||
new[] {typeof(object), typeof(DataClass), typeof(ISerializationManager)},
|
||||
Type,
|
||||
true);
|
||||
dynamicMethod.DefineParameter(1, ParameterAttributes.In, "obj");
|
||||
@@ -151,7 +152,7 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
|
||||
generator.Emit(OpCodes.Ret);
|
||||
|
||||
return dynamicMethod.CreateDelegate<Action<object, DataClass>>();
|
||||
return dynamicMethod.CreateDelegate<Action<object, DataClass, ISerializationManager>>();
|
||||
}
|
||||
|
||||
private class LinkEntry
|
||||
@@ -162,6 +163,11 @@ namespace Robust.Shared.Prototypes.DataClasses
|
||||
public LinkEntry(AbstractFieldInfo fieldInfo, BaseDataFieldAttribute dataFieldAttribute)
|
||||
{
|
||||
FieldInfo = fieldInfo;
|
||||
if (fieldInfo is SpecificPropertyInfo propertyInfo && (propertyInfo.PropertyInfo.GetMethod == null || propertyInfo.PropertyInfo.SetMethod == null))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Property without getter or setter was annotated with YamlfieldAttribute");
|
||||
}
|
||||
DataFieldAttribute = dataFieldAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes.DataClasses;
|
||||
using Robust.Shared.Prototypes.DataClasses.Attributes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
|
||||
namespace Robust.Shared.Prototypes
|
||||
{
|
||||
@@ -13,6 +14,7 @@ namespace Robust.Shared.Prototypes
|
||||
{
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly ISerializationManager _serializationManager = default!;
|
||||
|
||||
private Dictionary<Type, DataClassLink> _dataClassLinks = new();
|
||||
|
||||
@@ -119,7 +121,7 @@ namespace Robust.Shared.Prototypes
|
||||
if (!link.DataClassType.IsInstanceOfType(dataClass))
|
||||
throw new ArgumentException("Invalid Dataclass supplied in PopulateObject!", nameof(dataClass));
|
||||
|
||||
link.PopulateObjectDelegate(obj, dataClass);
|
||||
link.PopulateObjectDelegate(obj, dataClass, _serializationManager);
|
||||
}
|
||||
|
||||
public void PopulateDataClass(object obj, DataClass dataClass)
|
||||
@@ -128,7 +130,7 @@ namespace Robust.Shared.Prototypes
|
||||
if (!link.DataClassType.IsInstanceOfType(dataClass))
|
||||
throw new ArgumentException("Invalid Dataclass supplied in PopulateObject!", nameof(dataClass));
|
||||
|
||||
link.PopulateDataclassDelegate(obj, dataClass);
|
||||
link.PopulateDataclassDelegate(obj, dataClass, _serializationManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
namespace Robust.Shared.Prototypes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
[MeansImplicitAssignment]
|
||||
public class YamlFieldAttribute : BaseDataFieldAttribute
|
||||
{
|
||||
public readonly bool ReadOnly;
|
||||
@@ -20,7 +21,7 @@ namespace Robust.Shared.Prototypes
|
||||
ConstantType = constType;
|
||||
Required = required;
|
||||
ServerOnly = serverOnly;
|
||||
if (FlagType != null && constType != null)
|
||||
if (flagType != null && constType != null)
|
||||
throw new ArgumentException("Cannot have both a flagType and a constType specified");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace Robust.Shared.Serialization.Manager
|
||||
|
||||
public bool CanCallWith(object obj) => Type.IsInstanceOfType(obj);
|
||||
|
||||
private bool GetWarningSMethod(MethodInfo m)
|
||||
{
|
||||
return m.Name == nameof(Logger.WarningS) && m.GetParameters().Length == 2;
|
||||
}
|
||||
|
||||
public SerializationDataDefinition(Type type)
|
||||
{
|
||||
Type = type;
|
||||
@@ -131,9 +136,9 @@ namespace Robust.Shared.Serialization.Manager
|
||||
|
||||
if (typeof(IExposeData).IsAssignableFrom(Type))
|
||||
{
|
||||
generator.Emit(OpCodes.Ldstr,"SERV3");
|
||||
generator.Emit(OpCodes.Ldstr, "SERV3");
|
||||
generator.Emit(OpCodes.Ldstr, $"PushInheritance is not supported for IExposeData (Type: {Type})");
|
||||
var warnMethod = typeof(Logger).GetMethod(nameof(Logger.WarningS));
|
||||
var warnMethod = typeof(Logger).GetMethods().First(GetWarningSMethod);
|
||||
Debug.Assert(warnMethod != null, nameof(warnMethod) + " != null");
|
||||
generator.Emit(OpCodes.Call, warnMethod);
|
||||
}
|
||||
@@ -163,9 +168,9 @@ namespace Robust.Shared.Serialization.Manager
|
||||
|
||||
if (typeof(IExposeData).IsAssignableFrom(Type))
|
||||
{
|
||||
generator.Emit(OpCodes.Ldstr,"SERV3");
|
||||
generator.Emit(OpCodes.Ldstr, "SERV3");
|
||||
generator.Emit(OpCodes.Ldstr, $"Copy is not supported for IExposeData (Type: {Type})");
|
||||
var warnMethod = typeof(Logger).GetMethod(nameof(Logger.WarningS));
|
||||
var warnMethod = typeof(Logger).GetMethods().First(GetWarningSMethod);
|
||||
Debug.Assert(warnMethod != null, nameof(warnMethod) + " != null");
|
||||
generator.Emit(OpCodes.Call, warnMethod);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Robust.Shared.Serialization.Manager
|
||||
generator.Emit(OpCodes.Ldloc_0);
|
||||
generator.Emit_LdInst(fieldDefinition.DefaultValue, true); //load default value
|
||||
|
||||
var isDefaultLabel = new Label();
|
||||
var isDefaultLabel = generator.DefineLabel();
|
||||
generator.EmitEquals(fieldDefinition.FieldType, isDefaultLabel); //checking if the value is default. if so, we skip setting the field
|
||||
|
||||
//setting the field
|
||||
@@ -60,7 +60,7 @@ namespace Robust.Shared.Serialization.Manager
|
||||
public static void EmitPushInheritanceField(this ILGenerator generator,
|
||||
SerializationDataDefinition.FieldDefinition fieldDefinition)
|
||||
{
|
||||
var isDefaultValue = new Label();
|
||||
var isDefaultValue = generator.DefineLabel();
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
generator.EmitLdfld(fieldDefinition.FieldInfo);
|
||||
@@ -73,10 +73,25 @@ namespace Robust.Shared.Serialization.Manager
|
||||
}
|
||||
|
||||
//TODO Paul nesting you numbnugget
|
||||
public static void EmitCopy(this ILGenerator generator, int fromArg, AbstractFieldInfo fromField, int toArg, AbstractFieldInfo toField, int mgrArg)
|
||||
public static void EmitCopy(this ILGenerator generator, int fromArg, AbstractFieldInfo fromField, int toArg,
|
||||
AbstractFieldInfo toField, int mgrArg, bool assumeNotNull = false)
|
||||
{
|
||||
if (toField.FieldType.IsAssignableFrom(fromField.FieldType))
|
||||
throw new InvalidOperationException("Mismatch of types in EmitCopy call");
|
||||
if (assumeNotNull)
|
||||
{
|
||||
var type = fromField.FieldType;
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
type = type.GenericTypeArguments.First();
|
||||
}
|
||||
if (!toField.FieldType.IsAssignableFrom(type))
|
||||
throw new InvalidOperationException("Mismatch of types in EmitCopy call");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!toField.FieldType.IsAssignableFrom(fromField.FieldType))
|
||||
throw new InvalidOperationException("Mismatch of types in EmitCopy call");
|
||||
}
|
||||
|
||||
|
||||
if (toField.FieldType.IsPrimitive)
|
||||
{
|
||||
@@ -149,8 +164,8 @@ namespace Robust.Shared.Serialization.Manager
|
||||
{
|
||||
if(fieldDefinition.Attribute.ReadOnly) return; //hehe ez pz
|
||||
|
||||
var isDefaultLabel = new Label();
|
||||
var alwaysWriteLabel = new Label();
|
||||
var isDefaultLabel = generator.DefineLabel();
|
||||
var alwaysWriteLabel = generator.DefineLabel();
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_3); //load alwaysWrite bool
|
||||
generator.Emit(OpCodes.Brtrue_S, alwaysWriteLabel); //skip defaultcheck if alwayswrite is true
|
||||
|
||||
@@ -10,6 +10,7 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
|
||||
namespace Robust.UnitTesting.Client.GameObjects.Components
|
||||
{
|
||||
@@ -56,6 +57,8 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
|
||||
MapManager.Initialize();
|
||||
MapManager.Startup();
|
||||
|
||||
IoCManager.Resolve<IDataClassManager>().Initialize();
|
||||
IoCManager.Resolve<ISerializationManager>().Initialize();
|
||||
var manager = IoCManager.Resolve<IPrototypeManager>();
|
||||
manager.LoadFromStream(new StringReader(PROTOTYPES));
|
||||
manager.Resync();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
@@ -10,6 +11,7 @@ using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Prototypes
|
||||
{
|
||||
[UsedImplicitly]
|
||||
[TestFixture]
|
||||
public class PrototypeManager_Test : RobustUnitTest
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user