From 90aff7c9898496952a8c47c7db30989d180f32f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Fri, 31 Dec 2021 18:39:20 +0100 Subject: [PATCH] feat: add checking parameter method for the generator --- .../IParameterGenerator.cs | 8 +++ .../PacketContextListAttributeGenerator.cs | 21 ++++-- .../PacketGreedyIndexAttributeGenerator.cs | 18 +++-- .../PacketIndexAttributeGenerator.cs | 19 +++-- .../PacketListIndexAttributeGenerator.cs | 18 +++-- .../ConverterDeserializationGenerator.cs | 17 +---- .../PacketConverterGenerator.cs | 20 ++++-- .../ParameterChecker.cs | 72 +++++++++++++++++++ .../SourceGenerator.cs | 4 +- 9 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 Core/NosSmooth.PacketSerializersGenerator/ParameterChecker.cs diff --git a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/IParameterGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/IParameterGenerator.cs index ffefb51..0d0bfcf 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/IParameterGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/IParameterGenerator.cs @@ -23,6 +23,14 @@ namespace NosSmooth.PacketSerializersGenerator.AttributeGenerators /// Whether to handle this parameter. public bool ShouldHandle(ParameterInfo parameter); + /// + /// Checks the given parameter, returns an error if the parameter cannot be processed. + /// + /// The packet. + /// The parameter. + /// An error, if any. + public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter); + /// /// Generate part for the Serializer method to serialize the given parameter. /// diff --git a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketContextListAttributeGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketContextListAttributeGenerator.cs index 831620c..f8b6283 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketContextListAttributeGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketContextListAttributeGenerator.cs @@ -26,6 +26,18 @@ public class PacketContextListAttributeGenerator : IParameterGenerator public bool ShouldHandle(ParameterInfo parameter) => parameter.Attributes.Any(x => x.FullName == PacketListIndexAttributeFullName); + /// + public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter) + { + var error = ParameterChecker.CheckHasOneAttribute(packet, parameter); + if (error is not null) + { + return error; + } + + return ParameterChecker.CheckOptionalIsNullable(packet, parameter); + } + /// public IError? GenerateSerializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) { @@ -76,11 +88,7 @@ public class PacketContextListAttributeGenerator : IParameterGenerator // add optional if if (parameter.IsOptional()) { - var error = generator.StartOptionalCheck(parameter, packetInfo.Name); - if (error is not null) - { - return error; - } + generator.StartOptionalCheck(parameter, packetInfo.Name); } var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); @@ -96,7 +104,8 @@ public class PacketContextListAttributeGenerator : IParameterGenerator var innerSeparator = attribute.GetNamedValue("InnerSeparator", '.'); generator.PrepareLevel(innerSeparator); - generator.DeserializeAndCheck($"{packetInfo.Namespace}.{packetInfo.Name}", parameter, packetInfo.Parameters.IsLast); + generator.DeserializeAndCheck + ($"{packetInfo.Namespace}.{packetInfo.Name}", parameter, packetInfo.Parameters.IsLast); generator.RemovePreparedLevel(); generator.PopLevel(); if (!parameter.Nullable) diff --git a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketGreedyIndexAttributeGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketGreedyIndexAttributeGenerator.cs index 415195e..75a5a50 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketGreedyIndexAttributeGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketGreedyIndexAttributeGenerator.cs @@ -33,6 +33,18 @@ public class PacketGreedyIndexAttributeGenerator : IParameterGenerator public bool ShouldHandle(ParameterInfo parameter) => parameter.Attributes.Any(x => x.FullName == PacketIndexAttributeFullName); + /// + public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter) + { + var error = ParameterChecker.CheckHasOneAttribute(packet, parameter); + if (error is not null) + { + return error; + } + + return ParameterChecker.CheckOptionalIsNullable(packet, parameter); + } + /// public IError? GenerateSerializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) => _basicAttributeGenerator.GenerateSerializerPart(textWriter, packetInfo); @@ -50,11 +62,7 @@ public class PacketGreedyIndexAttributeGenerator : IParameterGenerator // add optional if if (parameter.IsOptional()) { - var error = generator.StartOptionalCheck(parameter, packetInfo.Name); - if (error is not null) - { - return error; - } + generator.StartOptionalCheck(parameter, packetInfo.Name); } var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); diff --git a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketIndexAttributeGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketIndexAttributeGenerator.cs index 985a24c..1602929 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketIndexAttributeGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketIndexAttributeGenerator.cs @@ -23,6 +23,18 @@ public class PacketIndexAttributeGenerator : IParameterGenerator public bool ShouldHandle(ParameterInfo parameter) => parameter.Attributes.Any(x => x.FullName == PacketIndexAttributeFullName); + /// + public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter) + { + var error = ParameterChecker.CheckHasOneAttribute(packet, parameter); + if (error is not null) + { + return error; + } + + return ParameterChecker.CheckOptionalIsNullable(packet, parameter); + } + /// public IError? GenerateSerializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) { @@ -85,11 +97,7 @@ public class PacketIndexAttributeGenerator : IParameterGenerator // add optional if if (parameter.IsOptional()) { - var error = generator.StartOptionalCheck(parameter, packetInfo.Name); - if (error is not null) - { - return error; - } + generator.StartOptionalCheck(parameter, packetInfo.Name); } var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); @@ -114,7 +122,6 @@ public class PacketIndexAttributeGenerator : IParameterGenerator } generator.AssignLocalVariable(parameter, false); - if (pushedLevel) { generator.ReadToLastToken(); diff --git a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketListIndexAttributeGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketListIndexAttributeGenerator.cs index 7058e71..edb26dc 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketListIndexAttributeGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/AttributeGenerators/PacketListIndexAttributeGenerator.cs @@ -28,6 +28,18 @@ public class PacketListIndexAttributeGenerator : IParameterGenerator public bool ShouldHandle(ParameterInfo parameter) => parameter.Attributes.Any(x => x.FullName == PacketListIndexAttributeFullName); + /// + public IError? CheckParameter(PacketInfo packet, ParameterInfo parameter) + { + var error = ParameterChecker.CheckHasOneAttribute(packet, parameter); + if (error is not null) + { + return error; + } + + return ParameterChecker.CheckOptionalIsNullable(packet, parameter); + } + /// public IError? GenerateSerializerPart(IndentedTextWriter textWriter, PacketInfo packetInfo) { @@ -80,11 +92,7 @@ public class PacketListIndexAttributeGenerator : IParameterGenerator // add optional if if (parameter.IsOptional()) { - var error = generator.StartOptionalCheck(parameter, packetInfo.Name); - if (error is not null) - { - return error; - } + generator.StartOptionalCheck(parameter, packetInfo.Name); } var afterSeparator = attribute.GetNamedValue("AfterSeparator", null); diff --git a/Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs index c22f858..87f1341 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs @@ -157,27 +157,12 @@ if ({resultVariableName}.Entity is null) {{ /// /// The parameter information. /// The name of the packet. - /// An error, if any. - public IError? StartOptionalCheck(ParameterInfo parameter, string packetName) + public void StartOptionalCheck(ParameterInfo parameter, string packetName) { - if (!parameter.Nullable) - { - return new DiagnosticError - ( - "SG0006", - "Optional parameters must be nullable", - "The parameter {0} in {1} has to be nullable, because it is optional.", - parameter.Parameter.SyntaxTree, - parameter.Parameter.FullSpan, - new List(new[] { parameter.Name, packetName }) - ); - } - // serialize this parameter only if we are not on the last token. _textWriter.WriteLine($"if (!(stringEnumerator.IsOnLastToken() ?? true))"); _textWriter.WriteLine("{"); _textWriter.Indent++; - return null; } /// diff --git a/Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs index a9c1413..b3134ff 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs @@ -136,10 +136,16 @@ private IResultError? CheckDeserializationResult(Result result, string pro { if (generator.ShouldHandle(parameter)) { - var result = generator.GenerateSerializerPart(textWriter, _packetInfo); - if (result is not null) + var checkError = generator.CheckParameter(_packetInfo, parameter); + if (checkError is not null) { - return result; + return checkError; + } + + var serializerError = generator.GenerateSerializerPart(textWriter, _packetInfo); + if (serializerError is not null) + { + return serializerError; } handled = true; @@ -192,7 +198,7 @@ private IResultError? CheckDeserializationResult(Result result, string pro { return new DiagnosticError ( - "SG0004", + "SGInd", "Same packet index", "There were two parameters of the same packet index {0} on property {1} in packet {2}, that is not supported.", parameter.Attributes.First().Attribute.SyntaxTree, @@ -214,6 +220,12 @@ private IResultError? CheckDeserializationResult(Result result, string pro { if (generator.ShouldHandle(parameter)) { + var checkError = generator.CheckParameter(_packetInfo, parameter); + if (checkError is not null) + { + return checkError; + } + var result = generator.GenerateDeserializerPart(textWriter, _packetInfo); if (result is not null) { diff --git a/Core/NosSmooth.PacketSerializersGenerator/ParameterChecker.cs b/Core/NosSmooth.PacketSerializersGenerator/ParameterChecker.cs new file mode 100644 index 0000000..5023421 --- /dev/null +++ b/Core/NosSmooth.PacketSerializersGenerator/ParameterChecker.cs @@ -0,0 +1,72 @@ +// +// ParameterChecker.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.PacketSerializersGenerator.Data; +using NosSmooth.PacketSerializersGenerator.Errors; +using NosSmooth.PacketSerializersGenerator.Extensions; + +namespace NosSmooth.PacketSerializersGenerator; + +/// +/// Helpers for checking packet parameters. +/// +public static class ParameterChecker +{ + /// + /// Checks that the given parameter has exactly one packet attribute. + /// + /// The packet. + /// The parameter. + /// An error, if any. + public static IError? CheckHasOneAttribute(PacketInfo packetInfo, ParameterInfo parameter) + { + if (parameter.Attributes.Count > 1) + { + return new DiagnosticError + ( + "SGAttr", + "Packet constructor parameter with multiple packet attributes", + "Found multiple packet attributes on parameter {0} in {1}. That is not supported for this type of packet attribute.", + parameter.Parameter.SyntaxTree, + parameter.Parameter.FullSpan, + new List + ( + new[] + { + parameter.Name, + packetInfo.Name + } + ) + ); + } + + return null; + } + + /// + /// Checks that the given parameter is nullable, if it is optional. + /// + /// The packet. + /// The parameter. + /// An error, if any. + public static IError? CheckOptionalIsNullable(PacketInfo packetInfo, ParameterInfo parameter) + { + if (parameter.IsOptional() && !parameter.Nullable) + { + return new DiagnosticError + ( + "SGNull", + "Optional parameters must be nullable", + "The parameter {0} in {1} has to be nullable, because it is optional.", + parameter.Parameter.SyntaxTree, + parameter.Parameter.FullSpan, + new List(new[] { parameter.Name, packetInfo.Name }) + ); + } + + return null; + } +} \ No newline at end of file diff --git a/Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs b/Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs index b9d8c18..4cece69 100644 --- a/Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs +++ b/Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs @@ -131,7 +131,7 @@ public class SourceGenerator : ISourceGenerator { return new DiagnosticError ( - "SG0001", + "SGConst", "Packet without constructor", "The packet class {0} does not have any constructors to use for packet serializer.", packetClass.SyntaxTree, @@ -219,7 +219,7 @@ public class SourceGenerator : ISourceGenerator { return new DiagnosticError ( - "SG0003", + "SGAttr", "Packet constructor parameter without packet attribute", "Could not find PacketIndexAttribute on {0} parameter in class {1}. Parameters without PacketIndexAttribute aren't allowed.", parameter.SyntaxTree, -- 2.48.1