fix(codegen): Fixes various code gen issues. Adds better embedded serialization support (#688)

* Adds save flag support (see `ElvenGlasses` for an example)
* Updates AOSAttributes so they are code genned
* Fixes embedded object support by adding an `IRawSerializable`
* Fixes various inconsistencies in serializing with codegen
This commit is contained in:
Kamron Batman 2021-08-17 02:43:52 -07:00 committed by GitHub
parent 69af652a18
commit 2c8097f707
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 787 additions and 507 deletions

View file

@ -36,7 +36,8 @@ namespace SerializableMigration
void GenerateDeserializationMethod(
StringBuilder source,
string indent,
SerializableProperty property
SerializableProperty property,
string? parentReference
);
void GenerateSerializationMethod(

View file

@ -48,7 +48,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
null
);
var length = serializableArrayType.RuleArguments.Length;
@ -60,7 +61,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
@ -74,7 +75,7 @@ namespace SerializableMigration
Array.Copy(ruleArguments, 2, arrayElementRuleArguments, 0, ruleArguments.Length - 2);
var propertyIndex = $"{property.Name}Index";
source.AppendLine($"{indent}{property.Name} = new {ruleArguments[0]}[reader.ReadInt()];");
source.AppendLine($"{indent}{property.Name} = new {ruleArguments[0]}[reader.ReadEncodedInt()];");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {property.Name}.Length; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
@ -86,7 +87,7 @@ namespace SerializableMigration
RuleArguments = arrayElementRuleArguments
};
arrayElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableArrayElement);
arrayElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableArrayElement, parentReference);
source.AppendLine($"{indent}}}");
}
@ -110,7 +111,7 @@ namespace SerializableMigration
var propertyIndex = $"{propertyVarPrefix}Index";
var propertyLength = $"{propertyVarPrefix}Length";
source.AppendLine($"{indent}var {propertyLength} = {property.Name}?.Length ?? 0;");
source.AppendLine($"{indent}writer.Write({propertyLength});");
source.AppendLine($"{indent}writer.WriteEncodedInt({propertyLength});");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {propertyLength}; {propertyIndex}++)");
source.AppendLine($"{indent}{{");

View file

@ -45,7 +45,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -52,7 +52,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
null
);
var extraOptions = "";
@ -71,7 +72,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
@ -95,7 +96,7 @@ namespace SerializableMigration
var propertyCount = $"{propertyVarPrefix}Count";
source.AppendLine($"{indent}{ruleArguments[argumentsOffset]} {propertyEntry};");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadInt();");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadEncodedInt();");
source.AppendLine($"{indent}{property.Name} = new System.Collections.Generic.HashSet<{ruleArguments[argumentsOffset]}>({propertyCount});");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; i < {propertyCount}; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
@ -108,7 +109,7 @@ namespace SerializableMigration
RuleArguments = setElementRuleArguments
};
setElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableSetElement);
setElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableSetElement, parentReference);
source.AppendLine($"{indent} {property.Name}.Add({propertyEntry});");
source.AppendLine($"{indent}}}");
@ -142,7 +143,7 @@ namespace SerializableMigration
source.AppendLine($"{indent}{property.Name}?.Tidy();");
}
source.AppendLine($"{indent}var {propertyCount} = {property.Name}?.Count ?? 0;");
source.AppendLine($"{indent}writer.Write({propertyCount});");
source.AppendLine($"{indent}writer.WriteEncodedInt({propertyCount});");
source.AppendLine($"{indent}if ({propertyCount} > 0)");
source.AppendLine($"{indent}{{");
source.AppendLine($"{indent} foreach (var {propertyEntry} in {property.Name}!)");

View file

@ -51,7 +51,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
null
);
var valueSerializedProperty = SerializableMigrationRulesEngine.GenerateSerializableProperty(
@ -62,7 +63,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
null
);
// Key
@ -81,7 +83,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
@ -107,7 +109,8 @@ namespace SerializableMigration
keyRule.GenerateDeserializationMethod(
source,
indent,
serializableKeyProperty
serializableKeyProperty,
parentReference
);
var valueIndex = 3 + keyRuleArguments.Length;
@ -127,7 +130,8 @@ namespace SerializableMigration
keyRule.GenerateDeserializationMethod(
source,
indent,
serializableValueProperty
serializableValueProperty,
parentReference
);
source.AppendLine(

View file

@ -52,7 +52,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
null
);
var extraOptions = "";
@ -71,7 +72,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
@ -96,7 +97,7 @@ namespace SerializableMigration
var propertyCount = $"{propertyVarPrefix}Count";
source.AppendLine($"{indent}{ruleArguments[argumentsOffset]} {propertyEntry};");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadInt();");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadEncodedInt();");
source.AppendLine($"{indent}{propertyName} = new System.Collections.Generic.List<{ruleArguments[argumentsOffset]}>({propertyCount});");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {propertyCount}; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
@ -109,7 +110,7 @@ namespace SerializableMigration
RuleArguments = listElementRuleArguments
};
listElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableListElement);
listElementRule.GenerateDeserializationMethod(source, $"{indent} ", serializableListElement, parentReference);
source.AppendLine($"{indent} {propertyName}.Add({propertyEntry});");
source.AppendLine($"{indent}}}");
@ -143,7 +144,7 @@ namespace SerializableMigration
source.AppendLine($"{indent}{property.Name}?.Tidy();");
}
source.AppendLine($"{indent}var {propertyCount} = {property.Name}?.Count ?? 0;");
source.AppendLine($"{indent}writer.Write({propertyCount});");
source.AppendLine($"{indent}writer.WriteEncodedInt({propertyCount});");
source.AppendLine($"{indent}if ({propertyCount} > 0)");
source.AppendLine($"{indent}{{");
source.AppendLine($"{indent} foreach (var {propertyEntry} in {property.Name}!)");

View file

@ -80,7 +80,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -49,7 +49,7 @@ namespace SerializableMigration
return ruleArguments != null;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -2,7 +2,7 @@
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EmbeddedSerializableMigrationRule.cs *
* File: RawSerializableMigrationRule.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@ -21,9 +21,9 @@ using SerializationGenerator;
namespace SerializableMigration
{
public class EmbeddedSerializableMigrationRule : ISerializableMigrationRule
public class RawSerializableMigrationRule : ISerializableMigrationRule
{
public string RuleName => nameof(EmbeddedSerializableMigrationRule);
public string RuleName => nameof(RawSerializableMigrationRule);
public bool GenerateRuleState(
Compilation compilation,
@ -35,13 +35,13 @@ namespace SerializableMigration
out string[] ruleArguments
)
{
if (symbol is not INamedTypeSymbol namedTypeSymbol)
if (symbol is not ITypeSymbol typeSymbol)
{
ruleArguments = null;
return false;
}
if (!embeddedSerializableTypes.Contains(namedTypeSymbol))
if (!typeSymbol.HasRawSerializableInterface(compilation, embeddedSerializableTypes))
{
ruleArguments = null;
return false;
@ -51,7 +51,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
@ -61,7 +61,7 @@ namespace SerializableMigration
}
var propertyName = property.Name;
source.AppendLine($"{indent}{propertyName} = new {property.Type}(this);");
source.AppendLine($"{indent}{propertyName} = new {property.Type}({parentReference ?? "this"});");
source.AppendLine($"{indent}{propertyName}.Deserialize(reader);");
}

View file

@ -45,7 +45,7 @@ namespace SerializableMigration
return false;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -52,7 +52,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -49,7 +49,7 @@ namespace SerializableMigration
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property, string? parentReference)
{
var expectedRule = RuleName;
var ruleName = property.Rule;

View file

@ -0,0 +1,31 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
namespace SerializableMigration
{
public class SerializableFieldFlagComparer : IComparer<(IMethodSymbol, int)>
{
public int Compare((IMethodSymbol, int) x, (IMethodSymbol, int) y)
{
var (methodSymbolX, orderX) = x;
var (methodSymbolY, orderY) = y;
if (ReferenceEquals(methodSymbolX, methodSymbolY))
{
return 0;
}
if (ReferenceEquals(null, methodSymbolY))
{
return 1;
}
if (ReferenceEquals(null, methodSymbolX))
{
return -1;
}
return orderX.CompareTo(orderY);
}
}
}

View file

@ -38,7 +38,7 @@ namespace SerializableMigration
new PrimitiveUOTypeMigrationRule(),
new SerializableInterfaceMigrationRule(),
new SerializationMethodSignatureMigrationRule(),
new EmbeddedSerializableMigrationRule(),
new RawSerializableMigrationRule(),
new TimerMigrationRule()
};
@ -55,7 +55,8 @@ namespace SerializableMigration
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol = default
ISymbol? parentSymbol,
IMethodSymbol? serializablePropertyFlagGetter
)
{
string propertyName;
@ -84,7 +85,8 @@ namespace SerializableMigration
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
parentSymbol,
serializablePropertyFlagGetter
);
}
@ -96,7 +98,8 @@ namespace SerializableMigration
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol = default
ISymbol? parentSymbol,
IMethodSymbol? serializablePropertyFlagGetter
)
{
foreach (var rule in Rules.Values)
@ -116,6 +119,7 @@ namespace SerializableMigration
Name = propertyName,
Type = propertyType.ToDisplayString(),
Order = order,
UsesSaveFlag = serializablePropertyFlagGetter != null ? true : null,
Rule = rule.RuleName,
RuleArguments = ruleArguments
};

View file

@ -25,6 +25,9 @@ namespace SerializableMigration
[JsonPropertyName("type")]
public string Type { get; init; }
[JsonPropertyName("usesSaveFlag")]
public bool? UsesSaveFlag { get; init; }
[JsonPropertyName("rule")]
public string Rule { get; init; }