fix(codegen): Adds codegen for embedded objects and timer fields (#686)

* Adds code genning for embedded objects. See `AquariumState` as an example.
* Adds code genning for fields that are `Timer`. See `Aquarium` as an example.
* Codegens aquariums
* Fixes missing option for most primitive field types.
This commit is contained in:
Kamron Batman 2021-08-16 14:48:18 -07:00 committed by GitHub
parent 4c265562bb
commit 1323162628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
126 changed files with 1287 additions and 1129 deletions

View file

@ -0,0 +1,31 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IPostDeserializeMethod.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 *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Text;
using Microsoft.CodeAnalysis;
namespace SerializableMigration
{
public interface IPostDeserializeMethod
{
public void PostDeserializeMethod(
StringBuilder source,
string indent,
SerializableProperty property,
Compilation compilation,
INamedTypeSymbol classSymbol
);
}
}

View file

@ -28,6 +28,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
);

View file

@ -29,6 +29,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -46,6 +47,7 @@ namespace SerializableMigration
0,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
@ -60,7 +62,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(ArrayMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -91,7 +93,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(ArrayMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -0,0 +1,81 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EmbeddedSerializableMigrationRule.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 *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Immutable;
using System.Text;
using Microsoft.CodeAnalysis;
using SerializationGenerator;
namespace SerializableMigration
{
public class EmbeddedSerializableMigrationRule : ISerializableMigrationRule
{
public string RuleName => nameof(EmbeddedSerializableMigrationRule);
public bool GenerateRuleState(
Compilation compilation,
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
{
if (symbol is not INamedTypeSymbol namedTypeSymbol)
{
ruleArguments = null;
return false;
}
if (!embeddedSerializableTypes.Contains(namedTypeSymbol))
{
ruleArguments = null;
return false;
}
ruleArguments = new[] { "" };
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
throw new ArgumentException($"Invalid rule applied to property {ruleName}. Expecting {expectedRule}, but received {ruleName}.");
}
var propertyName = property.Name;
source.AppendLine($"{indent}{propertyName} = new {property.Type}(this);");
source.AppendLine($"{indent}{propertyName}.Deserialize(reader);");
}
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
throw new ArgumentException($"Invalid rule applied to property {ruleName}. Expecting {expectedRule}, but received {ruleName}.");
}
var propertyName = property.Name;
source.AppendLine($"{indent}{propertyName}.Serialize(writer);");
}
}
}

View file

@ -30,6 +30,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -46,7 +47,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(EnumMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -58,7 +59,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(EnumMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -31,6 +31,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -50,6 +51,7 @@ namespace SerializableMigration
0,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
@ -71,7 +73,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(HashSetMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -114,7 +116,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(HashSetMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -30,6 +30,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -49,6 +50,7 @@ namespace SerializableMigration
0,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
@ -59,6 +61,7 @@ namespace SerializableMigration
1,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
@ -80,7 +83,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(KeyValuePairMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -134,7 +137,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(KeyValuePairMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -31,6 +31,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -50,6 +51,7 @@ namespace SerializableMigration
0,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
@ -71,7 +73,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(ListMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -115,7 +117,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(ListMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -31,6 +31,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -73,7 +74,7 @@ namespace SerializableMigration
new[] { "DeltaTime" },
SpecialType.System_String when attributes.Any(a => a.IsInternString(compilation)) =>
new[] { "InternString" },
_ => Array.Empty<string>()
_ => new[] { "" }
};
return true;
@ -81,7 +82,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(PrimitiveTypeMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -124,7 +125,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(PrimitiveTypeMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -30,6 +30,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -50,7 +51,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(PrimitiveUOTypeMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -63,7 +64,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(PrimitiveUOTypeMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -30,6 +30,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -46,7 +47,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(SerializableInterfaceMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -59,7 +60,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(SerializableInterfaceMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -30,6 +30,7 @@ namespace SerializableMigration
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
@ -53,7 +54,7 @@ namespace SerializableMigration
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(SerializationMethodSignatureMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
@ -69,7 +70,7 @@ namespace SerializableMigration
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
const string expectedRule = nameof(SerializationMethodSignatureMigrationRule);
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{

View file

@ -0,0 +1,125 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TimerMigrationRule.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 *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using SerializationGenerator;
namespace SerializableMigration
{
public class TimerMigrationRule : ISerializableMigrationRule, IPostDeserializeMethod
{
public string RuleName => nameof(TimerMigrationRule);
public bool GenerateRuleState(
Compilation compilation,
ISymbol symbol,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol,
out string[] ruleArguments
)
{
if (!(symbol is ITypeSymbol typeSymbol && typeSymbol.IsTimer(compilation)))
{
ruleArguments = null;
return false;
}
ruleArguments = attributes.Any(a => a.IsTimerDrift(compilation))
? new[] { "@TimerDrift" }
: new[] { "" };
return true;
}
public void GenerateDeserializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
throw new ArgumentException($"Invalid rule applied to property {ruleName}. Expecting {expectedRule}, but received {ruleName}.");
}
var propertyName = property.Name;
var ruleArguments = property.RuleArguments;
var driftTimer = ruleArguments[0].Contains("@TimerDrift");
var readTimer = driftTimer ? "reader.ReadDeltaTime()" : "reader.ReadDateTime()";
source.AppendLine($"{indent}var {propertyName}Delay = {readTimer} - Core.Now;");
}
public void GenerateSerializationMethod(StringBuilder source, string indent, SerializableProperty property)
{
var expectedRule = RuleName;
var ruleName = property.Rule;
if (expectedRule != ruleName)
{
throw new ArgumentException($"Invalid rule applied to property {ruleName}. Expecting {expectedRule}, but received {ruleName}.");
}
var propertyName = property.Name;
var ruleArguments = property.RuleArguments;
var driftTimer = ruleArguments[0].Contains("@TimerDrift");
var writerMethod = driftTimer ? "WriteDeltaTime" : "Write";
source.AppendLine($"{indent}writer.{writerMethod}({propertyName}.Next);");
}
public void PostDeserializeMethod(
StringBuilder source, string indent, SerializableProperty property, Compilation compilation, INamedTypeSymbol classSymbol
)
{
var deserializeTimerMethod = classSymbol
.GetMembers()
.OfType<IMethodSymbol>()
.FirstOrDefault(
m =>
{
if (!m.ReturnsVoid || m.Parameters.Length != 1 || !m.Parameters[0].Type.IsTimeSpan(compilation))
{
return false;
}
return m.GetAttributes()
.FirstOrDefault(
attr =>
{
if (!SymbolEqualityComparer.Default.Equals(
attr.AttributeClass,
compilation.GetTypeByMetadataName(
SymbolMetadata.DESERIALIZE_TIMER_FIELD_ATTRIBUTE
)
))
{
return false;
}
var order = (int)attr.ConstructorArguments[0].Value!;
return order == property.Order;
}
) != null;
}
) ?? throw new Exception("Serializing a timer requires a method with the DeserializeTimerField attribute to handle creating the timer itself.");
source.AppendLine($"{indent}{deserializeTimerMethod.Name}({property.Name}Delay);");
}
}
}

View file

@ -38,6 +38,8 @@ namespace SerializableMigration
new PrimitiveUOTypeMigrationRule(),
new SerializableInterfaceMigrationRule(),
new SerializationMethodSignatureMigrationRule(),
new EmbeddedSerializableMigrationRule(),
new TimerMigrationRule()
};
foreach (var rule in rules)
@ -52,6 +54,7 @@ namespace SerializableMigration
int order,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol = default
)
{
@ -80,6 +83,7 @@ namespace SerializableMigration
order,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol
);
}
@ -91,6 +95,7 @@ namespace SerializableMigration
int order,
ImmutableArray<AttributeData> attributes,
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes,
ISymbol? parentSymbol = default
)
{
@ -101,6 +106,7 @@ namespace SerializableMigration
propertyType,
attributes,
serializableTypes,
embeddedSerializableTypes,
parentSymbol,
out var ruleArguments
))