fix: Fixes codegenning nested classes (#738)

This commit is contained in:
Kamron Batman 2021-08-27 19:08:04 -07:00 committed by GitHub
parent 408a343e0c
commit 862e868cf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 63 deletions

View file

@ -168,11 +168,13 @@ namespace SerializationGenerator
? Array.Empty<ITypeSymbol>() ? Array.Empty<ITypeSymbol>()
: new ITypeSymbol[] { compilation.GetTypeByMetadataName(SymbolMetadata.RAW_SERIALIZABLE_INTERFACE) }; : new ITypeSymbol[] { compilation.GetTypeByMetadataName(SymbolMetadata.RAW_SERIALIZABLE_INTERFACE) };
source.GenerateClassStart(className, " ", interfaces.ToImmutableArray()); var indent = " ";
const string indent = " "; source.RecursiveGenerateClassStart(classSymbol, interfaces.ToImmutableArray(), ref indent);
indent += " ";
source.GenerateClassField( source.GenerateClassField(
indent,
Accessibility.Private, Accessibility.Private,
InstanceModifier.Const, InstanceModifier.Const,
"int", "int",
@ -223,7 +225,7 @@ namespace SerializationGenerator
if (attrTypeArg.Kind == TypedConstantKind.Primitive && attrTypeArg.Value is string attrStr) if (attrTypeArg.Kind == TypedConstantKind.Primitive && attrTypeArg.Value is string attrStr)
{ {
source.AppendLine($" {attrStr}"); source.AppendLine($"{indent} {attrStr}");
} }
else else
{ {
@ -298,7 +300,7 @@ namespace SerializationGenerator
if (!embedded) if (!embedded)
{ {
// Serial constructor // Serial constructor
source.GenerateSerialCtor(compilation, className, isOverride); source.GenerateSerialCtor(compilation, className, indent, isOverride);
source.AppendLine(); source.AppendLine();
} }
@ -309,7 +311,7 @@ namespace SerializationGenerator
var migration = migrations[i]; var migration = migrations[i];
if (migration.Version < version) if (migration.Version < version)
{ {
source.GenerateMigrationContentStruct(compilation, migration, classSymbol); source.GenerateMigrationContentStruct(compilation, indent, migration, classSymbol);
source.AppendLine(); source.AppendLine();
} }
} }
@ -318,6 +320,7 @@ namespace SerializationGenerator
// Serialize Method // Serialize Method
source.GenerateSerializeMethod( source.GenerateSerializeMethod(
compilation, compilation,
indent,
isOverride, isOverride,
encodedVersion, encodedVersion,
serializableProperties, serializableProperties,
@ -329,6 +332,7 @@ namespace SerializationGenerator
source.GenerateDeserializeMethod( source.GenerateDeserializeMethod(
compilation, compilation,
classSymbol, classSymbol,
indent,
isOverride, isOverride,
version, version,
encodedVersion, encodedVersion,
@ -344,22 +348,23 @@ namespace SerializationGenerator
source.AppendLine(); source.AppendLine();
source.GenerateEnumStart( source.GenerateEnumStart(
"SaveFlag", "SaveFlag",
" ", $"{indent} ",
true, true,
Accessibility.Private Accessibility.Private
); );
source.GenerateEnumValue(" ", true, "None", -1); source.GenerateEnumValue($"{indent} ", true, "None", -1);
int index = 0; int index = 0;
foreach (var (order, _) in serializableFieldSaveFlags) foreach (var (order, _) in serializableFieldSaveFlags)
{ {
source.GenerateEnumValue(" ", true, serializableProperties[order].Name, index++); source.GenerateEnumValue($"{indent} ", true, serializableProperties[order].Name, index++);
} }
source.GenerateEnumEnd(" "); source.GenerateEnumEnd($"{indent} ");
} }
source.GenerateClassEnd(" "); indent = indent.Substring(0, indent.Length - 4);
source.RecursiveGenerateClassEnd(classSymbol, ref indent);
source.GenerateNamespaceEnd(); source.GenerateNamespaceEnd();
if (migrationPath != null) if (migrationPath != null)
@ -384,5 +389,41 @@ namespace SerializationGenerator
var filePath = Path.Combine(migrationPath, $"{metadata.Type}.v{metadata.Version}.json"); var filePath = Path.Combine(migrationPath, $"{metadata.Type}.v{metadata.Version}.json");
File.WriteAllText(filePath, JsonSerializer.Serialize(metadata, options)); File.WriteAllText(filePath, JsonSerializer.Serialize(metadata, options));
} }
private static void RecursiveGenerateClassStart(
this StringBuilder source,
INamedTypeSymbol classSymbol,
ImmutableArray<ITypeSymbol> interfaces,
ref string indent
)
{
var containingSymbolList = new List<INamedTypeSymbol>();
do
{
containingSymbolList.Add(classSymbol);
classSymbol = classSymbol.ContainingSymbol as INamedTypeSymbol;
} while (classSymbol != null);
containingSymbolList.Reverse();
for (var i = 0; i < containingSymbolList.Count; i++)
{
var symbol = containingSymbolList[i];
source.GenerateClassStart(symbol, indent, i == containingSymbolList.Count - 1 ? interfaces : ImmutableArray<ITypeSymbol>.Empty);
indent += " ";
}
}
private static void RecursiveGenerateClassEnd(this StringBuilder source, INamedTypeSymbol classSymbol, ref string indent)
{
do
{
source.GenerateClassEnd(indent);
indent = indent.Substring(0, indent.Length - 4);
classSymbol = classSymbol.ContainingSymbol as INamedTypeSymbol;
} while (classSymbol != null);
}
} }
} }

View file

@ -28,6 +28,7 @@ namespace SerializationGenerator
this StringBuilder source, this StringBuilder source,
Compilation compilation, Compilation compilation,
INamedTypeSymbol classSymbol, INamedTypeSymbol classSymbol,
string indent,
bool isOverride, bool isOverride,
int version, int version,
bool encodedVersion, bool encodedVersion,
@ -40,7 +41,7 @@ namespace SerializationGenerator
var genericReaderInterface = compilation.GetTypeByMetadataName(SymbolMetadata.GENERIC_READER_INTERFACE); var genericReaderInterface = compilation.GetTypeByMetadataName(SymbolMetadata.GENERIC_READER_INTERFACE);
source.GenerateMethodStart( source.GenerateMethodStart(
" ", indent,
"Deserialize", "Deserialize",
Accessibility.Public, Accessibility.Public,
isOverride, isOverride,
@ -48,12 +49,12 @@ namespace SerializationGenerator
ImmutableArray.Create<(ITypeSymbol, string)>((genericReaderInterface, "reader")) ImmutableArray.Create<(ITypeSymbol, string)>((genericReaderInterface, "reader"))
); );
const string indent = " "; var bodyIndent = $"{indent} ";
const string innerIndent = $"{indent} "; var innerIndent = $"{bodyIndent} ";
if (isOverride) if (isOverride)
{ {
source.AppendLine($"{indent}base.Deserialize(reader);"); source.AppendLine($"{bodyIndent}base.Deserialize(reader);");
source.AppendLine(); source.AppendLine();
} }
@ -79,7 +80,7 @@ namespace SerializationGenerator
).Where(m => m.Item2 != null).ToList(); ).Where(m => m.Item2 != null).ToList();
// Version // Version
source.AppendLine($"{indent}var version = reader.{(encodedVersion ? "ReadEncodedInt" : "ReadInt")}();"); source.AppendLine($"{bodyIndent}var version = reader.{(encodedVersion ? "ReadEncodedInt" : "ReadInt")}();");
if (version > 0) if (version > 0)
{ {
@ -95,32 +96,32 @@ namespace SerializationGenerator
} }
source.AppendLine(); source.AppendLine();
source.AppendLine($"{indent}if (version == {migrationVersion})"); source.AppendLine($"{bodyIndent}if (version == {migrationVersion})");
source.AppendLine($"{indent}{{"); source.AppendLine($"{bodyIndent}{{");
source.AppendLine($"{indent} MigrateFrom(new V{migrationVersion}Content(reader, this));"); source.AppendLine($"{bodyIndent} MigrateFrom(new V{migrationVersion}Content(reader, this));");
source.AppendLine($"{indent} {parent}.MarkDirty();"); source.AppendLine($"{bodyIndent} {parent}.MarkDirty();");
source.GenerateAfterDeserialization($"{indent} ", afterDeserialization); source.GenerateAfterDeserialization($"{bodyIndent} ", afterDeserialization);
source.AppendLine($"{indent} return;"); source.AppendLine($"{bodyIndent} return;");
source.AppendLine($"{indent}}}"); source.AppendLine($"{bodyIndent}}}");
} }
if (nextVersion < version) if (nextVersion < version)
{ {
source.AppendLine(); source.AppendLine();
source.AppendLine($"{indent}if (version < _version)"); source.AppendLine($"{bodyIndent}if (version < _version)");
source.AppendLine($"{indent}{{"); source.AppendLine($"{bodyIndent}{{");
source.AppendLine($"{indent} Deserialize(reader, version);"); source.AppendLine($"{bodyIndent} Deserialize(reader, version);");
source.AppendLine($"{indent} {parent}.MarkDirty();"); source.AppendLine($"{bodyIndent} {parent}.MarkDirty();");
source.GenerateAfterDeserialization($"{indent} ", afterDeserialization); source.GenerateAfterDeserialization($"{bodyIndent} ", afterDeserialization);
source.AppendLine($"{indent} return;"); source.AppendLine($"{bodyIndent} return;");
source.AppendLine($"{indent}}}"); source.AppendLine($"{bodyIndent}}}");
} }
} }
if (serializableFieldSaveFlagMethodsDictionary.Count > 0) if (serializableFieldSaveFlagMethodsDictionary.Count > 0)
{ {
source.AppendLine(); source.AppendLine();
source.AppendLine($"{indent}var saveFlags = reader.ReadEnum<SaveFlag>();"); source.AppendLine($"{bodyIndent}var saveFlags = reader.ReadEnum<SaveFlag>();");
} }
foreach (var property in properties) foreach (var property in properties)
@ -137,11 +138,11 @@ namespace SerializationGenerator
// Special case // Special case
if (property.Type == "bool") if (property.Type == "bool")
{ {
source.AppendLine($"{indent}{property.Name} = (saveFlags & SaveFlag.{property.Name}) != 0;"); source.AppendLine($"{bodyIndent}{property.Name} = (saveFlags & SaveFlag.{property.Name}) != 0;");
} }
else else
{ {
source.AppendLine($"{indent}if ((saveFlags & SaveFlag.{property.Name}) != 0)\n{indent}{{"); source.AppendLine($"{bodyIndent}if ((saveFlags & SaveFlag.{property.Name}) != 0)\n{bodyIndent}{{");
rule.GenerateDeserializationMethod( rule.GenerateDeserializationMethod(
source, source,
innerIndent, innerIndent,
@ -152,13 +153,13 @@ namespace SerializationGenerator
if (serializableFieldSaveFlagMethods.GetFieldDefaultValue != null) if (serializableFieldSaveFlagMethods.GetFieldDefaultValue != null)
{ {
source.AppendLine($"{indent}}}\n{indent}else\n{indent}{{"); source.AppendLine($"{bodyIndent}}}\n{bodyIndent}else\n{bodyIndent}{{");
source.AppendLine( source.AppendLine(
$"{indent} {property.Name} = {serializableFieldSaveFlagMethods.GetFieldDefaultValue.Name}();" $"{bodyIndent} {property.Name} = {serializableFieldSaveFlagMethods.GetFieldDefaultValue.Name}();"
); );
} }
source.AppendLine($"{indent}}}"); source.AppendLine($"{bodyIndent}}}");
} }
} }
else else
@ -166,16 +167,16 @@ namespace SerializationGenerator
source.AppendLine(); source.AppendLine();
rule.GenerateDeserializationMethod( rule.GenerateDeserializationMethod(
source, source,
indent, bodyIndent,
property, property,
parentFieldOrProperty?.Name ?? "this" parentFieldOrProperty?.Name ?? "this"
); );
(rule as IPostDeserializeMethod)?.PostDeserializeMethod(source, indent, property, compilation, classSymbol); (rule as IPostDeserializeMethod)?.PostDeserializeMethod(source, bodyIndent, property, compilation, classSymbol);
} }
} }
source.GenerateAfterDeserialization($"{indent}", afterDeserialization); source.GenerateAfterDeserialization($"{bodyIndent}", afterDeserialization);
source.GenerateMethodEnd(" "); source.GenerateMethodEnd(indent);
} }
private static void GenerateAfterDeserialization( private static void GenerateAfterDeserialization(

View file

@ -26,13 +26,14 @@ namespace SerializationGenerator
this StringBuilder source, this StringBuilder source,
Compilation compilation, Compilation compilation,
string className, string className,
string indent,
bool isOverride bool isOverride
) )
{ {
var serialType = (ITypeSymbol)compilation.GetTypeByMetadataName("Server.Serial"); var serialType = (ITypeSymbol)compilation.GetTypeByMetadataName("Server.Serial");
source.GenerateConstructorStart( source.GenerateConstructorStart(
" ", indent,
className, className,
Accessibility.Public, Accessibility.Public,
new []{ (serialType, "serial") }.ToImmutableArray(), new []{ (serialType, "serial") }.ToImmutableArray(),
@ -41,11 +42,11 @@ namespace SerializationGenerator
if (!isOverride) if (!isOverride)
{ {
source.AppendLine(@$" Serial = serial; source.AppendLine($"{indent} Serial = serial;");
SetTypeRef(typeof({className}));"); source.AppendLine($"{indent} SetTypeRef(typeof({className}));");
} }
source.GenerateMethodEnd(" "); source.GenerateMethodEnd(indent);
} }
} }
} }

View file

@ -27,6 +27,7 @@ namespace SerializationGenerator
public static void GenerateSerializeMethod( public static void GenerateSerializeMethod(
this StringBuilder source, this StringBuilder source,
Compilation compilation, Compilation compilation,
string indent,
bool isOverride, bool isOverride,
bool encodedVersion, bool encodedVersion,
ImmutableArray<SerializableProperty> properties, ImmutableArray<SerializableProperty> properties,
@ -36,7 +37,7 @@ namespace SerializationGenerator
var genericWriterInterface = compilation.GetTypeByMetadataName(SymbolMetadata.GENERIC_WRITER_INTERFACE); var genericWriterInterface = compilation.GetTypeByMetadataName(SymbolMetadata.GENERIC_WRITER_INTERFACE);
source.GenerateMethodStart( source.GenerateMethodStart(
" ", indent,
"Serialize", "Serialize",
Accessibility.Public, Accessibility.Public,
isOverride, isOverride,
@ -44,34 +45,34 @@ namespace SerializationGenerator
ImmutableArray.Create<(ITypeSymbol, string)>((genericWriterInterface, "writer")) ImmutableArray.Create<(ITypeSymbol, string)>((genericWriterInterface, "writer"))
); );
const string indent = " "; var bodyIndent = $"{indent} ";
const string innerIndent = $"{indent} "; var innerIndent = $"{bodyIndent} ";
if (isOverride) if (isOverride)
{ {
source.AppendLine($"{indent}base.Serialize(writer);"); source.AppendLine($"{bodyIndent}base.Serialize(writer);");
source.AppendLine(); source.AppendLine();
} }
// Version // Version
source.AppendLine($"{indent}writer.{(encodedVersion ? "WriteEncodedInt" : "Write")}(_version);"); source.AppendLine($"{bodyIndent}writer.{(encodedVersion ? "WriteEncodedInt" : "Write")}(_version);");
// Let's collect the flags // Let's collect the flags
if (serializableFieldSaveFlagMethodsDictionary.Count > 0) if (serializableFieldSaveFlagMethodsDictionary.Count > 0)
{ {
source.AppendLine($"\n{indent}var saveFlags = SaveFlag.None;"); source.AppendLine($"\n{bodyIndent}var saveFlags = SaveFlag.None;");
foreach (var (order, saveFlagMethods) in serializableFieldSaveFlagMethodsDictionary) foreach (var (order, saveFlagMethods) in serializableFieldSaveFlagMethodsDictionary)
{ {
source.AppendLine($"{indent}if ({saveFlagMethods.DetermineFieldShouldSerialize!.Name}())\n{indent}{{"); source.AppendLine($"{bodyIndent}if ({saveFlagMethods.DetermineFieldShouldSerialize!.Name}())\n{bodyIndent}{{");
var propertyName = properties[order].Name; var propertyName = properties[order].Name;
source.AppendLine($"{innerIndent}saveFlags |= SaveFlag.{propertyName};"); source.AppendLine($"{innerIndent}saveFlags |= SaveFlag.{propertyName};");
source.AppendLine($"{indent}}}"); source.AppendLine($"{bodyIndent}}}");
} }
source.AppendLine($"{indent}writer.WriteEnum(saveFlags);"); source.AppendLine($"{bodyIndent}writer.WriteEnum(saveFlags);");
} }
foreach (var property in properties) foreach (var property in properties)
@ -81,13 +82,13 @@ namespace SerializationGenerator
// Special case // Special case
if (property.Type != "bool") if (property.Type != "bool")
{ {
source.AppendLine($"\n{indent}if ((saveFlags & SaveFlag.{property.Name}) != 0)\n{indent}{{"); source.AppendLine($"\n{bodyIndent}if ((saveFlags & SaveFlag.{property.Name}) != 0)\n{bodyIndent}{{");
SerializableMigrationRulesEngine.Rules[property.Rule].GenerateSerializationMethod( SerializableMigrationRulesEngine.Rules[property.Rule].GenerateSerializationMethod(
source, source,
innerIndent, innerIndent,
property property
); );
source.AppendLine($"{indent}}}"); source.AppendLine($"{bodyIndent}}}");
} }
} }
else else
@ -95,13 +96,13 @@ namespace SerializationGenerator
source.AppendLine(); source.AppendLine();
SerializableMigrationRulesEngine.Rules[property.Rule].GenerateSerializationMethod( SerializableMigrationRulesEngine.Rules[property.Rule].GenerateSerializationMethod(
source, source,
indent, bodyIndent,
property property
); );
} }
} }
source.GenerateMethodEnd(" "); source.GenerateMethodEnd(indent);
} }
} }
} }

View file

@ -26,12 +26,11 @@ namespace SerializationGenerator
public static void GenerateMigrationContentStruct( public static void GenerateMigrationContentStruct(
this StringBuilder source, this StringBuilder source,
Compilation compilation, Compilation compilation,
string indent,
SerializableMetadata migration, SerializableMetadata migration,
INamedTypeSymbol classSymbol INamedTypeSymbol classSymbol
) )
{ {
const string indent = " ";
source.AppendLine($"{indent}ref struct V{migration.Version}Content"); source.AppendLine($"{indent}ref struct V{migration.Version}Content");
source.AppendLine($"{indent}{{"); source.AppendLine($"{indent}{{");
var properties = migration.Properties ?? ImmutableArray<SerializableProperty>.Empty; var properties = migration.Properties ?? ImmutableArray<SerializableProperty>.Empty;
@ -46,7 +45,7 @@ namespace SerializationGenerator
source.AppendLine($"{indent} internal readonly {type} {serializableProperty.Name};"); source.AppendLine($"{indent} internal readonly {type} {serializableProperty.Name};");
} }
const string innerIndent = $"{indent} "; var innerIndent = $"{indent} ";
var usesSaveFlags = properties.Any(p => p.UsesSaveFlag == true); var usesSaveFlags = properties.Any(p => p.UsesSaveFlag == true);

View file

@ -23,14 +23,14 @@ namespace SerializationGenerator
{ {
public static void GenerateClassStart( public static void GenerateClassStart(
this StringBuilder source, this StringBuilder source,
string className, INamedTypeSymbol classSymbol,
string indent, string indent,
ImmutableArray<ITypeSymbol> interfaces, ImmutableArray<ITypeSymbol> interfaces,
Accessibility accessor = Accessibility.Public,
bool isPartial = true bool isPartial = true
) )
{ {
source.Append($"{indent}{accessor.ToFriendlyString()} {(isPartial ? "partial " : "")}class {className}"); var accessor = classSymbol.DeclaredAccessibility;
source.Append($"{indent}{accessor.ToFriendlyString()} {(isPartial ? "partial " : "")}class {classSymbol.Name}");
if (!interfaces.IsEmpty) if (!interfaces.IsEmpty)
{ {
source.Append(" : "); source.Append(" : ");
@ -55,6 +55,7 @@ namespace SerializationGenerator
// TODO: Generalize this to any field using dynamic indentation // TODO: Generalize this to any field using dynamic indentation
public static void GenerateClassField( public static void GenerateClassField(
this StringBuilder source, this StringBuilder source,
string indent,
Accessibility accessors, Accessibility accessors,
InstanceModifier instance, InstanceModifier instance,
string type, string type,
@ -65,7 +66,7 @@ namespace SerializationGenerator
var instanceStr = instance == InstanceModifier.None ? "" : $"{instance.ToFriendlyString()} "; var instanceStr = instance == InstanceModifier.None ? "" : $"{instance.ToFriendlyString()} ";
var accessorStr = accessors == Accessibility.NotApplicable ? "" : $"{accessors.ToFriendlyString()} "; var accessorStr = accessors == Accessibility.NotApplicable ? "" : $"{accessors.ToFriendlyString()} ";
var valueStr = value == null ? "" : $" = {value}"; var valueStr = value == null ? "" : $" = {value}";
source.AppendLine($" {accessorStr}{instanceStr}{type} {variableName}{valueStr};"); source.AppendLine($"{indent}{accessorStr}{instanceStr}{type} {variableName}{valueStr};");
} }
} }
} }