private void AddArrayHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder methodBuilder, ListTypeDescriptor listTypeDescriptor, HashSet <string> processed, bool isNonNullable) { methodBuilder.AddParameter( ParameterBuilder.New() .SetType(listTypeDescriptor.ToEntityIdBuilder()) .SetName(ListParamName)); var listVarName = listTypeDescriptor.Name.WithLowerFirstChar() + "s"; if (!isNonNullable) { methodBuilder.AddCode(EnsureProperNullability(ListParamName, isNonNullable)); } methodBuilder.AddCode( AssignmentBuilder.New() .SetLefthandSide($"var {listVarName}") .SetRighthandSide( CodeBlockBuilder.New() .AddCode("new ") .AddCode(TypeNames.List) .AddCode("<") .AddCode( listTypeDescriptor.InnerType.ToBuilder() .SkipTrailingSpace()) .AddCode(">") .AddCode("()"))); methodBuilder.AddEmptyLine(); var loopbuilder = ForEachBuilder.New() .SetLoopHeader( CodeBlockBuilder.New() .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder()) .AddCode($"child in {ListParamName}")) .AddCode( MethodCallBuilder.New() .SetPrefix($"{listVarName}.") .SetMethodName("Add") .AddArgument( BuildMapMethodCall( listTypeDescriptor.InnerType, "child"))); methodBuilder.AddCode(loopbuilder); methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"return {listVarName};"); AddMapMethod( listVarName, listTypeDescriptor.InnerType, classBuilder, constructorBuilder, processed); }
private void AddEntityHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder method, ComplexTypeDescriptor complexTypeDescriptor, HashSet <string> processed, bool isNonNullable) { method.AddParameter( EntityIdParamName, x => x.SetType(TypeNames.EntityId.MakeNullable(!isNonNullable))); if (!isNonNullable) { method.AddCode( EnsureProperNullability( EntityIdParamName, isNonNullable)); } if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) { foreach (ObjectTypeDescriptor implementee in interfaceTypeDescriptor.ImplementedBy) { NameString dataMapperName = CreateEntityMapperName( implementee.RuntimeType.Name, implementee.Name); if (processed.Add(dataMapperName)) { var dataMapperType = TypeNames.IEntityMapper.WithGeneric( CreateEntityTypeName(implementee.Name), implementee.RuntimeType.Name); AddConstructorAssignedField( dataMapperType, GetFieldName(dataMapperName), classBuilder, constructorBuilder); } method.AddCode(GenerateEntityHandlerIfClause(implementee, isNonNullable)); } } method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException)); }
private void GenerateIfForEachImplementedBy( MethodBuilder method, ComplexTypeDescriptor complexTypeDescriptor, Func <ObjectTypeDescriptor, IfBuilder> generator) { if (!(complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) || !interfaceTypeDescriptor.ImplementedBy.Any()) { return; } var ifChain = generator(interfaceTypeDescriptor.ImplementedBy.First()); foreach (ObjectTypeDescriptor objectTypeDescriptor in interfaceTypeDescriptor.ImplementedBy.Skip(1)) { ifChain.AddIfElse( generator(objectTypeDescriptor) .SkipIndents()); } ifChain.AddElse( CodeInlineBuilder.New() .SetText($"throw new {TypeNames.NotSupportedException}();")); method.AddCode(ifChain); }
private void AddDataTypeDeserializerMethod( ClassBuilder classBuilder, MethodBuilder methodBuilder, ComplexTypeDescriptor complexTypeDescriptor, HashSet <string> processed) { if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) { AddInterfaceDataTypeDeserializerToMethod(methodBuilder, interfaceTypeDescriptor); } else { MethodCallBuilder returnStatement = MethodCallBuilder .New() .SetReturn() .SetNew() .SetMethodName(complexTypeDescriptor.Name); foreach (PropertyDescriptor property in complexTypeDescriptor.Properties) { returnStatement.AddArgument(BuildUpdateMethodCall(property)); } methodBuilder.AddCode(returnStatement); } AddRequiredDeserializeMethods(complexTypeDescriptor, classBuilder, processed); }
public static CodeBlockBuilder AddBody(this MethodBuilder method) { var code = CodeBlockBuilder.New(); method.AddCode(code); return(code); }
private void AddScalarTypeDeserializerMethod( MethodBuilder methodBuilder, ILeafTypeDescriptor namedType) { string deserializeMethod = namedType.SerializationType.ToString() switch { TypeNames.String => nameof(JsonElement.GetString), TypeNames.Uri => nameof(JsonElement.GetString), TypeNames.Byte => nameof(JsonElement.GetByte), TypeNames.ByteArray => nameof(JsonElement.GetBytesFromBase64), TypeNames.Int16 => nameof(JsonElement.GetInt16), TypeNames.Int32 => nameof(JsonElement.GetInt32), TypeNames.Int64 => nameof(JsonElement.GetInt64), TypeNames.UInt16 => nameof(JsonElement.GetUInt16), TypeNames.UInt32 => nameof(JsonElement.GetUInt32), TypeNames.UInt64 => nameof(JsonElement.GetUInt64), TypeNames.Single => nameof(JsonElement.GetSingle), TypeNames.Double => nameof(JsonElement.GetDouble), TypeNames.Decimal => nameof(JsonElement.GetDecimal), TypeNames.DateTimeOffset => nameof(JsonElement.GetString), TypeNames.DateTime => nameof(JsonElement.GetString), TypeNames.TimeSpan => nameof(JsonElement.GetString), TypeNames.Boolean => nameof(JsonElement.GetBoolean), TypeNames.Guid => nameof(JsonElement.GetGuid), _ => throw new NotSupportedException("Serialization format not supported.") }; methodBuilder.AddCode( $"return {GetFieldName(namedType.Name)}Parser.Parse({_objParamName}.Value" + $".{deserializeMethod}()!);"); } }
private void AddScalarTypeDeserializerMethod( MethodBuilder methodBuilder, NamedTypeDescriptor namedType) { string deserializeMethod = namedType.GraphQLTypeName?.Value switch { String => nameof(JsonElement.GetString), ID => nameof(JsonElement.GetString), Url => nameof(JsonElement.GetString), Uuid => nameof(JsonElement.GetString), DateTime => nameof(JsonElement.GetString), Date => nameof(JsonElement.GetString), TimeSpan => nameof(JsonElement.GetString), Boolean => nameof(JsonElement.GetBoolean), Byte => nameof(JsonElement.GetByte), Short => nameof(JsonElement.GetInt16), Int => nameof(JsonElement.GetInt32), Long => nameof(JsonElement.GetInt64), Float => nameof(JsonElement.GetDouble), Decimal => nameof(JsonElement.GetDecimal), ByteArray => nameof(JsonElement.GetBytesFromBase64), _ => "Get" + (namedType.SerializationType?.Split('.').Last() ?? namedType.Name.WithCapitalFirstChar()) }; methodBuilder.AddCode( $"return {namedType.Name.ToFieldName()}Parser.Parse({_objParamName}.Value" + $".{deserializeMethod}()!);"); } }
private void AddComplexDataHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder method, ComplexTypeDescriptor complexTypeDescriptor, HashSet <string> processed, bool isNonNullable) { if (complexTypeDescriptor.ParentRuntimeType is null) { throw new InvalidOperationException(); } method.AddParameter( ParameterBuilder.New() .SetType(complexTypeDescriptor.ParentRuntimeType.ToString()) .SetName(_dataParameterName)); if (!isNonNullable) { method.AddCode( EnsureProperNullability( _dataParameterName, isNonNullable)); } var variableName = "returnValue"; method.AddCode($"{complexTypeDescriptor.RuntimeType.Name} {variableName} = default!;"); method.AddEmptyLine(); GenerateIfForEachImplementedBy( method, complexTypeDescriptor, o => GenerateComplexDataInterfaceIfClause(o, variableName)); method.AddCode($"return {variableName};"); AddRequiredMapMethods( _dataParameterName, complexTypeDescriptor, classBuilder, constructorBuilder, processed); }
private void AddInterfaceDataTypeDeserializerToMethod( MethodBuilder methodBuilder, InterfaceTypeDescriptor interfaceTypeDescriptor) { methodBuilder.AddCode( AssignmentBuilder .New() .SetLefthandSide($"var {_typename}") .SetRighthandSide(MethodCallBuilder .Inline() .SetMethodName( _obj, nameof(Nullable <EntityId> .Value), nameof(JsonElement.GetProperty)) .AddArgument(__typename.AsStringToken()) .Chain(x => x.SetMethodName(nameof(JsonElement.GetString))))); // If the type is an interface foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy) { MethodCallBuilder returnStatement = MethodCallBuilder .New() .SetReturn() .SetNew() .SetMethodName( $"{concreteType.RuntimeType.Namespace}.State." + CreateDataTypeName(concreteType.Name)) .AddArgument("typename"); foreach (PropertyDescriptor property in concreteType.Properties) { returnStatement.AddArgument( CodeBlockBuilder .New() .AddCode($"{GetParameterName(property.Name)}: ") .AddCode(BuildUpdateMethodCall(property))); } IfBuilder ifStatement = IfBuilder .New() .SetCondition( $"typename?.Equals(\"{concreteType.Name}\", " + $"{TypeNames.OrdinalStringComparison}) ?? false") .AddCode(returnStatement); methodBuilder .AddEmptyLine() .AddCode(ifStatement); } methodBuilder .AddEmptyLine() .AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException)); }
private void AddArrayHandler( ClassBuilder classBuilder, MethodBuilder methodBuilder, ListTypeDescriptor listTypeDescriptor, HashSet <string> processed) { var listVarName = listTypeDescriptor.Name.WithLowerFirstChar() + "s"; methodBuilder.AddCode( AssignmentBuilder.New() .SetLefthandSide($"var {listVarName}") .SetRighthandSide( CodeBlockBuilder.New() .AddCode("new ") .AddCode(TypeNames.List) .AddCode("<") .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder() .SkipTrailingSpace()) .AddCode(">") .AddCode("()") )); methodBuilder.AddEmptyLine(); methodBuilder.AddCode( ForEachBuilder.New() .SetLoopHeader( $"{TypeNames.JsonElement} child in {_objParamName}.Value.EnumerateArray()") .AddCode( MethodCallBuilder.New() .SetPrefix($"{listVarName}.") .SetMethodName("Add") .AddArgument( BuildUpdateMethodCall(listTypeDescriptor.InnerType, "child")))); methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"return {listVarName};"); AddDeserializeMethod(listTypeDescriptor.InnerType, classBuilder, processed); }
private void AddDataHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder method, ComplexTypeDescriptor namedTypeDescriptor, HashSet <string> processed, bool isNonNullable) { method.AddParameter( _dataParameterName, x => x.SetType(namedTypeDescriptor.ParentRuntimeType !.ToString())); if (!isNonNullable) { method.AddCode(EnsureProperNullability(_dataParameterName, isNonNullable)); } var variableName = "returnValue"; method.AddCode($"{namedTypeDescriptor.RuntimeType.Name} {variableName} = default!;"); method.AddEmptyLine(); GenerateIfForEachImplementedBy( method, namedTypeDescriptor, o => GenerateDataInterfaceIfClause(o, isNonNullable, variableName)); method.AddCode($"return {variableName};"); AddRequiredMapMethods( _dataParameterName, namedTypeDescriptor, classBuilder, constructorBuilder, processed); }
private void AddArrayHandler( ClassBuilder classBuilder, MethodBuilder methodBuilder, ListTypeDescriptor listTypeDescriptor, HashSet <string> processed) { var listVarName = GetParameterName(listTypeDescriptor.Name) + "s"; methodBuilder .AddCode( AssignmentBuilder .New() .SetLefthandSide($"var {listVarName}") .SetRighthandSide( CodeBlockBuilder .New() .AddCode("new ") .AddCode(TypeNames.List) .AddCode("<") .AddCode( listTypeDescriptor.InnerType .ToEntityIdBuilder() .SkipTrailingSpace()) .AddCode(">") .AddCode("()"))) .AddEmptyLine() .AddCode( ForEachBuilder .New() .SetLoopHeader( $"{TypeNames.JsonElement} {_child} in {_obj}.Value.EnumerateArray()") .AddCode( MethodCallBuilder .New() .SetMethodName(listVarName, nameof(List <object> .Add)) .AddArgument( BuildUpdateMethodCall( listTypeDescriptor.InnerType, CodeInlineBuilder.From(_child))))) .AddEmptyLine() .AddCode($"return {listVarName};"); AddDeserializeMethod(listTypeDescriptor.InnerType, classBuilder, processed); }
private void AddDeserializeMethod( ITypeDescriptor typeReference, ClassBuilder classBuilder, HashSet <string> processed) { string methodName = DeserializerMethodNameFromTypeName(typeReference); if (processed.Add(methodName)) { MethodBuilder methodBuilder = classBuilder .AddMethod() .SetPrivate() .SetReturnType(typeReference.ToEntityIdBuilder()) .SetName(methodName); methodBuilder .AddParameter(_obj) .SetType(TypeNames.JsonElement.MakeNullable()); if (typeReference.IsEntityType() || typeReference.ContainsEntity()) { methodBuilder .AddParameter(_entityIds) .SetType(TypeNames.ISet.WithGeneric(TypeNames.EntityId)); } IfBuilder jsonElementNullCheck = IfBuilder .New() .SetCondition($"!{_obj}.HasValue") .AddCode( typeReference.IsNonNullableType() ? ExceptionBuilder.New(TypeNames.ArgumentNullException) : CodeLineBuilder.From("return null;")); methodBuilder .AddCode(jsonElementNullCheck) .AddEmptyLine(); AddDeserializeMethodBody(classBuilder, methodBuilder, typeReference, processed); } }
private void AddScalarTypeDeserializerMethod( MethodBuilder methodBuilder, ILeafTypeDescriptor namedType) { string deserializeMethod = namedType.SerializationType.ToString() switch { TypeNames.String => nameof(JsonElement.GetString), TypeNames.Uri => nameof(JsonElement.GetString), TypeNames.Byte => nameof(JsonElement.GetByte), TypeNames.ByteArray => nameof(JsonElement.GetBytesFromBase64), TypeNames.Int16 => nameof(JsonElement.GetInt16), TypeNames.Int32 => nameof(JsonElement.GetInt32), TypeNames.Int64 => nameof(JsonElement.GetInt64), TypeNames.UInt16 => nameof(JsonElement.GetUInt16), TypeNames.UInt32 => nameof(JsonElement.GetUInt32), TypeNames.UInt64 => nameof(JsonElement.GetUInt64), TypeNames.Single => nameof(JsonElement.GetSingle), TypeNames.Double => nameof(JsonElement.GetDouble), TypeNames.Decimal => nameof(JsonElement.GetDecimal), TypeNames.DateTimeOffset => nameof(JsonElement.GetString), TypeNames.DateTime => nameof(JsonElement.GetString), TypeNames.TimeSpan => nameof(JsonElement.GetString), TypeNames.Boolean => nameof(JsonElement.GetBoolean), TypeNames.Guid => nameof(JsonElement.GetGuid), _ => throw new NotSupportedException("Serialization format not supported.") }; methodBuilder.AddCode( MethodCallBuilder .New() .SetReturn() .SetMethodName( GetFieldName(namedType.Name) + "Parser", nameof(ILeafValueParser <object, object> .Parse)) .AddArgument(MethodCallBuilder .Inline() .SetMethodName(_obj, nameof(Nullable <JsonElement> .Value), deserializeMethod) .SetNullForgiving())); } }
private void AddDataHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder method, NamedTypeDescriptor namedTypeDescriptor, HashSet <string> processed, bool isNonNullable) { method.AddParameter( ParameterBuilder.New() .SetType( $"global::{namedTypeDescriptor.Namespace}.State." + DataTypeNameFromTypeName(namedTypeDescriptor.GraphQLTypeName)) .SetName(DataParamName)); if (!isNonNullable) { method.AddCode( EnsureProperNullability( DataParamName, isNonNullable)); } var variableName = "returnValue"; method.AddCode($"{namedTypeDescriptor.Name} {variableName} = default!;"); method.AddEmptyLine(); if (namedTypeDescriptor.ImplementedBy.Any()) { var ifChain = InterfaceImplementeeIf(namedTypeDescriptor.ImplementedBy[0]); foreach (NamedTypeDescriptor interfaceImplementee in namedTypeDescriptor.ImplementedBy.Skip(1)) { var singleIf = InterfaceImplementeeIf(interfaceImplementee).SkipIndents(); ifChain.AddIfElse(singleIf); } ifChain.AddElse( CodeInlineBuilder.New() .SetText($"throw new {TypeNames.NotSupportedException}();")); method.AddCode(ifChain); } IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee) { var ifCorrectType = IfBuilder.New(); if (isNonNullable) { ifCorrectType.SetCondition( $"{DataParamName}.__typename.Equals(\"" + $"{interfaceImplementee.GraphQLTypeName}\", " + $"{TypeNames.OrdinalStringComparisson})"); } else { ifCorrectType.SetCondition( $"{DataParamName}?.__typename.Equals(\"" + $"{interfaceImplementee.GraphQLTypeName}\", " + $"{TypeNames.OrdinalStringComparisson}) ?? false"); } var constructorCall = MethodCallBuilder.New() .SetPrefix($"{variableName} = new ") .SetMethodName(interfaceImplementee.Name); foreach (PropertyDescriptor prop in interfaceImplementee.Properties) { var propAccess = $"{DataParamName}.{prop.Name}"; if (prop.Type.IsEntityType()) { constructorCall.AddArgument( BuildMapMethodCall( DataParamName, prop, true)); } else { constructorCall.AddArgument( $"{propAccess} ?? throw new {TypeNames.ArgumentNullException}()"); } } ifCorrectType.AddCode(constructorCall); return(ifCorrectType); } method.AddCode($"return {variableName};"); AddRequiredMapMethods( DataParamName, namedTypeDescriptor, classBuilder, constructorBuilder, processed); }
private void AddUpdateEntityMethod( ClassBuilder classBuilder, MethodBuilder methodBuilder, INamedTypeDescriptor namedTypeDescriptor, HashSet <string> processed) { var entityIdVarName = "entityId"; methodBuilder.AddCode( AssignmentBuilder.New() .SetLefthandSide( CodeBlockBuilder.New() .AddCode(TypeNames.EntityId) .AddCode($" {entityIdVarName}")) .SetRighthandSide($"{_extractIdFieldName}({_objParamName}.Value)")); methodBuilder.AddCode($"{_entityIdsParam}.Add({entityIdVarName});"); methodBuilder.AddEmptyLine(); var entityVarName = "entity"; if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) { // If the type is an interface foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy) { methodBuilder.AddEmptyLine(); var ifStatement = IfBuilder.New() .SetCondition( $"entityId.Name.Equals(\"{concreteType.Name}\", " + $"{TypeNames.OrdinalStringComparison})"); var entityTypeName = CreateEntityTypeName(concreteType.Name); WriteEntityLoader( ifStatement, entityTypeName, entityVarName, entityIdVarName); WritePropertyAssignments( ifStatement, concreteType.Properties, entityVarName); ifStatement.AddEmptyLine(); ifStatement.AddCode($"return {entityIdVarName};"); methodBuilder.AddCode(ifStatement); } methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();"); } else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor) { WriteEntityLoader( methodBuilder, CreateEntityTypeName(namedTypeDescriptor.Name), entityVarName, entityIdVarName); WritePropertyAssignments( methodBuilder, complexTypeDescriptor.Properties, entityVarName); methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"return {entityIdVarName};"); } AddRequiredDeserializeMethods( namedTypeDescriptor, classBuilder, processed); }
protected override void Generate( CodeWriter writer, ITypeDescriptor typeDescriptor, out string fileName) { var(classBuilder, constructorBuilder) = CreateClassBuilder(false); NamedTypeDescriptor descriptor = (NamedTypeDescriptor)typeDescriptor.NamedType(); // Setup class fileName = descriptor.ExtractMapperName(); classBuilder .AddImplements( TypeNames.IEntityMapper .WithGeneric(descriptor.ExtractTypeName(), descriptor.Name)) .SetName(fileName); constructorBuilder.SetTypeName(descriptor.Name); if (descriptor.ContainsEntity()) { AddConstructorAssignedField( TypeNames.IEntityStore, StoreFieldName, classBuilder, constructorBuilder); } // Define map method MethodBuilder mapMethod = MethodBuilder.New() .SetName(_mapMethodName) .SetAccessModifier(AccessModifier.Public) .SetReturnType(descriptor.Name) .AddParameter( ParameterBuilder.New() .SetType( descriptor.Kind == TypeKind.EntityType ? EntityTypeNameFromGraphQLTypeName(descriptor.GraphQLTypeName) : descriptor.Name) .SetName(_entityParamName)); var constructorCall = MethodCallBuilder .New() .SetMethodName($"return new {descriptor.Name}"); if (typeDescriptor is NamedTypeDescriptor namedTypeDescriptor) { foreach (PropertyDescriptor property in namedTypeDescriptor.Properties) { constructorCall.AddArgument(BuildMapMethodCall(_entityParamName, property)); } } mapMethod.AddCode(constructorCall); if (constructorBuilder.HasParameters()) { classBuilder.AddConstructor(constructorBuilder); } classBuilder.AddMethod(mapMethod); var processed = new HashSet <string>(); AddRequiredMapMethods( _entityParamName, descriptor, classBuilder, constructorBuilder, processed); CodeFileBuilder .New() .SetNamespace(descriptor.Namespace) .AddType(classBuilder) .Build(writer); }
private void AddDataTypeDeserializerMethod( ClassBuilder classBuilder, MethodBuilder methodBuilder, NamedTypeDescriptor namedTypeDescriptor, HashSet <string> processed) { if (namedTypeDescriptor.IsInterface) { methodBuilder.AddCode( "var typename = obj.Value.GetProperty(\"__typename\").GetString();"); // If the type is an interface foreach (NamedTypeDescriptor concreteType in namedTypeDescriptor.ImplementedBy) { methodBuilder.AddEmptyLine(); var ifStatement = IfBuilder.New() .SetCondition( $"typename?.Equals(\"{concreteType.GraphQLTypeName}\", " + $"{TypeNames.OrdinalStringComparisson}) ?? false"); var dataTypeName = $"global::{concreteType.Namespace}.State." + DataTypeNameFromTypeName(concreteType.GraphQLTypeName); var returnStatement = MethodCallBuilder.New() .SetPrefix("return new ") .SetMethodName(dataTypeName); returnStatement.AddArgument("typename"); foreach (PropertyDescriptor property in concreteType.Properties) { returnStatement.AddArgument( CodeBlockBuilder.New() .AddCode($"{property.Name.WithLowerFirstChar()}: ") .AddCode(BuildUpdateMethodCall(property))); } ifStatement.AddCode(returnStatement); methodBuilder.AddCode(ifStatement); } methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();"); } else { var returnStatement = MethodCallBuilder.New() .SetPrefix("return new ") .SetMethodName(namedTypeDescriptor.Name); foreach (PropertyDescriptor property in namedTypeDescriptor.Properties) { returnStatement.AddArgument(BuildUpdateMethodCall(property)); } methodBuilder.AddCode(returnStatement); } AddRequiredDeserializeMethods( namedTypeDescriptor, classBuilder, processed); }
private void AddEntityHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder method, NamedTypeDescriptor namedTypeDescriptor, HashSet <string> processed, bool isNonNullable) { var nullabilityAdditive = "?"; if (isNonNullable) { nullabilityAdditive = ""; } method.AddParameter( ParameterBuilder.New() .SetType(TypeNames.EntityId + nullabilityAdditive) .SetName(EntityIdParamName)); if (!isNonNullable) { method.AddCode( EnsureProperNullability( EntityIdParamName, isNonNullable)); } foreach (NamedTypeDescriptor implementee in namedTypeDescriptor.ImplementedBy) { var dataMapperName = EntityMapperNameFromGraphQLTypeName( implementee.Name, implementee.GraphQLTypeName); if (processed.Add(dataMapperName)) { var dataMapperType = $"{TypeNames.IEntityMapper}<" + $"{EntityTypeNameFromGraphQLTypeName(implementee.GraphQLTypeName)}, " + $"{implementee.Name}>"; AddConstructorAssignedField( dataMapperType, dataMapperName.ToFieldName(), classBuilder, constructorBuilder); } } foreach (NamedTypeDescriptor interfaceImplementee in namedTypeDescriptor.ImplementedBy) { method.AddCode(InterfaceImplementeeIf(interfaceImplementee)); } method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException)); IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee) { var dataMapperName = EntityMapperNameFromGraphQLTypeName( interfaceImplementee.Name, interfaceImplementee.GraphQLTypeName) .ToFieldName(); var ifCorrectType = IfBuilder.New(); if (isNonNullable) { ifCorrectType.SetCondition( $"{EntityIdParamName}.Name.Equals(\"" + $"{interfaceImplementee.GraphQLTypeName}\", " + $"{TypeNames.OrdinalStringComparisson})"); } else { ifCorrectType.SetCondition( $"{EntityIdParamName}.Value.Name.Equals(\"" + $"{interfaceImplementee.GraphQLTypeName}\", " + $"{TypeNames.OrdinalStringComparisson})"); } MethodCallBuilder constructorCall = MethodCallBuilder.New() .SetPrefix($"return {dataMapperName}.") .SetWrapArguments() .SetMethodName(nameof(IEntityMapper <object, object> .Map)); MethodCallBuilder argument = MethodCallBuilder.New() .SetMethodName($"{StoreFieldName}.{nameof(IEntityStore.GetEntity)}") .SetDetermineStatement(false) .AddGeneric( EntityTypeNameFromGraphQLTypeName(interfaceImplementee.GraphQLTypeName)) .AddArgument(isNonNullable ? EntityIdParamName : $"{EntityIdParamName}.Value"); constructorCall.AddArgument( NullCheckBuilder.New() .SetDetermineStatement(false) .SetCondition(argument) .SetCode(ExceptionBuilder .New(TypeNames.GraphQLClientException) .SetDetermineStatement(false))); method.AddEmptyLine(); ifCorrectType.AddCode(constructorCall); return(ifCorrectType); } }
private void AddUpdateEntityMethod( ClassBuilder classBuilder, MethodBuilder methodBuilder, INamedTypeDescriptor namedTypeDescriptor, HashSet <string> processed) { methodBuilder.AddCode( AssignmentBuilder .New() .SetLefthandSide($"{TypeNames.EntityId} {_entityId}") .SetRighthandSide( MethodCallBuilder .Inline() .SetMethodName(_extractId) .AddArgument($"{_obj}.{nameof(Nullable<EntityId>.Value)}"))); methodBuilder.AddCode( MethodCallBuilder .New() .SetMethodName(_entityIds, nameof(List <object> .Add)) .AddArgument(_entityId)); methodBuilder.AddEmptyLine(); if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) { // If the type is an interface foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy) { IfBuilder ifStatement = IfBuilder .New() .SetCondition( MethodCallBuilder .Inline() .SetMethodName( _entityId, nameof(EntityId.Name), nameof(string.Equals)) .AddArgument(concreteType.Name.AsStringToken()) .AddArgument(TypeNames.OrdinalStringComparison)); var entityTypeName = CreateEntityTypeName(concreteType.Name); WriteEntityLoader( ifStatement, entityTypeName); WritePropertyAssignments( ifStatement, concreteType.Properties); ifStatement .AddEmptyLine() .AddCode($"return {_entityId};"); methodBuilder .AddEmptyLine() .AddCode(ifStatement); } methodBuilder.AddEmptyLine(); methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException)); } else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor) { WriteEntityLoader(methodBuilder, CreateEntityTypeName(namedTypeDescriptor.Name)); WritePropertyAssignments(methodBuilder, complexTypeDescriptor.Properties); methodBuilder.AddEmptyLine(); methodBuilder.AddCode($"return {_entityId};"); } AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, processed); }
private void AddArrayHandler( ClassBuilder classBuilder, ConstructorBuilder constructorBuilder, MethodBuilder methodBuilder, ListTypeDescriptor listTypeDescriptor, HashSet <string> processed, bool isNonNullable) { methodBuilder .AddParameter(_list) .SetType(listTypeDescriptor.ToEntityIdBuilder()); var listVarName = GetParameterName(listTypeDescriptor.Name) + "s"; if (!isNonNullable) { methodBuilder.AddCode(EnsureProperNullability(_list, isNonNullable)); } methodBuilder.AddCode( AssignmentBuilder .New() .SetLefthandSide($"var {listVarName}") .SetRighthandSide( CodeBlockBuilder .New() .AddCode("new ") .AddCode(TypeNames.List) .AddCode("<") .AddCode(listTypeDescriptor.InnerType.ToBuilder().SkipTrailingSpace()) .AddCode(">") .AddCode("()"))); methodBuilder.AddEmptyLine(); ForEachBuilder forEachBuilder = ForEachBuilder .New() .SetLoopHeader( CodeBlockBuilder .New() .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder()) .AddCode($"{_child} in {_list}")) .AddCode( MethodCallBuilder .New() .SetMethodName(listVarName, nameof(List <object> .Add)) .AddArgument(MethodCallBuilder .Inline() .SetMethodName(MapMethodNameFromTypeName(listTypeDescriptor.InnerType)) .AddArgument(_child))); methodBuilder .AddCode(forEachBuilder) .AddEmptyLine() .AddCode($"return {listVarName};"); AddMapMethod( listVarName, listTypeDescriptor.InnerType, classBuilder, constructorBuilder, processed); }
protected override void Generate( CodeWriter writer, ITypeDescriptor typeDescriptor, out string fileName) { var(classBuilder, constructorBuilder) = CreateClassBuilder(false); ComplexTypeDescriptor descriptor = typeDescriptor as ComplexTypeDescriptor ?? throw new InvalidOperationException( "A result entity mapper can only be generated for complex types"); // Setup class fileName = descriptor.ExtractMapperName(); classBuilder .AddImplements( TypeNames.IEntityMapper .WithGeneric(descriptor.ExtractTypeName(), descriptor.RuntimeType.Name)) .SetName(fileName); constructorBuilder.SetTypeName(descriptor.Name); if (descriptor.ContainsEntity()) { AddConstructorAssignedField( TypeNames.IEntityStore, StoreFieldName, classBuilder, constructorBuilder); } // Define map method MethodBuilder mapMethod = MethodBuilder.New() .SetName(_mapMethodName) .SetAccessModifier(AccessModifier.Public) .SetReturnType(descriptor.RuntimeType.Name) .AddParameter( ParameterBuilder.New() .SetType( descriptor.Kind == TypeKind.EntityType ? CreateEntityTypeName(descriptor.Name) : descriptor.Name) .SetName(_entityParamName)); var constructorCall = MethodCallBuilder .New() .SetMethodName($"return new {descriptor.RuntimeType.Name}"); if (typeDescriptor is ComplexTypeDescriptor complexTypeDescriptor) { foreach (PropertyDescriptor property in complexTypeDescriptor.Properties) { constructorCall.AddArgument(BuildMapMethodCall(_entityParamName, property)); } } mapMethod.AddCode(constructorCall); if (constructorBuilder.HasParameters()) { classBuilder.AddConstructor(constructorBuilder); } classBuilder.AddMethod(mapMethod); AddRequiredMapMethods( _entityParamName, descriptor, classBuilder, constructorBuilder, new HashSet <string>()); CodeFileBuilder .New() .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
private void AddBuildDataMethod( InterfaceTypeDescriptor resultNamedType, ClassBuilder classBuilder) { var concreteType = CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name); MethodBuilder buildDataMethod = classBuilder .AddMethod() .SetPrivate() .SetName("BuildData") .SetReturnType($"({resultNamedType.RuntimeType.Name}, {concreteType})") .AddParameter(_obj, x => x.SetType(TypeNames.JsonElement)) .AddCode( AssignmentBuilder .New() .SetLefthandSide($"using {TypeNames.IEntityUpdateSession} {_session}") .SetRighthandSide( MethodCallBuilder .Inline() .SetMethodName(_entityStore, nameof(IEntityStore.BeginUpdate)))) .AddCode( AssignmentBuilder .New() .SetLefthandSide($"var {_entityIds}") .SetRighthandSide(MethodCallBuilder .Inline() .SetNew() .SetMethodName(TypeNames.HashSet) .AddGeneric(TypeNames.EntityId))) .AddEmptyLine(); foreach (PropertyDescriptor property in resultNamedType.Properties.Where(prop => prop.Type.IsEntityType())) { buildDataMethod.AddCode( AssignmentBuilder .New() .SetLefthandSide(CodeBlockBuilder .New() .AddCode(property.Type.ToEntityIdBuilder()) .AddCode($"{GetParameterName(property.Name)}Id")) .SetRighthandSide(BuildUpdateMethodCall(property))); } buildDataMethod .AddEmptyLine() .AddCode( AssignmentBuilder .New() .SetLefthandSide($"var {_resultInfo}") .SetRighthandSide( CreateResultInfoMethodCall(resultNamedType, concreteType))) .AddEmptyLine() .AddCode( TupleBuilder .Inline() .SetDetermineStatement(true) .SetReturn() .AddMember(MethodCallBuilder .Inline() .SetMethodName( _resultDataFactory, nameof(IOperationResultDataFactory <object> .Create)) .AddArgument(_resultInfo)) .AddMember(_resultInfo)); }