public async Task <CompilationUnitSyntax> GenerateCode(CancellationToken cancellationToken) { var namespaceName = "HagarGeneratedCode." + this.compilation.AssemblyName; // Collect metadata from the compilation. var metadataModel = await this.GenerateMetadataModel(cancellationToken); var members = new List <MemberDeclarationSyntax>(); foreach (var type in metadataModel.InvokableInterfaces) { foreach (var method in type.Methods) { var(invokable, generatedInvokerDescription) = InvokableGenerator.Generate(this.compilation, this.libraryTypes, type, method); metadataModel.SerializableTypes.Add(generatedInvokerDescription); metadataModel.GeneratedInvokables[method] = generatedInvokerDescription; members.Add(invokable); } var(proxy, generatedProxyDescription) = ProxyGenerator.Generate(this.compilation, this.libraryTypes, type, metadataModel); metadataModel.GeneratedProxies.Add(generatedProxyDescription); members.Add(proxy); } // Generate code. foreach (var type in metadataModel.SerializableTypes) { // Generate a partial serializer class for each serializable type. members.Add(SerializerGenerator.GenerateSerializer(this.compilation, this.libraryTypes, type)); if (type.IsEmptyConstructable) { metadataModel.ActivatableTypes.Add(type); // Generate a partial serializer class for each serializable type. members.Add(ActivatorGenerator.GenerateActivator(this.compilation, this.libraryTypes, type)); } } // Generate metadata. var metadataClass = MetadataGenerator.GenerateMetadata(this.compilation, metadataModel, this.libraryTypes); members.Add(metadataClass); var metadataAttribute = AttributeList() .WithTarget(AttributeTargetSpecifier(Token(SyntaxKind.AssemblyKeyword))) .WithAttributes( SingletonSeparatedList( Attribute(this.libraryTypes.MetadataProviderAttribute.ToNameSyntax()) .AddArgumentListArguments(AttributeArgument(TypeOfExpression(ParseTypeName($"{namespaceName}.{metadataClass.Identifier.Text}")))))); return(CompilationUnit() .WithAttributeLists(List(new [] { metadataAttribute })) .WithMembers( SingletonList <MemberDeclarationSyntax>( NamespaceDeclaration(ParseName(namespaceName)) .WithMembers(List(members)) .WithUsings(List(new[] { UsingDirective(ParseName("global::Hagar.Codecs")), UsingDirective(ParseName("global::Hagar.GeneratedCodeHelpers")) }))))); }
public static TypeSyntax GetPartialSerializerTypeName(this ISerializableTypeDescription type) { var genericArity = type.TypeParameters.Length; var name = SerializerGenerator.GetSimpleClassName(type); if (genericArity > 0) { name += $"<{new string(',', genericArity - 1)}>"; } return(ParseTypeName(name)); }
public static ClassDeclarationSyntax GenerateMetadata(Compilation compilation, List <TypeDescription> serializableTypes) { var configParam = "config".ToIdentifierName(); var addMethod = configParam.Member("Serializers").Member("Add"); var body = new List <StatementSyntax>(); body.AddRange( serializableTypes.Select( type => (StatementSyntax)ExpressionStatement(InvocationExpression(addMethod, ArgumentList(SingletonSeparatedList(Argument(TypeOfExpression(GetPartialSerializerTypeName(type.Type))))))) )); var libraryTypes = LibraryTypes.FromCompilation(compilation); var configType = libraryTypes.SerializerConfiguration; var configureMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), "Configure") .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters( Parameter(configParam.Identifier).WithType(configType.ToTypeSyntax())) .AddBodyStatements(body.ToArray()); var interfaceType = libraryTypes.ConfigurationProvider.Construct(configType); return(ClassDeclaration(CodeGenerator.CodeGeneratorName + "_Metadata_" + compilation.AssemblyName.Replace('.', '_')) .AddBaseListTypes(SimpleBaseType(interfaceType.ToTypeSyntax())) .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.SealedKeyword)) .AddAttributeLists(AttributeList(SingletonSeparatedList(CodeGenerator.GetGeneratedCodeAttributeSyntax()))) .AddMembers(configureMethod)); TypeSyntax GetPartialSerializerTypeName(INamedTypeSymbol type) { var genericArity = type.TypeParameters.Length; var name = SerializerGenerator.GetSimpleClassName(type); if (genericArity > 0) { name += $"<{new string(',', genericArity - 1)}>"; } return(ParseTypeName(name)); } }
public async Task <CompilationUnitSyntax> GenerateCode(CancellationToken cancellationToken) { // Collect metadata from the compilation. var serializableTypes = await GetSerializableTypes(cancellationToken); // Generate code. var members = new List <MemberDeclarationSyntax>(); foreach (var type in serializableTypes) { // Generate a partial serializer class for each serializable type. members.Add(SerializerGenerator.GenerateSerializer(this.compilation, type)); } var namespaceName = "HagarGeneratedCode." + this.compilation.AssemblyName; // Generate metadata. var metadataClass = MetadataGenerator.GenerateMetadata(this.compilation, serializableTypes); members.Add(metadataClass); var metadataAttribute = AttributeList() .WithTarget(AttributeTargetSpecifier(Token(SyntaxKind.AssemblyKeyword))) .WithAttributes( SingletonSeparatedList( Attribute(this.compilation.GetTypeByMetadataName("Hagar.Configuration.MetadataProviderAttribute").ToNameSyntax()) .AddArgumentListArguments(AttributeArgument(TypeOfExpression(ParseTypeName($"{namespaceName}.{metadataClass.Identifier.Text}")))))); return(CompilationUnit() .WithAttributeLists(List(new [] { metadataAttribute })) .WithMembers( SingletonList <MemberDeclarationSyntax>( NamespaceDeclaration(ParseName(namespaceName)) .WithMembers(List(members)) .WithUsings(List(new[] { UsingDirective(ParseName("global::Hagar.Codecs")), UsingDirective(ParseName("global::Hagar.GeneratedCodeHelpers")) }))))); }