예제 #1
0
        private static RootNodeDefinition ParseSyntax(
            string fbsPath,
            IIncludeLoader includeLoader)
        {
            string rootPath = Path.GetFullPath(fbsPath);

            // First, visit includes. We need to figure out which files warrant a thorough look.
            HashSet <string> includes = new HashSet <string>()
            {
                rootPath
            };
            Queue <string> visitOrder = new Queue <string>();

            visitOrder.Enqueue(rootPath);

            var rootNode      = new RootNodeDefinition(rootPath);
            var schemaVisitor = new SchemaVisitor(rootNode);

            // SHA256 -> 32 bytes.
            byte[] hash = new byte[32];

            string asmVersion = typeof(FlatSharpCompiler).Assembly.GetCustomAttribute <AssemblyFileVersionAttribute>()?.Version ?? "unknown";

            Encoding.UTF8.GetBytes(asmVersion, 0, asmVersion.Length, hash, 0);

            while (visitOrder.Count > 0)
            {
                string next = visitOrder.Dequeue();
                string fbs  = includeLoader.LoadInclude(next);

                using (var sha256 = SHA256Managed.Create())
                {
                    byte[] componentHash = sha256.ComputeHash(Encoding.UTF8.GetBytes(fbs));
                    for (int i = 0; i < hash.Length; ++i)
                    {
                        hash[i] ^= componentHash[i];
                    }
                }

                schemaVisitor.CurrentFileName = next;

                // Traverse the graph of includes.
                var includeVisitor = new IncludeVisitor(next, includes, visitOrder);

                ErrorContext.Current.WithScope(next, () =>
                {
                    var schema = GetParser(fbs).schema();
                    ErrorContext.Current.ThrowIfHasErrors();

                    includeVisitor.Visit(schema);
                    ErrorContext.Current.ThrowIfHasErrors();

                    schemaVisitor.Visit(schema);
                    ErrorContext.Current.ThrowIfHasErrors();
                });
            }

            rootNode.InputHash = $"{asmVersion}.{Convert.ToBase64String(hash)}";
            return(rootNode);
        }
예제 #2
0
        static int Main(string[] args)
        {
            using (var context = ErrorContext.Current)
            {
                try
                {
                    context.PushScope("$");

                    // Read existing file to see if we even need to do any work.
                    string fbsFileName    = Path.GetFileName(args[0]);
                    string outputFileName = fbsFileName + ".generated.cs";
                    string outputPath     = args.Length < 2 || string.IsNullOrEmpty(args[1]) ? Path.GetDirectoryName(args[0]) : args[1];
                    string outputFullPath = Path.Combine(outputPath, outputFileName);
                    // string fbsText = File.ReadAllText(args[0]);

                    int attemptCount = 0;
                    while (attemptCount++ <= 5)
                    {
                        try
                        {
                            RootNodeDefinition rootNode = ParseSyntax(args[0], new IncludeFileLoader());

                            if (File.Exists(outputFullPath))
                            {
                                string existingOutput = File.ReadAllText(outputFullPath);
                                if (existingOutput.Contains(rootNode.InputHash))
                                {
                                    // Input file unchanged.
                                    return(0);
                                }
                            }

                            string cSharp = CreateCSharp(rootNode);
                            File.WriteAllText(outputFullPath, cSharp);
                        }
                        catch (IOException)
                        {
                            // Some projects built multiple targets at once, and this can
                            // cause contention between different invocations of the compiler.
                            // Usually, one will succeed, the others will fail, then they'll wake up and
                            // see that the file looks right to them.
                            Thread.Sleep(TimeSpan.FromMilliseconds(new Random().Next(20, 200)));
                        }
                    }
                }
                catch (InvalidFbsFileException ex)
                {
                    foreach (var message in ex.Errors)
                    {
                        Console.Error.WriteLine(message);
                    }

                    return(-1);
                }
                catch (FlatSharpCompilationException ex)
                {
                    foreach (var message in ex.CompilerErrors)
                    {
                        Console.Error.WriteLine(message);
                    }

                    return(-1);
                }
                catch (FileNotFoundException)
                {
                    Console.Error.WriteLine($"File '{args[0]}' was not found");
                    return(-1);
                }
                catch (IndexOutOfRangeException)
                {
                    Console.Error.WriteLine($"No file specified");
                    return(-1);
                }
                finally
                {
                    context.PopScope();
                }

                return(0);
            }
        }
예제 #3
0
 public SchemaVisitor(RootNodeDefinition rootNode)
 {
     this.schemaRoot = rootNode;
 }