private bool CheckForErrors(CodeAnalyzer codeAnalyzer)
        {
            bool hasErrors = false;

            if (codeAnalyzer.Diagnostics.Any(diag => diag.Severity == DiagnosticSeverity.Error || diag.Severity == DiagnosticSeverity.Warning))
            {
                var oldColor = Console.ForegroundColor;
                foreach (var diagnostic in codeAnalyzer.Diagnostics)
                {
                    switch (diagnostic.Severity)
                    {
                    case DiagnosticSeverity.Error:
                        Console.ForegroundColor = ConsoleColor.Red;
                        hasErrors = true;
                        break;

                    case DiagnosticSeverity.Warning:
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        break;

                    default:
                        Console.ForegroundColor = oldColor;
                        break;
                    }

                    Console.WriteLine(diagnostic.ToString());
                }

                Console.ForegroundColor = oldColor;
            }

            return(!hasErrors);
        }
        /// <summary>
        /// The main entry point to run the code generation based on the given options.
        ///
        /// Main phases of execution are:
        /// 1. Load the code into roslyn
        ///    1. Parse Source Files into syntax trees
        ///    2. Load the references
        ///    3. Run the compiler to create the Linked semantic model.
        /// 2. Analyze the roslyn Compilation unit
        ///    1. Detect react types in the code
        ///    2. Build a Model for the assembly
        /// 3. Generate code
        ///    1. Use the Model from step 2 to emit a C# Syntax Tree
        ///    2. Write the SyntaxTree to a file.
        /// </summary>
        public async Task <bool> Run(Options options)
        {
            var codeAnalyzer = new CodeAnalyzer(m_cancellationToken);

            // Load the code into roslyn
            using (new ConsoleMeasurement("Parsing source files"))
            {
                await codeAnalyzer.ParseSourceFilesAsync(
                    GetDistinctExistingFiles(options.SourceFiles),
                    options.Defines.Select(def => def.Trim()));
            }

            using (new ConsoleMeasurement("Loading references"))
            {
                await codeAnalyzer.LoadMetadataReferencesAsync(
                    GetDistinctExistingFiles(options.References));
            }

            using (new ConsoleMeasurement("Compiling"))
            {
                if (!codeAnalyzer.TryCompileAndCheckForErrors())
                {
                    CheckForErrors(codeAnalyzer);
                    return(false);
                }
            }

            // Extract the model form the assembly
            ReactAssembly assembly;

            using (new ConsoleMeasurement("Finding types"))
            {
                assembly = codeAnalyzer.AnalyzeAndConstructAssemblyModel();
            }

            // Check if any errors have been logged and display them.
            if (!CheckForErrors(codeAnalyzer))
            {
                return(false);
            }

            var codeGenerator = new CodeGenerator(codeAnalyzer.ReactTypes, options.Namespace);
            CSharpSyntaxNode node;

            using (new ConsoleMeasurement("Generating code"))
            {
                node = codeGenerator.Generate(assembly);
            }

            var code = node.NormalizeWhitespace(indentation: "  ", elasticTrivia: false).ToFullString();

            if (!await TryWriteFileIfDifferent(options.OutputFile, code))
            {
                return(false);
            }

            return(true);
        }