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

@ -30,9 +30,11 @@ namespace SerializationGenerator
this GeneratorExecutionContext context,
INamedTypeSymbol classSymbol,
AttributeData serializableAttr,
bool embedded,
ImmutableArray<ISymbol> fieldsAndProperties,
JsonSerializerOptions jsonSerializerOptions,
ImmutableArray<INamedTypeSymbol> serializableTypes
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes
)
{
var version = (int)serializableAttr.ConstructorArguments[0].Value!;
@ -47,10 +49,12 @@ namespace SerializationGenerator
classSymbol,
serializableAttr,
null, // Do not generate schema
embedded,
null,
migrations.ToImmutableArray(),
fieldsAndProperties,
serializableTypes
serializableTypes,
embeddedSerializableTypes
);
}
@ -59,9 +63,11 @@ namespace SerializationGenerator
INamedTypeSymbol classSymbol,
AttributeData serializableAttr,
string? migrationPath,
bool embedded,
JsonSerializerOptions? jsonSerializerOptions,
ImmutableArray<ISymbol> fieldsAndProperties,
ImmutableArray<INamedTypeSymbol> serializableTypes
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes
)
{
var version = (int)serializableAttr.ConstructorArguments[0].Value!;
@ -77,10 +83,12 @@ namespace SerializationGenerator
classSymbol,
serializableAttr,
migrationPath,
embedded,
jsonSerializerOptions,
migrations.ToImmutableArray(),
fieldsAndProperties,
serializableTypes
serializableTypes,
embeddedSerializableTypes
);
}
@ -89,22 +97,27 @@ namespace SerializationGenerator
INamedTypeSymbol classSymbol,
AttributeData serializableAttr,
string? migrationPath,
bool embedded,
JsonSerializerOptions? jsonSerializerOptions,
ImmutableArray<SerializableMetadata> migrations,
ImmutableArray<ISymbol> fieldsAndProperties,
ImmutableArray<INamedTypeSymbol> serializableTypes
ImmutableArray<INamedTypeSymbol> serializableTypes,
ImmutableArray<INamedTypeSymbol> embeddedSerializableTypes
)
{
var serializableFieldAttribute =
compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_ATTRIBUTE);
var serializableFieldAttrAttribute =
compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_ATTR_ATTRIBUTE);
var serializableInterface = compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_INTERFACE);
var serializableInterface =
compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_INTERFACE);
var parentSerializableAttribute =
compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_PARENT_ATTRIBUTE);
// If we have a parent that is or derives from ISerializable, then we are in override
var isOverride = classSymbol.BaseType.ContainsInterface(serializableInterface);
if (!isOverride && !classSymbol.ContainsInterface(serializableInterface))
if (!(embedded || isOverride || classSymbol.ContainsInterface(serializableInterface)))
{
return null;
}
@ -120,10 +133,7 @@ namespace SerializationGenerator
source.AppendLine("#pragma warning disable\n");
source.GenerateNamespaceStart(namespaceName);
source.GenerateClassStart(
className,
ImmutableArray<ITypeSymbol>.Empty
);
source.GenerateClassStart(className, ImmutableArray<ITypeSymbol>.Empty);
const string indent = " ";
@ -136,6 +146,14 @@ namespace SerializationGenerator
);
source.AppendLine();
var parentFieldOrProperty = embedded ? fieldsAndProperties.FirstOrDefault(
fieldOrPropertySymbol => fieldOrPropertySymbol.GetAttributes()
.FirstOrDefault(
attr =>
SymbolEqualityComparer.Default.Equals(attr.AttributeClass, parentSerializableAttribute)
) != null
) : null;
var serializablePropertySet = new SortedSet<SerializableProperty>(new SerializablePropertyComparer());
foreach (var fieldOrPropertySymbol in fieldsAndProperties)
@ -193,7 +211,8 @@ namespace SerializationGenerator
fieldSymbol,
getterAccessor,
setterAccessor,
virtualProperty
virtualProperty,
parentFieldOrProperty
);
source.AppendLine();
}
@ -204,6 +223,7 @@ namespace SerializationGenerator
order,
allAttributes,
serializableTypes,
embeddedSerializableTypes,
classSymbol
);
@ -213,7 +233,7 @@ namespace SerializationGenerator
var serializableProperties = serializablePropertySet.ToImmutableArray();
// If we are not inheriting ISerializable, then we need to define some stuff
if (!isOverride)
if (!(isOverride || embedded))
{
// long ISerializable.SavePosition { get; set; } = -1;
source.GenerateAutoProperty(
@ -237,9 +257,12 @@ namespace SerializationGenerator
);
}
// Serial constructor
source.GenerateSerialCtor(compilation, className, isOverride);
source.AppendLine();
if (!embedded)
{
// Serial constructor
source.GenerateSerialCtor(compilation, className, isOverride);
source.AppendLine();
}
if (version > 0)
{
@ -271,7 +294,8 @@ namespace SerializationGenerator
version,
encodedVersion,
migrations,
serializableProperties
serializableProperties,
parentFieldOrProperty
);
source.GenerateClassEnd();

View file

@ -31,7 +31,8 @@ namespace SerializationGenerator
int version,
bool encodedVersion,
ImmutableArray<SerializableMetadata> migrations,
ImmutableArray<SerializableProperty> properties
ImmutableArray<SerializableProperty> properties,
ISymbol parentFieldOrProperty
)
{
var genericReaderInterface = compilation.GetTypeByMetadataName(SymbolMetadata.GENERIC_READER_INTERFACE);
@ -74,6 +75,7 @@ namespace SerializationGenerator
if (version > 0)
{
var parent = parentFieldOrProperty?.Name ?? "this";
var nextVersion = 0;
for (var i = 0; i < migrations.Length; i++)
@ -88,7 +90,7 @@ namespace SerializationGenerator
source.AppendLine($"{indent}if (version == {migrationVersion})");
source.AppendLine($"{indent}{{");
source.AppendLine($"{indent} MigrateFrom(new V{migrationVersion}Content(reader));");
source.AppendLine($"{indent} ((Server.ISerializable)this).MarkDirty();");
source.AppendLine($"{indent} {parent}.MarkDirty();");
if (afterDeserialization != null)
{
source.AppendLine($"{indent} Timer.DelayCall({afterDeserialization.Name});");
@ -103,7 +105,7 @@ namespace SerializationGenerator
source.AppendLine($"{indent}if (version < _version)");
source.AppendLine($"{indent}{{");
source.AppendLine($"{indent} Deserialize(reader, version);");
source.AppendLine($"{indent} ((Server.ISerializable)this).MarkDirty();");
source.AppendLine($"{indent} {parent}.MarkDirty();");
if (afterDeserialization != null)
{
source.AppendLine($"{indent} Timer.DelayCall({afterDeserialization.Name});");
@ -116,11 +118,14 @@ namespace SerializationGenerator
foreach (var property in properties)
{
source.AppendLine();
SerializableMigrationRulesEngine.Rules[property.Rule].GenerateDeserializationMethod(
var rule = SerializableMigrationRulesEngine.Rules[property.Rule];
rule.GenerateDeserializationMethod(
source,
indent,
property
);
(rule as IPostDeserializeMethod)?.PostDeserializeMethod(source, indent, property, compilation, classSymbol);
}
if (afterDeserialization != null)

View file

@ -27,7 +27,8 @@ namespace SerializationGenerator
IFieldSymbol fieldSymbol,
Accessibility getter,
Accessibility? setter,
bool isVirtual
bool isVirtual,
ISymbol? parentFieldOrProperty = null
)
{
var fieldName = fieldSymbol.Name;
@ -54,16 +55,18 @@ namespace SerializationGenerator
// Getter
source.GeneratePropertyGetterReturnsField(propertyIndent, fieldSymbol, getterAccessor);
if (setter != null)
if (setter != null && setter != Accessibility.NotApplicable)
{
var setterAccessor = setter == propertyAccessor ? Accessibility.NotApplicable : setter;
var parentSymbol = parentFieldOrProperty?.Name ?? "this";
// Setter
source.GeneratePropertySetterStart(propertyIndent, false, setterAccessor.Value);
source.AppendLine($"{innerIndent}if (value != {fieldName})");
source.AppendLine($"{innerIndent}{{");
source.AppendLine($"{innerIndent} {fieldName} = value;");
source.AppendLine($"{innerIndent} ((ISerializable)this).MarkDirty();");
source.AppendLine($"{innerIndent} {parentSymbol}.MarkDirty();");
if (invalidatePropertiesAttribute != null)
{