protected override void Generate( CodeWriter writer, ITypeDescriptor typeDescriptor, out string fileName) { ComplexTypeDescriptor descriptor = typeDescriptor as ComplexTypeDescriptor ?? throw new InvalidOperationException( "A result data factory can only be generated for complex types"); var(classBuilder, constructorBuilder) = CreateClassBuilder(); fileName = CreateResultFactoryName(descriptor.RuntimeType.Name); classBuilder .SetName(fileName) .AddImplements( // TODO: This should be descriptor.RuntimeType! $"{TypeNames.IOperationResultDataFactory}<{descriptor.RuntimeType.Name}>"); constructorBuilder .SetTypeName(descriptor.Name) .SetAccessModifier(AccessModifier.Public); AddConstructorAssignedField( TypeNames.IEntityStore, StoreParamName, classBuilder, constructorBuilder); var createMethod = MethodBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetName("Create") .SetReturnType(descriptor.RuntimeType.Name) .AddParameter("dataInfo", b => b.SetType(TypeNames.IOperationResultDataInfo)); var returnStatement = MethodCallBuilder.New() .SetPrefix("return new ") .SetMethodName(descriptor.RuntimeType.Name); var ifHasCorrectType = IfBuilder.New() .SetCondition( $"dataInfo is {CreateResultInfoName(descriptor.RuntimeType.Name)} info"); foreach (PropertyDescriptor property in descriptor.Properties) { returnStatement.AddArgument( BuildMapMethodCall( "info", property)); } ifHasCorrectType.AddCode(returnStatement); createMethod.AddCode(ifHasCorrectType); createMethod.AddEmptyLine(); createMethod.AddCode( $"throw new {TypeNames.ArgumentException}(\"" + $"{CreateResultInfoName(descriptor.RuntimeType.Name)} expected.\");"); classBuilder.AddMethod(createMethod); var processed = new HashSet <string>(); AddRequiredMapMethods( "info", descriptor, classBuilder, constructorBuilder, processed, true); CodeFileBuilder .New() .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
protected override void Generate( CodeWriter writer, ResultBuilderDescriptor resultBuilderDescriptor, out string fileName) { InterfaceTypeDescriptor resultTypeDescriptor = resultBuilderDescriptor.ResultNamedType as InterfaceTypeDescriptor ?? throw new InvalidOperationException( "A result type can only be generated for complex types"); fileName = resultBuilderDescriptor.RuntimeType.Name; ClassBuilder classBuilder = ClassBuilder .New() .SetName(fileName); ConstructorBuilder constructorBuilder = classBuilder .AddConstructor() .SetTypeName(fileName); classBuilder .AddImplements( TypeNames.IOperationResultBuilder.WithGeneric( TypeNames.JsonDocument, resultTypeDescriptor.RuntimeType.Name)); AddConstructorAssignedField( TypeNames.IEntityStore, _entityStore, classBuilder, constructorBuilder); AddConstructorAssignedField( TypeNames.Func.WithGeneric(TypeNames.JsonElement, TypeNames.EntityId), _extractId, classBuilder, constructorBuilder); AddConstructorAssignedField( TypeNames.IOperationResultDataFactory .WithGeneric(resultTypeDescriptor.RuntimeType.Name), _resultDataFactory, classBuilder, constructorBuilder); constructorBuilder .AddParameter(_serializerResolver) .SetType(TypeNames.ISerializerResolver); IEnumerable <ValueParserDescriptor> valueParsers = resultBuilderDescriptor .ValueParsers .GroupBy(t => t.Name) .Select(t => t.First()); foreach (ValueParserDescriptor valueParser in valueParsers) { var parserFieldName = $"{GetFieldName(valueParser.Name)}Parser"; classBuilder .AddField(parserFieldName) .SetReadOnly() .SetType( TypeNames.ILeafValueParser .WithGeneric(valueParser.SerializedType, valueParser.RuntimeType)); MethodCallBuilder getLeaveValueParser = MethodCallBuilder .Inline() .SetMethodName( _serializerResolver, nameof(ISerializerResolver.GetLeafValueParser)) .AddGeneric(valueParser.SerializedType.ToString()) .AddGeneric(valueParser.RuntimeType.ToString()) .AddArgument(valueParser.Name.AsStringToken()); constructorBuilder.AddCode( AssignmentBuilder .New() .SetAssertNonNull() .SetAssertException( ExceptionBuilder .Inline(TypeNames.ArgumentException) .AddArgument( $"\"No serializer for type `{valueParser.Name}` found.\"")) .SetLefthandSide(parserFieldName) .SetRighthandSide(getLeaveValueParser)); } AddBuildMethod(resultTypeDescriptor, classBuilder); AddBuildDataMethod(resultTypeDescriptor, classBuilder); var processed = new HashSet <string>(); AddRequiredDeserializeMethods(resultTypeDescriptor, classBuilder, processed); CodeFileBuilder .New() .SetNamespace(resultTypeDescriptor.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
protected override void Generate( CodeWriter writer, ITypeDescriptor typeDescriptor, out string fileName) { ComplexTypeDescriptor complexTypeDescriptor = typeDescriptor as ComplexTypeDescriptor ?? throw new InvalidOperationException( "A result entity mapper can only be generated for complex types"); var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name); fileName = className; ClassBuilder classBuilder = ClassBuilder .New() .AddImplements(TypeNames.IOperationResultDataInfo) .SetName(fileName); ConstructorBuilder constructorBuilder = classBuilder .AddConstructor() .SetTypeName(complexTypeDescriptor.RuntimeType.Name); foreach (var prop in complexTypeDescriptor.Properties) { TypeReferenceBuilder propTypeBuilder = prop.Type.ToEntityIdBuilder(); // Add Property to class classBuilder .AddProperty(prop.Name) .SetType(propTypeBuilder) .SetPublic(); // Add initialization of property to the constructor var paramName = GetParameterName(prop.Name); constructorBuilder.AddParameter(paramName).SetType(propTypeBuilder); constructorBuilder.AddCode( AssignmentBuilder .New() .SetLefthandSide(prop.Name) .SetRighthandSide(paramName)); } classBuilder .AddProperty("EntityIds") .SetType(TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId)) .AsLambda(_entityIds); classBuilder .AddProperty("Version") .SetType(TypeNames.UInt64) .AsLambda(_version); AddConstructorAssignedField( TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId), _entityIds, classBuilder, constructorBuilder); AddConstructorAssignedField( TypeNames.UInt64, _version, classBuilder, constructorBuilder, true); // WithVersion const string version = nameof(version); classBuilder .AddMethod("WithVersion") .SetAccessModifier(AccessModifier.Public) .SetReturnType(TypeNames.IOperationResultDataInfo) .AddParameter(version, x => x.SetType(TypeNames.UInt64)) .AddCode(MethodCallBuilder .New() .SetReturn() .SetNew() .SetMethodName(className) .AddArgumentRange( complexTypeDescriptor.Properties.Select(x => x.Name.Value)) .AddArgument(_entityIds) .AddArgument(version)); CodeFileBuilder .New() .SetNamespace(complexTypeDescriptor.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
protected override void Generate( CodeWriter writer, DataTypeDescriptor descriptor, out string fileName) { // Setup class fileName = descriptor.Name; AbstractTypeBuilder typeBuilder; ConstructorBuilder? constructorBuilder = null; var typenamePropName = "__typename"; if (descriptor.IsInterface) { typeBuilder = new InterfaceBuilder() .SetName(fileName); typeBuilder.AddProperty(PropertyBuilder.New() .SetName(typenamePropName) .SetType(TypeNames.String)); } else { var(classBuilder, constructorBuilder2) = CreateClassBuilder(); constructorBuilder2 .SetTypeName(fileName) .SetAccessModifier(AccessModifier.Public); constructorBuilder = constructorBuilder2; classBuilder.AddProperty( PropertyBuilder .New() .SetAccessModifier(AccessModifier.Public) .SetName(typenamePropName) .SetType(TypeNames.String)); var paramName = "typename"; var assignment = AssignmentBuilder .New() .SetLefthandSide(typenamePropName) .SetRighthandSide(paramName) .AssertNonNull(); constructorBuilder.AddParameter( ParameterBuilder .New() .SetType(TypeNames.String) .SetName(paramName)) .AddCode(assignment); classBuilder.SetName(fileName); typeBuilder = classBuilder; } // Add Properties to class foreach (PropertyDescriptor item in descriptor.Properties) { var itemParamName = item.Name.WithLowerFirstChar(); var assignment = AssignmentBuilder .New() .SetLefthandSide(item.Name) .SetRighthandSide(itemParamName); var paramType = item.Type.IsEntityType() ? item.Type.ToEntityIdBuilder() : item.Type.ToBuilder(); constructorBuilder?.AddParameter( ParameterBuilder .New() .SetType(paramType) .SetName(itemParamName) .SetDefault("null")) .AddCode(assignment); switch (item.Type.Kind) { case TypeKind.LeafType: typeBuilder.AddProperty(item.Name) .SetType(item.Type.ToBuilder()) .SetAccessModifier(AccessModifier.Public); break; case TypeKind.DataType: typeBuilder.AddProperty(item.Name) .SetType(item.Type.ToBuilder(item.Type.Name)) .SetAccessModifier(AccessModifier.Public); break; case TypeKind.EntityType: typeBuilder.AddProperty(item.Name) .SetType(item.Type.ToBuilder().SetName(TypeNames.EntityId)) .SetAccessModifier(AccessModifier.Public); break; default: throw new ArgumentOutOfRangeException(); } } foreach (NameString superType in descriptor.Implements) { typeBuilder.AddImplements(DataTypeNameFromTypeName(superType)); } CodeFileBuilder .New() .SetNamespace(descriptor.Namespace) .AddType(typeBuilder) .Build(writer); }
protected override void Generate( CodeWriter writer, ResultBuilderDescriptor resultBuilderDescriptor, out string fileName) { var processed = new HashSet <string>(); var resultTypeDescriptor = resultBuilderDescriptor.ResultNamedType as InterfaceTypeDescriptor ?? throw new InvalidOperationException( "A result type can only be generated for complex types"); var(classBuilder, constructorBuilder) = CreateClassBuilder(); fileName = resultBuilderDescriptor.RuntimeType.Name; classBuilder.SetName(fileName); constructorBuilder.SetTypeName(fileName); classBuilder.AddImplements( $"{TypeNames.IOperationResultBuilder}<{TypeNames.JsonDocument}," + $" {resultTypeDescriptor.RuntimeType.Name}>"); AddConstructorAssignedField( TypeNames.IEntityStore, _entityStoreFieldName, classBuilder, constructorBuilder); AddConstructorAssignedField( TypeReferenceBuilder.New() .SetName(TypeNames.Func) .AddGeneric(TypeNames.JsonElement) .AddGeneric(TypeNames.EntityId), _extractIdFieldName, classBuilder, constructorBuilder); AddConstructorAssignedField( TypeReferenceBuilder.New() .SetName(TypeNames.IOperationResultDataFactory) .AddGeneric(resultTypeDescriptor.RuntimeType.Name), _resultDataFactoryFieldName, classBuilder, constructorBuilder); constructorBuilder.AddParameter( ParameterBuilder.New() .SetName(_serializerResolverParamName) .SetType(TypeNames.ISerializerResolver)); IEnumerable <ValueParserDescriptor> valueParsers = resultBuilderDescriptor .ValueParsers .GroupBy(t => t.Name) .Select(t => t.First()); foreach (ValueParserDescriptor valueParser in valueParsers) { var parserFieldName = $"{GetFieldName(valueParser.Name)}Parser"; classBuilder.AddField( FieldBuilder.New() .SetReadOnly() .SetName(parserFieldName) .SetType( TypeReferenceBuilder.New() .SetName(TypeNames.ILeafValueParser) .AddGeneric(valueParser.SerializedType.ToString()) .AddGeneric(valueParser.RuntimeType.ToString()))); constructorBuilder.AddCode( AssignmentBuilder.New() .SetAssertNonNull() .SetAssertException( TypeNames.ArgumentException + $"(\"No serializer for type `{valueParser.Name}` found.\")") .SetLefthandSide(parserFieldName) .SetRighthandSide( MethodCallBuilder.New() .SetPrefix(_serializerResolverParamName + ".") .SetDetermineStatement(false) .SetMethodName( $"GetLeafValueParser<{valueParser.SerializedType}, " + $"{valueParser.RuntimeType}>") .AddArgument($"\"{valueParser.Name}\""))); } AddBuildMethod( resultTypeDescriptor, classBuilder); AddBuildDataMethod( resultTypeDescriptor, classBuilder); AddRequiredDeserializeMethods( resultBuilderDescriptor.ResultNamedType, classBuilder, processed); CodeFileBuilder.New() .SetNamespace( resultBuilderDescriptor.ResultNamedType.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
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); }
protected override void Generate( CodeWriter writer, OperationDescriptor descriptor, out string fileName) { var(classBuilder, constructorBuilder) = CreateClassBuilder(); fileName = CreateDocumentTypeName(descriptor.Name); classBuilder .AddImplements(TypeNames.IDocument) .SetName(fileName); constructorBuilder.SetAccessModifier(AccessModifier.Private); classBuilder.AddField( FieldBuilder.New() .SetStatic() .SetConst() .SetType(TypeNames.String) .SetName("_bodyString") .SetValue($"@\"{descriptor.BodyString}\"", true)); classBuilder.AddField( FieldBuilder.New() .SetStatic() .SetReadOnly() .SetType("byte[]") .SetName("_body") .SetValue($"{TypeNames.EncodingUtf8}.GetBytes(_bodyString)")); string operationKind; switch (descriptor) { case MutationOperationDescriptor mutationOperationDescriptor: operationKind = "Mutation"; break; case QueryOperationDescriptor queryOperationDescriptor: operationKind = "Query"; break; case SubscriptionOperationDescriptor subscriptionOperationDescriptor: operationKind = "Subscription"; break; default: throw new ArgumentOutOfRangeException(nameof(descriptor)); } classBuilder.AddProperty( PropertyBuilder.New() .SetStatic() .SetType(fileName) .SetName("Instance") .SetValue($"new {fileName}()")); classBuilder.AddProperty( PropertyBuilder.New() .SetType(TypeNames.OperationKind) .SetName("Kind").AsLambda($"{TypeNames.OperationKind}.{operationKind}")); classBuilder.AddProperty( PropertyBuilder.New() .SetType($"{TypeNames.IReadOnlySpan}<byte>") .SetName("Body").AsLambda("_body")); classBuilder.AddMethod( MethodBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetReturnType("override string") .SetName("ToString") .AddCode("return _bodyString;")); CodeFileBuilder .New() .SetNamespace(descriptor.Namespace) .AddType(classBuilder) .Build(writer); }
protected override void Generate( CodeWriter writer, ITypeDescriptor typeDescriptor, out string fileName) { ComplexTypeDescriptor descriptor = typeDescriptor as ComplexTypeDescriptor ?? throw new InvalidOperationException( "A result data factory can only be generated for complex types"); fileName = CreateResultFactoryName(descriptor.RuntimeType.Name); ClassBuilder classBuilder = ClassBuilder .New() .SetName(fileName) .AddImplements( TypeNames.IOperationResultDataFactory .WithGeneric(descriptor.RuntimeType.Name)); ConstructorBuilder constructorBuilder = classBuilder .AddConstructor() .SetTypeName(descriptor.Name); AddConstructorAssignedField( TypeNames.IEntityStore, _entityStore, classBuilder, constructorBuilder); MethodCallBuilder returnStatement = MethodCallBuilder .New() .SetReturn() .SetNew() .SetMethodName(descriptor.RuntimeType.Name); foreach (PropertyDescriptor property in descriptor.Properties) { returnStatement .AddArgument(BuildMapMethodCall(_info, property)); } IfBuilder ifHasCorrectType = IfBuilder .New() .SetCondition( $"{_dataInfo} is {CreateResultInfoName(descriptor.RuntimeType.Name)} {_info}") .AddCode(returnStatement); classBuilder .AddMethod("Create") .SetAccessModifier(AccessModifier.Public) .SetReturnType(descriptor.RuntimeType.Name) .AddParameter(_dataInfo, b => b.SetType(TypeNames.IOperationResultDataInfo)) .AddCode(ifHasCorrectType) .AddEmptyLine() .AddCode( ExceptionBuilder .New(TypeNames.ArgumentException) .AddArgument( $"\"{CreateResultInfoName(descriptor.RuntimeType.Name)} expected.\"")); var processed = new HashSet <string>(); AddRequiredMapMethods( _info, descriptor, classBuilder, constructorBuilder, processed, true); CodeFileBuilder .New() .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal) .AddType(classBuilder) .Build(writer); }
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); }
protected override Task WriteAsync( CodeWriter writer, EnumValueSerializerDescriptor descriptor) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (descriptor is null) { throw new ArgumentNullException(nameof(descriptor)); } ClassBuilder classBuilder = ClassBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetSealed() .SetName(descriptor.Name) .AddImplements(Types.IValueSerializer) .AddProperty(PropertyBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetType("string") .SetName("Name") .SetGetter(CodeLineBuilder.New() .SetLine($"return \"{descriptor.EnumGraphQLTypeName}\";"))) .AddProperty(PropertyBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetType(Types.ValueKind) .SetName("Kind") .SetGetter(CodeLineBuilder.New() .SetLine($"return {Types.ValueKind}.Enum;"))) .AddProperty(PropertyBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetType(Types.Type) .SetName("ClrType") .SetGetter(CodeLineBuilder.New() .SetLine($"return typeof({descriptor.EnumTypeName});"))) .AddProperty(PropertyBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetType(Types.Type) .SetName("SerializationType") .SetGetter(CodeLineBuilder.New() .SetLine($"return typeof(string);"))) .AddMethod(MethodBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetReturnType("object?", NullableRefTypes) .SetReturnType("object", !NullableRefTypes) .SetName("Serialize") .AddParameter(ParameterBuilder.New() .SetType("object?", NullableRefTypes) .SetType("object", !NullableRefTypes) .SetName("value")) .AddCode(CreateSerializerMethodBody(descriptor, CodeWriter.Indent))) .AddMethod(MethodBuilder.New() .SetAccessModifier(AccessModifier.Public) .SetReturnType("object?", NullableRefTypes) .SetReturnType("object", !NullableRefTypes) .SetName("Deserialize") .AddParameter(ParameterBuilder.New() .SetType("object?", NullableRefTypes) .SetType("object", !NullableRefTypes) .SetName("serialized")) .AddCode(CreateDeserializerMethodBody(descriptor, CodeWriter.Indent))); return(CodeFileBuilder.New() .SetNamespace(descriptor.Namespace) .AddType(classBuilder) .BuildAsync(writer)); }