Beispiel #1
0
        private static int WriteCSharpSourceFiles(
            string inputFile,
            bool writeSource,
            bool writeTests,
            bool writeSignatures,
            string outputFile
            )
        {
            var tree = ReadTree(inputFile);

            // The syntax.xml doc contains some nodes that are useful for other tools, but which are
            // not needed by this syntax generator.  Specifically, we have `<Choice>` and
            // `<Sequence>` nodes in the xml file to help others tools understand the relationship
            // between some fields (i.e. 'only one of these children can be non-null').  To make our
            // life easier, we just flatten all those nodes, grabbing all the nested `<Field>` nodes
            // and placing into a single linear list that we can then process.
            TreeFlattening.FlattenChildren(tree);

            if (writeSignatures)
            {
                SignatureWriter.Write(Console.Out, tree);
            }
            else
            {
                if (writeSource)
                {
                    var outputPath         = outputFile.Trim('"');
                    var prefix             = Path.GetFileName(inputFile);
                    var outputMainFile     = Path.Combine(outputPath, $"{prefix}.Main.Generated.cs");
                    var outputInternalFile = Path.Combine(
                        outputPath,
                        $"{prefix}.Internal.Generated.cs"
                        );
                    var outputSyntaxFile = Path.Combine(
                        outputPath,
                        $"{prefix}.Syntax.Generated.cs"
                        );

                    WriteToFile(writer => SourceWriter.WriteMain(writer, tree), outputMainFile);
                    WriteToFile(
                        writer => SourceWriter.WriteInternal(writer, tree),
                        outputInternalFile
                        );
                    WriteToFile(writer => SourceWriter.WriteSyntax(writer, tree), outputSyntaxFile);
                }
                if (writeTests)
                {
                    WriteToFile(writer => TestWriter.Write(writer, tree), outputFile);
                }
            }

            return(0);
        }
Beispiel #2
0
        public void Execute(GeneratorExecutionContext context)
        {
            var syntaxXml = context.AdditionalFiles.SingleOrDefault(a => Path.GetFileName(a.Path) == "Syntax.xml");

            if (syntaxXml == null)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_MissingSyntaxXml, location: null));
                return;
            }

            var syntaxXmlText = syntaxXml.GetText();

            if (syntaxXmlText == null)
            {
                context.ReportDiagnostic(Diagnostic.Create(s_UnableToReadSyntaxXml, location: null));
                return;
            }

            Tree tree;
            var  reader = XmlReader.Create(new SourceTextReader(syntaxXmlText), new XmlReaderSettings {
                DtdProcessing = DtdProcessing.Prohibit
            });

            try
            {
                var serializer = new XmlSerializer(typeof(Tree));
                tree = (Tree)serializer.Deserialize(reader);
            }
            catch (InvalidOperationException ex) when(ex.InnerException is XmlException)
            {
                var xmlException = (XmlException)ex.InnerException;

                var line     = syntaxXmlText.Lines[xmlException.LineNumber - 1]; // LineNumber is one-based.
                int offset   = xmlException.LinePosition - 1;                    // LinePosition is one-based
                var position = line.Start + offset;
                var span     = new TextSpan(position, 0);
                var lineSpan = syntaxXmlText.Lines.GetLinePositionSpan(span);

                context.ReportDiagnostic(
                    Diagnostic.Create(
                        s_SyntaxXmlError,
                        location: Location.Create(syntaxXml.Path, span, lineSpan),
                        xmlException.Message));

                return;
            }

            TreeFlattening.FlattenChildren(tree);

            AddResult(writer => SourceWriter.WriteMain(writer, tree, context.CancellationToken), "Syntax.xml.Main.Generated.cs");
            AddResult(writer => SourceWriter.WriteInternal(writer, tree, context.CancellationToken), "Syntax.xml.Internal.Generated.cs");
            AddResult(writer => SourceWriter.WriteSyntax(writer, tree, context.CancellationToken), "Syntax.xml.Syntax.Generated.cs");

            void AddResult(Action <TextWriter> writeFunction, string hintName)
            {
                // Write out the contents to a StringBuilder to avoid creating a single large string
                // in memory
                var stringBuilder = new StringBuilder();

                using (var textWriter = new StringWriter(stringBuilder))
                {
                    writeFunction(textWriter);
                }

                // And create a SourceText from the StringBuilder, once again avoiding allocating a single massive string
                context.AddSource(hintName, SourceText.From(new StringBuilderReader(stringBuilder), stringBuilder.Length, encoding: Encoding.UTF8));
            }
        }