예제 #1
0
        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")) })))));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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));
            }
        }
예제 #4
0
        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")) })))));
        }