misc fixes

adds meansimplicitassignment
This commit is contained in:
Paul
2021-02-11 09:15:05 +01:00
parent 5844fad620
commit 4a6e1fdb97
15 changed files with 118 additions and 30 deletions

View File

@@ -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!;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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",

View 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);
}
}

View File

@@ -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));

View File

@@ -0,0 +1,6 @@
using System;
namespace Robust.Shared
{
public class MeansImplicitAssignmentAttribute : Attribute { }
}

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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");
}
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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
{