fix(codegen): Adds access modifiers to serializable fields (#633)

- [X] Adds options for SerializableField.

Example:
```cs
[SerializableField(0, getter: "protected", setter: "protected", isVritual: true)]
private int _someField;
```

Defaults: `getter: "public", setter: "public", isVirtual: false`
This commit is contained in:
Kamron Batman 2021-06-01 22:53:51 -07:00 committed by GitHub
parent 72d3966541
commit 803b4a33cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 183 additions and 164 deletions

View file

@ -1,7 +1,7 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
using Xunit; using Xunit;
namespace SerializationGeneratorTests namespace SerializationGeneratorTests

View file

@ -21,7 +21,6 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SerializableMigration; using SerializableMigration;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {
@ -128,7 +127,7 @@ namespace SerializationGenerator
const string indent = " "; const string indent = " ";
source.GenerateClassField( source.GenerateClassField(
AccessModifier.Private, Accessibility.Private,
InstanceModifier.Const, InstanceModifier.Const,
"int", "int",
"_version", "_version",
@ -154,8 +153,6 @@ namespace SerializationGenerator
continue; continue;
} }
var order = (int)serializableFieldAttr.ConstructorArguments[0].Value!;
foreach (var attr in allAttributes) foreach (var attr in allAttributes)
{ {
if (!SymbolEqualityComparer.Default.Equals(attr.AttributeClass, serializableFieldAttrAttribute)) if (!SymbolEqualityComparer.Default.Equals(attr.AttributeClass, serializableFieldAttrAttribute))
@ -182,9 +179,22 @@ namespace SerializationGenerator
} }
} }
var attrCtorArgs = serializableFieldAttr.ConstructorArguments;
var order = (int)attrCtorArgs[0].Value!;
var getterAccessor = Helpers.GetAccessibility(attrCtorArgs[1].Value!.ToString());
var setterAccessor = Helpers.GetAccessibility(attrCtorArgs[2].Value!.ToString());
var virtualProperty = (bool)attrCtorArgs[3].Value!;
if (fieldOrPropertySymbol is IFieldSymbol fieldSymbol) if (fieldOrPropertySymbol is IFieldSymbol fieldSymbol)
{ {
source.GenerateSerializableProperty(fieldSymbol, compilation); source.GenerateSerializableProperty(
compilation,
fieldSymbol,
getterAccessor,
setterAccessor,
virtualProperty
);
source.AppendLine(); source.AppendLine();
} }
@ -206,22 +216,22 @@ namespace SerializationGenerator
{ {
// long ISerializable.SavePosition { get; set; } = -1; // long ISerializable.SavePosition { get; set; } = -1;
source.GenerateAutoProperty( source.GenerateAutoProperty(
AccessModifier.None, Accessibility.NotApplicable,
"long", "long",
"ISerializable.SavePosition", "ISerializable.SavePosition",
AccessModifier.None, Accessibility.NotApplicable,
AccessModifier.None, Accessibility.NotApplicable,
indent, indent,
defaultValue: "-1" defaultValue: "-1"
); );
// BufferWriter ISerializable.SaveBuffer { get; set; } // BufferWriter ISerializable.SaveBuffer { get; set; }
source.GenerateAutoProperty( source.GenerateAutoProperty(
AccessModifier.None, Accessibility.NotApplicable,
"BufferWriter", "BufferWriter",
"ISerializable.SaveBuffer", "ISerializable.SaveBuffer",
AccessModifier.None, Accessibility.NotApplicable,
AccessModifier.None, Accessibility.NotApplicable,
indent indent
); );
} }

View file

@ -18,7 +18,6 @@ using System.Linq;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SerializableMigration; using SerializableMigration;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {
@ -39,7 +38,7 @@ namespace SerializationGenerator
source.GenerateMethodStart( source.GenerateMethodStart(
"Deserialize", "Deserialize",
AccessModifier.Public, Accessibility.Public,
isOverride, isOverride,
"void", "void",
ImmutableArray.Create<(ITypeSymbol, string)>((genericReaderInterface, "reader")) ImmutableArray.Create<(ITypeSymbol, string)>((genericReaderInterface, "reader"))

View file

@ -16,7 +16,6 @@
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {
@ -24,8 +23,11 @@ namespace SerializationGenerator
{ {
public static void GenerateSerializableProperty( public static void GenerateSerializableProperty(
this StringBuilder source, this StringBuilder source,
Compilation compilation,
IFieldSymbol fieldSymbol, IFieldSymbol fieldSymbol,
Compilation compilation Accessibility getter,
Accessibility? setter,
bool isVirtual
) )
{ {
var fieldName = fieldSymbol.Name; var fieldName = fieldSymbol.Name;
@ -40,27 +42,38 @@ namespace SerializationGenerator
) ?? false ) ?? false
); );
source.GeneratePropertyStart(AccessModifier.Public, fieldSymbol); const string indent = " ";
const string propertyIndent = " ";
var propertyAccessor = setter > getter ? setter : getter;
var getterAccessor = getter == propertyAccessor ? Accessibility.NotApplicable : getter;
source.GeneratePropertyStart(indent, propertyAccessor.Value, isVirtual, fieldSymbol);
// Getter // Getter
source.GeneratePropertyGetterReturnsField(fieldSymbol); source.GeneratePropertyGetterReturnsField(propertyIndent, fieldSymbol, getterAccessor);
// Setter if (setter != null)
source.GeneratePropertySetterStart(false);
const string indent = " ";
source.AppendLine($"{indent}if (value != {fieldName})");
source.AppendLine($"{indent}{{");
source.AppendLine($"{indent} {fieldName} = value;");
source.AppendLine($"{indent} ((ISerializable)this).MarkDirty();");
if (invalidatePropertiesAttribute != null)
{ {
source.AppendLine($"{indent} InvalidateProperties();"); var setterAccessor = setter == propertyAccessor ? Accessibility.NotApplicable : setter;
}
source.AppendLine($"{indent}}}");
source.GeneratePropertyGetSetEnd(false);
source.GeneratePropertyEnd(); // Setter
source.GeneratePropertySetterStart(propertyIndent, false, setterAccessor.Value);
const string innerIndent = " ";
source.AppendLine($"{innerIndent}if (value != {fieldName})");
source.AppendLine($"{innerIndent}{{");
source.AppendLine($"{innerIndent} {fieldName} = value;");
source.AppendLine($"{innerIndent} ((ISerializable)this).MarkDirty();");
if (invalidatePropertiesAttribute != null)
{
source.AppendLine($"{innerIndent} InvalidateProperties();");
}
source.AppendLine($"{innerIndent}}}");
source.GeneratePropertyGetSetEnd(propertyIndent, false);
}
source.GeneratePropertyEnd(indent);
} }
} }
} }

View file

@ -16,7 +16,6 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {
@ -34,7 +33,7 @@ namespace SerializationGenerator
source.GenerateConstructorStart( source.GenerateConstructorStart(
className, className,
AccessModifier.Public, Accessibility.Public,
new []{ (serialType, "serial") }.ToImmutableArray(), new []{ (serialType, "serial") }.ToImmutableArray(),
isOverride ? _baseParameters : ImmutableArray<string>.Empty isOverride ? _baseParameters : ImmutableArray<string>.Empty
); );

View file

@ -17,7 +17,6 @@ using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SerializableMigration; using SerializableMigration;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {
@ -35,7 +34,7 @@ namespace SerializationGenerator
source.GenerateMethodStart( source.GenerateMethodStart(
"Serialize", "Serialize",
AccessModifier.Public, Accessibility.Public,
isOverride, isOverride,
"void", "void",
ImmutableArray.Create<(ITypeSymbol, string)>((genericWriterInterface, "writer")) ImmutableArray.Create<(ITypeSymbol, string)>((genericWriterInterface, "writer"))

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -18,7 +18,7 @@ using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -17,7 +17,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SourceGeneration; using SerializationGenerator;
namespace SerializableMigration namespace SerializableMigration
{ {

View file

@ -13,7 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/ *************************************************************************/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -58,6 +57,7 @@ namespace SerializableMigration
{ {
var text = File.ReadAllText(file, Encoding.UTF8); var text = File.ReadAllText(file, Encoding.UTF8);
migration = JsonSerializer.Deserialize<SerializableMetadata>(text, options); migration = JsonSerializer.Deserialize<SerializableMetadata>(text, options);
_cache[fi.Name] = migration;
} }
if (typeName == migration!.Type && version > migration.Version) if (typeName == migration!.Type && version > migration.Version)
@ -96,6 +96,7 @@ namespace SerializableMigration
} }
migration = JsonSerializer.Deserialize<SerializableMetadata>(text, options); migration = JsonSerializer.Deserialize<SerializableMetadata>(text, options);
_cache[fi.Name] = migration;
} }
if (typeName == migration!.Type && version > migration.Version) if (typeName == migration!.Type && version > migration.Version)

View file

@ -13,12 +13,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/ *************************************************************************/
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using SourceGeneration;
namespace SerializationGenerator namespace SerializationGenerator
{ {

View file

@ -17,8 +17,9 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static class Helpers public static class Helpers
{ {
@ -40,5 +41,19 @@ namespace SourceGeneration
return list.ToImmutableArray(); return list.ToImmutableArray();
} }
public static string ToFriendlyString(this Accessibility accessibility) => SyntaxFacts.GetText(accessibility);
public static Accessibility GetAccessibility(string value) =>
value switch
{
"private" => Accessibility.Private,
"protected" => Accessibility.Protected,
"internal" => Accessibility.Internal,
"public" => Accessibility.Public,
"protected internal" => Accessibility.ProtectedOrInternal,
"private protected" => Accessibility.ProtectedAndInternal,
_ => Accessibility.NotApplicable
};
} }
} }

View file

@ -1,43 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SourceGeneration.AccessModifier.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/>. *
*************************************************************************/
namespace SourceGeneration
{
public enum AccessModifier
{
None,
Public,
Private,
Protected,
Internal,
ProtectedInternal,
PrivateProtected
}
public static partial class SourceGeneration
{
public static string ToFriendlyString(this AccessModifier modifier) =>
modifier switch
{
AccessModifier.Public => "public",
AccessModifier.Private => "private",
AccessModifier.Protected => "protected",
AccessModifier.Internal => "internal",
AccessModifier.ProtectedInternal => "protected internal",
AccessModifier.PrivateProtected => "private protected",
_ => ""
};
}
}

View file

@ -18,7 +18,7 @@ using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {

View file

@ -17,7 +17,7 @@ using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {

View file

@ -17,7 +17,7 @@ using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {
@ -49,7 +49,7 @@ namespace SourceGeneration
// 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,
AccessModifier accessors, Accessibility accessors,
InstanceModifier instance, InstanceModifier instance,
string type, string type,
string variableName, string variableName,
@ -63,7 +63,7 @@ namespace SourceGeneration
} }
var instanceStr = instance == InstanceModifier.None ? "" : $"{instance.ToFriendlyString()} "; var instanceStr = instance == InstanceModifier.None ? "" : $"{instance.ToFriendlyString()} ";
var accessorStr = accessors == AccessModifier.None ? "" : $"{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($" {accessorStr}{instanceStr}{type} {variableName}{valueStr};");

View file

@ -13,7 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/ *************************************************************************/
namespace SourceGeneration namespace SerializationGenerator
{ {
public enum InstanceModifier public enum InstanceModifier
{ {

View file

@ -17,11 +17,11 @@ using System.Collections.Immutable;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {
public static void GenerateMethodStart(this StringBuilder source, string methodName, AccessModifier accessors, bool isOverride, string returnType, ImmutableArray<(ITypeSymbol, string)> parameters) public static void GenerateMethodStart(this StringBuilder source, string methodName, Accessibility accessors, bool isOverride, string returnType, ImmutableArray<(ITypeSymbol, string)> parameters)
{ {
source.Append($" {accessors.ToFriendlyString()}{(isOverride ? " override" : "")} {returnType} {methodName}("); source.Append($" {accessors.ToFriendlyString()}{(isOverride ? " override" : "")} {returnType} {methodName}(");
source.GenerateSignatureArguments(parameters); source.GenerateSignatureArguments(parameters);
@ -32,7 +32,7 @@ namespace SourceGeneration
public static void GenerateMethodEnd(this StringBuilder source) => source.AppendLine(@" }"); public static void GenerateMethodEnd(this StringBuilder source) => source.AppendLine(@" }");
public static void GenerateConstructorStart( public static void GenerateConstructorStart(
this StringBuilder source, string className, AccessModifier accessors, ImmutableArray<(ITypeSymbol, string)> parameters, this StringBuilder source, string className, Accessibility accessors, ImmutableArray<(ITypeSymbol, string)> parameters,
ImmutableArray<string> baseParameters, bool isOverload = false ImmutableArray<string> baseParameters, bool isOverload = false
) )
{ {

View file

@ -15,7 +15,7 @@
using System.Text; using System.Text;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {

View file

@ -18,7 +18,7 @@ using System.Text;
using Humanizer; using Humanizer;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SourceGeneration public static partial class SourceGeneration
{ {
@ -42,23 +42,26 @@ namespace SourceGeneration
public static void GeneratePropertyStart( public static void GeneratePropertyStart(
this StringBuilder source, this StringBuilder source,
AccessModifier accessors, string indent,
Accessibility accessors,
bool isVirtual,
IFieldSymbol fieldSymbol IFieldSymbol fieldSymbol
) )
{ {
var propertyName = fieldSymbol.GetPropertyName(); var propertyName = fieldSymbol.GetPropertyName();
var virt = isVirtual ? "virtual " : "";
source.AppendLine($@" {accessors.ToFriendlyString()} {fieldSymbol.Type} {propertyName} source.AppendLine($"{indent}{accessors.ToFriendlyString()} {virt}{fieldSymbol.Type} {propertyName}");
{{"); source.AppendLine($"{indent}{{");
} }
public static void GenerateAutoProperty( public static void GenerateAutoProperty(
this StringBuilder source, this StringBuilder source,
AccessModifier accessors, Accessibility accessors,
string type, string type,
string propertyName, string propertyName,
AccessModifier? getAccessor, Accessibility? getAccessor,
AccessModifier? setAccessor, Accessibility? setAccessor,
string indent, string indent,
bool useInit = false, bool useInit = false,
string defaultValue = null, string defaultValue = null,
@ -72,18 +75,18 @@ namespace SourceGeneration
var getter = getAccessor == null ? var getter = getAccessor == null ?
"" : "" :
$"{(getAccessor != AccessModifier.None ? $"{getAccessor.Value.ToFriendlyString()} " : "")}get;"; $"{(getAccessor != Accessibility.NotApplicable ? $"{getAccessor.Value.ToFriendlyString()} " : "")}get;";
var getterSpace = getAccessor != null ? " " : ""; var getterSpace = getAccessor != null ? " " : "";
var setOrInit = useInit ? "init;" : "set;"; var setOrInit = useInit ? "init;" : "set;";
var setterAccessor = setAccessor is null or AccessModifier.None var setterAccessor = setAccessor is null or Accessibility.NotApplicable
? "" ? ""
: $"{setAccessor.Value.ToFriendlyString() ?? ""} "; : $"{setAccessor.Value.ToFriendlyString() ?? ""} ";
var setter = setAccessor == null ? "" : $"{getterSpace}{setterAccessor}{setOrInit}"; var setter = setAccessor == null ? "" : $"{getterSpace}{setterAccessor}{setOrInit}";
var propertyAccessor = accessors == AccessModifier.None ? "" : $"{accessors.ToFriendlyString()} "; var propertyAccessor = accessors == Accessibility.NotApplicable ? "" : $"{accessors.ToFriendlyString()} ";
var printOverride = isOverride ? "override " : ""; var printOverride = isOverride ? "override " : "";
var printDefaultValue = defaultValue != null ? $"{(setAccessor != null ? " =" : "")} {defaultValue};" : ""; var printDefaultValue = defaultValue != null ? $"{(setAccessor != null ? " =" : "")} {defaultValue};" : "";
var printGetterSetter = setAccessor == null ? "=>" : $"{{ {getter}{setter} }}"; var printGetterSetter = setAccessor == null ? "=>" : $"{{ {getter}{setter} }}";
@ -91,26 +94,51 @@ namespace SourceGeneration
source.AppendLine($"{indent}{propertyAccessor}{printOverride}{type} {propertyName} {printGetterSetter}{printDefaultValue}"); source.AppendLine($"{indent}{propertyAccessor}{printOverride}{type} {propertyName} {printGetterSetter}{printDefaultValue}");
} }
public static void GeneratePropertyEnd(this StringBuilder source) => source.AppendLine(" }"); public static void GeneratePropertyEnd(this StringBuilder source, string indent) => source.AppendLine($"{indent}}}");
public static void GeneratePropertyGetterReturnsField(this StringBuilder source, IFieldSymbol fieldSymbol) => public static void GeneratePropertyGetterReturnsField(
source.AppendLine($" get => {fieldSymbol.Name};"); this StringBuilder source,
string indent,
IFieldSymbol fieldSymbol,
Accessibility Accessibility
)
{
var accessor = Accessibility != Accessibility.NotApplicable ? $"{Accessibility.ToFriendlyString()} " : "";
source.AppendLine($"{indent}{accessor}get => {fieldSymbol.Name};");
}
public static void GeneratePropertyGetterStart(this StringBuilder source, bool useExpression) => public static void GeneratePropertyGetterStart(
source.AppendLine($" get{(useExpression ? " => " : "\n {")}"); this StringBuilder source,
string indent,
bool useExpression,
Accessibility Accessibility
)
{
var accessor = Accessibility != Accessibility.NotApplicable ? $"{Accessibility.ToFriendlyString()} " : "";
var expression = useExpression ? " => " : $"\n{indent}{{";
source.AppendLine($"{indent}{accessor}get{expression}");
}
public static void GeneratePropertyGetSetEnd(this StringBuilder source, bool useExpression) public static void GeneratePropertyGetSetEnd(this StringBuilder source, string indent, bool useExpression)
{ {
if (!useExpression) if (!useExpression)
{ {
source.AppendLine(" }"); source.AppendLine($"{indent}}}");
} }
} }
public static void GeneratePropertySetterSetsValue(this StringBuilder source, IFieldSymbol fieldSymbol) => public static void GeneratePropertySetterStart(
source.AppendLine($" set => {fieldSymbol.Name} = value;"); this StringBuilder source,
string indent,
public static void GeneratePropertySetterStart(this StringBuilder source, bool useExpression, bool useInit = false) => bool useExpression,
source.AppendLine($" {(useInit ? "init" : "set")}{(useExpression ? " => " : "\n {")}"); Accessibility Accessibility,
bool useInit = false
)
{
var init = useInit ? "init" : "set";
var expression = useExpression ? " => " : $"\n{indent}{{";
var accessor = Accessibility != Accessibility.NotApplicable ? $"{Accessibility.ToFriendlyString()} " : "";
source.AppendLine($"{indent}{accessor}{init}{expression}");
}
} }
} }

View file

@ -15,7 +15,7 @@
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SymbolMetadata public static partial class SymbolMetadata
{ {

View file

@ -13,12 +13,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/ *************************************************************************/
using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
namespace SourceGeneration namespace SerializationGenerator
{ {
public static partial class SymbolMetadata public static partial class SymbolMetadata
{ {

View file

@ -20,7 +20,7 @@ using System.Linq;
using System.Text.Json; using System.Text.Json;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using SerializableMigration; using SerializableMigration;
using SourceGeneration; using SerializationGenerator;
namespace SerializationSchemaGenerator namespace SerializationSchemaGenerator
{ {

View file

@ -26,7 +26,21 @@ namespace Server
public sealed class SerializableFieldAttribute : Attribute public sealed class SerializableFieldAttribute : Attribute
{ {
public int Order { get; } public int Order { get; }
public string PropertyGetter { get; }
public string? PropertySetter { get; }
public bool IsVirtual { get; }
public SerializableFieldAttribute(int order) => Order = order; public SerializableFieldAttribute(
int order,
string getter = "public",
string setter = "public",
bool isVirtual = false
)
{
Order = order;
PropertyGetter = getter;
PropertySetter = setter;
IsVirtual = isVirtual;
}
} }
} }

View file

@ -72,7 +72,4 @@
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="Migrations/*.v*.json" /> <AdditionalFiles Include="Migrations/*.v*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Migrations/*.v*.json" />
</ItemGroup>
</Project> </Project>

View file

@ -173,19 +173,18 @@ namespace Server.Engines.Events
} }
} }
public class ZombieSkeleton : BaseCreature [Serializable(0, false)]
public partial class ZombieSkeleton : BaseCreature
{ {
private const string _name = "Zombie Skeleton"; [SerializableField(0, "private", "private")]
private PlayerMobile _deadPlayer;
// TODO: Requires private modifier public override string DefaultName => _deadPlayer != null ? $"{_deadPlayer.Name}'s Zombie Skeleton" : "Zombie Skeleton";
private PlayerMobile m_DeadPlayer;
public ZombieSkeleton(PlayerMobile player = null) public ZombieSkeleton(PlayerMobile player = null)
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{ {
m_DeadPlayer = player; _deadPlayer = player;
Name = player != null ? $"{player.Name}'s {_name}" : _name;
Body = 0x93; Body = 0x93;
BaseSoundID = 0x1c3; BaseSoundID = 0x1c3;
@ -219,11 +218,6 @@ namespace Server.Engines.Events
VirtualArmor = 18; VirtualArmor = 18;
} }
public ZombieSkeleton(Serial serial)
: base(serial)
{
}
public override string CorpseName => "a rotting corpse"; public override string CorpseName => "a rotting corpse";
public override bool BleedImmune => true; public override bool BleedImmune => true;
@ -232,7 +226,7 @@ namespace Server.Engines.Events
public override void GenerateLoot() public override void GenerateLoot()
{ {
var deadPlayerExists = m_DeadPlayer?.Deleted == false; var deadPlayerExists = _deadPlayer?.Deleted == false;
PackItem( PackItem(
Utility.Random(deadPlayerExists ? 8 : 10) switch Utility.Random(deadPlayerExists ? 8 : 10) switch
@ -242,7 +236,7 @@ namespace Server.Engines.Events
2 => new Torso(), 2 => new Torso(),
3 => new Bone(), 3 => new Bone(),
4 => new RibCage(), 4 => new RibCage(),
9 => deadPlayerExists ? new PlayerBones(m_DeadPlayer.Name) : null, 9 => deadPlayerExists ? new PlayerBones(_deadPlayer.Name) : null,
_ => null // 5-8, 10 (50%) _ => null // 5-8, 10 (50%)
} }
); );
@ -252,26 +246,10 @@ namespace Server.Engines.Events
public override void OnDelete() public override void OnDelete()
{ {
if (m_DeadPlayer?.Deleted == false) if (_deadPlayer?.Deleted == false)
{ {
HalloweenHauntings.ReAnimated?.Remove(m_DeadPlayer); HalloweenHauntings.ReAnimated?.Remove(_deadPlayer);
} }
} }
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(m_DeadPlayer);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
m_DeadPlayer = reader.ReadEntity<PlayerMobile>();
}
} }
} }

View file

@ -0,0 +1,12 @@
{
"version": 0,
"type": "Server.Engines.Events.ZombieSkeleton",
"properties": [
{
"name": "DeadPlayer",
"type": "Server.Mobiles.PlayerMobile",
"rule": "SerializableInterfaceMigrationRule",
"ruleArguments": []
}
]
}