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; } }
// 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; } }
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(); } } }
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(); } } }