Exemple #1
0
        private static string CreateCSharp(BaseSchemaMember rootNode)
        {
            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            var tablesNeedingSerializers = new List <TableOrStructDefinition>();
            var rpcDefinitions           = new List <RpcDefinition>();

            FindItemsRequiringSecondCodePass(rootNode, tablesNeedingSerializers, rpcDefinitions);

            if (tablesNeedingSerializers.Count == 0 && rpcDefinitions.Count == 0)
            {
                // Hey, no serializers or RPCs. We're all done. Go ahead and return the code we already generated.
                CodeWriter tempWriter = new CodeWriter();
                rootNode.WriteCode(tempWriter, CodeWritingPass.SecondPass, rootNode.DeclaringFile, new Dictionary <string, string>());

                if (ErrorContext.Current.Errors.Any())
                {
                    throw new InvalidFbsFileException(ErrorContext.Current.Errors);
                }

                return(tempWriter.ToString());
            }

            // Compile the assembly so that we may generate serializers for the data contracts defined in this FBS file.;
            // Compile with firstpass here to include all data (even stuff from includes).
            CodeWriter writer = new CodeWriter();

            rootNode.WriteCode(writer, CodeWritingPass.FirstPass, rootNode.DeclaringFile, new Dictionary <string, string>());
            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            string code = writer.ToString();

            var(assembly, _, _) = RoslynSerializerGenerator.CompileAssembly(code, true);

            Dictionary <string, string> generatedSerializers = new Dictionary <string, string>();

            foreach (var definition in tablesNeedingSerializers)
            {
                generatedSerializers[definition.FullName] = GenerateSerializerForType(assembly, definition);
            }

            writer = new CodeWriter();
            rootNode.WriteCode(writer, CodeWritingPass.SecondPass, rootNode.DeclaringFile, generatedSerializers);

            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            string rawCode       = writer.ToString();
            string formattedCode = RoslynSerializerGenerator.GetFormattedText(rawCode);

            return(formattedCode);
        }
    private string GenerateSerializerForType(
        CompileContext context,
        FlatBufferDeserializationOption deserializationOption)
    {
        Type?type = context.PreviousAssembly?.GetType(this.FullName);

        FlatSharpInternal.Assert(type is not null, $"Flatsharp failed to find expected type '{this.FullName}' in assembly.");

        var options = new FlatBufferSerializerOptions(deserializationOption)
        {
            ConvertProtectedInternalToProtected = false
        };
        var generator = new RoslynSerializerGenerator(options, context.TypeModelContainer);

        MethodInfo method = generator.GetType()
                            .GetMethod(nameof(RoslynSerializerGenerator.GenerateCSharp), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) !
                            .MakeGenericMethod(type);

        try
        {
            string code = (string)method.Invoke(generator, new[] { "private" }) !;
            return(code);
        }
        catch (TargetInvocationException ex)
        {
            ExceptionDispatchInfo.Capture(ex.InnerException !).Throw();
            throw;
        }
    }
Exemple #3
0
        // TODO: consider moving to TableOrStructDefinition.
        private static string GenerateSerializerForType(Assembly assembly, TableOrStructDefinition tableOrStruct)
        {
            CSharpHelpers.ConvertProtectedInternalToProtected = false;
            try
            {
                Type type      = assembly.GetType(tableOrStruct.FullName);
                var  options   = new FlatBufferSerializerOptions(tableOrStruct.RequestedSerializer.Value);
                var  generator = new RoslynSerializerGenerator(options, TypeModelContainer.CreateDefault());

                var method = generator
                             .GetType()
                             .GetMethod(nameof(RoslynSerializerGenerator.GenerateCSharp), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
                             .MakeGenericMethod(type);

                try
                {
                    string code = (string)method.Invoke(generator, new[] { "private" });
                    return(code);
                }
                catch (TargetInvocationException ex)
                {
                    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                    throw;
                }
            }
            finally
            {
                CSharpHelpers.ConvertProtectedInternalToProtected = true;
            }
        }
Exemple #4
0
        private static string CreateCSharp(BaseSchemaMember rootNode, CompilerOptions options)
        {
            ErrorContext.Current.ThrowIfHasErrors();

            if (string.IsNullOrEmpty(rootNode.DeclaringFile))
            {
                throw new InvalidFbsFileException("FlatSharp.Internal: RootNode missing declaring file");
            }

            Assembly?  assembly = null;
            CodeWriter writer   = new CodeWriter();
            var        steps    = new[]
            {
                CodeWritingPass.Initialization,
                CodeWritingPass.PropertyModeling,
                CodeWritingPass.SerializerGeneration,
                CodeWritingPass.RpcGeneration,
            };

            foreach (var step in steps)
            {
                var localOptions = options;

                if (step <= CodeWritingPass.PropertyModeling)
                {
                    localOptions = localOptions with {
                        NullableWarnings = false
                    };
                }

                if (step > CodeWritingPass.Initialization)
                {
                    string code = writer.ToString();
                    (assembly, _, _) = RoslynSerializerGenerator.CompileAssembly(code, true);
                }

                writer = new CodeWriter();

                rootNode.WriteCode(
                    writer,
                    new CompileContext
                {
                    CompilePass        = step,
                    Options            = localOptions,
                    RootFile           = rootNode.DeclaringFile,
                    PreviousAssembly   = assembly,
                    TypeModelContainer = TypeModelContainer.CreateDefault(),
                });

                ErrorContext.Current.ThrowIfHasErrors();
            }

            string rawCode       = writer.ToString();
            string formattedCode = RoslynSerializerGenerator.GetFormattedText(rawCode);

            return(formattedCode);
        }
    }
        private static string CreateCSharp(string fbsSchema, string inputHash)
        {
            BaseSchemaMember rootNode = ParseSyntax(fbsSchema, inputHash);

            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            // Create the first pass of the code. This pass includes the data contracts from the FBS file.
            // If the schema requests a pregenerated serializer, then we'll need to load this code, generate
            // the serializer, and then rebuild it.
            CodeWriter writer = new CodeWriter();

            rootNode.WriteCode(writer, CodeWritingPass.FirstPass, null);

            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            string code = writer.ToString();

            var tablesNeedingSerializers = new List <TableOrStructDefinition>();
            var rpcDefinitions           = new List <RpcDefinition>();

            FindItemsRequiringSecondCodePass(rootNode, tablesNeedingSerializers, rpcDefinitions);

            if (tablesNeedingSerializers.Count == 0 && rpcDefinitions.Count == 0)
            {
                // Hey, no serializers or RPCs. We're all done. Go ahead and return the code we already generated.
                return(code);
            }

            // Compile the assembly so that we may generate serializers for the data contracts defined in this FBS file.
            var(assembly, _, _) = RoslynSerializerGenerator.CompileAssembly(code, true);

            Dictionary <string, string> generatedSerializers = new Dictionary <string, string>();

            foreach (var definition in tablesNeedingSerializers)
            {
                generatedSerializers[definition.FullName] = GenerateSerializerForType(assembly, definition);
            }

            writer = new CodeWriter();
            rootNode.WriteCode(writer, CodeWritingPass.SecondPass, generatedSerializers);

            if (ErrorContext.Current.Errors.Any())
            {
                throw new InvalidFbsFileException(ErrorContext.Current.Errors);
            }

            string rawCode       = writer.ToString();
            string formattedCode = RoslynSerializerGenerator.GetFormattedText(rawCode);

            return(formattedCode);
        }
        // TODO: consider moving to TableOrStructDefinition.
        private static string GenerateSerializerForType(Assembly assembly, TableOrStructDefinition tableOrStruct)
        {
            Type type      = assembly.GetType(tableOrStruct.FullName);
            var  options   = new FlatBufferSerializerOptions(tableOrStruct.RequestedSerializer.Value);
            var  generator = new RoslynSerializerGenerator(options);

            var method = generator
                         .GetType()
                         .GetMethod(nameof(RoslynSerializerGenerator.GenerateCSharp), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
                         .MakeGenericMethod(type);

            string code = (string)method.Invoke(generator, new[] { "private" });

            return(code);
        }
 internal static Assembly CompileAndLoadAssembly(string fbsSchema, string inputHash = "", IEnumerable <Assembly> additionalReferences = null)
 {
     using (var context = ErrorContext.Current)
     {
         context.PushScope("$");
         try
         {
             Assembly[] additionalRefs = additionalReferences?.ToArray() ?? Array.Empty <Assembly>();
             string     cSharp         = CreateCSharp(fbsSchema, inputHash);
             var(assembly, formattedText, _) = RoslynSerializerGenerator.CompileAssembly(cSharp, true, additionalRefs);
             string debugText = formattedText();
             return(assembly);
         }
         finally
         {
             context.PopScope();
         }
     }
 }
Exemple #8
0
        internal static Assembly CompileAndLoadAssembly(
            string fbsSchema,
            CompilerOptions options,
            IEnumerable <Assembly>?additionalReferences    = null,
            Dictionary <string, string>?additionalIncludes = null)
        {
            InMemoryIncludeLoader includeLoader = new InMemoryIncludeLoader
            {
                { "root.fbs", fbsSchema }
            };

            if (additionalIncludes != null)
            {
                foreach (var kvp in additionalIncludes)
                {
                    includeLoader[kvp.Key] = kvp.Value;
                }
            }

            using (var context = ErrorContext.Current)
            {
                context.PushScope("$");
                try
                {
                    Assembly[] additionalRefs = additionalReferences?.ToArray() ?? Array.Empty <Assembly>();
                    var        rootNode       = ParseSyntax("root.fbs", includeLoader);
                    string     cSharp         = CreateCSharp(rootNode, options);
                    var(assembly, formattedText, _) = RoslynSerializerGenerator.CompileAssembly(cSharp, true, additionalRefs);
                    string debugText = formattedText();
                    return(assembly);
                }
                finally
                {
                    context.PopScope();
                }
            }
        }