Exemplo n.º 1
0
        private static TCompilation GetCompilationWithAnalyzerDiagnostics <TCompilation>(
            this TCompilation c,
            DiagnosticAnalyzer[] analyzers,
            AnalyzerOptions options,
            Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException,
            bool reportSuppressedDiagnostics,
            bool includeCompilerDiagnostics,
            out ImmutableArray <Diagnostic> diagnostics)
            where TCompilation : Compilation
        {
            var analyzersArray = analyzers.ToImmutableArray();

            if (reportSuppressedDiagnostics != c.Options.ReportSuppressedDiagnostics)
            {
                c = (TCompilation)c.WithOptions(c.Options.WithReportSuppressedDiagnostics(reportSuppressedDiagnostics));
            }

            var analyzerManager = new AnalyzerManager(analyzersArray);
            var driver          = AnalyzerDriver.CreateAndAttachToCompilation(c, analyzersArray, options, analyzerManager, onAnalyzerException, null, false, out var newCompilation, CancellationToken.None);

            var compilerDiagnostics = newCompilation.GetDiagnostics();
            var analyzerDiagnostics = driver.GetDiagnosticsAsync(newCompilation).Result;
            var allDiagnostics      = includeCompilerDiagnostics ?
                                      compilerDiagnostics.AddRange(analyzerDiagnostics) :
                                      analyzerDiagnostics;

            diagnostics = driver.ApplyProgrammaticSuppressions(allDiagnostics, newCompilation);

            if (!reportSuppressedDiagnostics)
            {
                Assert.True(diagnostics.All(d => !d.IsSuppressed));
            }

            return((TCompilation)newCompilation); // note this is a new compilation
        }
Exemplo n.º 2
0
        private static TCompilation GetCompilationWithAnalyzerDiagnostics <TCompilation>(
            this TCompilation c,
            DiagnosticAnalyzer[] analyzers,
            AnalyzerOptions options,
            Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException,
            bool logAnalyzerExceptionAsDiagnostics,
            bool reportSuppressedDiagnostics,
            bool includeCompilerDiagnostics,
            out ImmutableArray <Diagnostic> diagnostics)
            where TCompilation : Compilation
        {
            var analyzersArray = analyzers.ToImmutableArray();

            var exceptionDiagnostics = new ConcurrentSet <Diagnostic>();

            if (onAnalyzerException == null)
            {
                if (logAnalyzerExceptionAsDiagnostics)
                {
                    onAnalyzerException = (ex, analyzer, diagnostic) =>
                    {
                        exceptionDiagnostics.Add(diagnostic);
                    };
                }
                else
                {
                    // We want unit tests to throw if any analyzer OR the driver throws, unless the test explicitly provides a delegate.
                    onAnalyzerException = FailFastOnAnalyzerException;
                }
            }

            if (reportSuppressedDiagnostics != c.Options.ReportSuppressedDiagnostics)
            {
                c = (TCompilation)c.WithOptions(c.Options.WithReportSuppressedDiagnostics(reportSuppressedDiagnostics));
            }

            var analyzerManager = new AnalyzerManager(analyzersArray);
            var driver          = AnalyzerDriver.CreateAndAttachToCompilation(c, analyzersArray, options, analyzerManager, onAnalyzerException, null, false, out var newCompilation, CancellationToken.None);

            var compilerDiagnostics = newCompilation.GetDiagnostics();
            var analyzerDiagnostics = driver.GetDiagnosticsAsync(newCompilation).Result;
            var allDiagnostics      = includeCompilerDiagnostics ?
                                      compilerDiagnostics.AddRange(analyzerDiagnostics) :
                                      analyzerDiagnostics;

            diagnostics = driver.ApplyProgrammaticSuppressions(allDiagnostics, newCompilation).AddRange(exceptionDiagnostics);

            if (!reportSuppressedDiagnostics)
            {
                Assert.True(diagnostics.All(d => !d.IsSuppressed));
            }

            return((TCompilation)newCompilation); // note this is a new compilation
        }
Exemplo n.º 3
0
        private static TCompilation GetAnalyzerDiagnostics <TCompilation>(
            this TCompilation c,
            DiagnosticAnalyzer[] analyzers,
            AnalyzerOptions options,
            Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException,
            bool logAnalyzerExceptionAsDiagnostics,
            bool reportDiagnosticsWithSourceSuppressions,
            out ImmutableArray <Diagnostic> diagnostics)
            where TCompilation : Compilation
        {
            var analyzersArray = analyzers.ToImmutableArray();

            var exceptionDiagnostics = new ConcurrentSet <Diagnostic>();

            if (onAnalyzerException == null)
            {
                if (logAnalyzerExceptionAsDiagnostics)
                {
                    onAnalyzerException = (ex, analyzer, diagnostic) =>
                    {
                        exceptionDiagnostics.Add(diagnostic);
                    };
                }
                else
                {
                    // We want unit tests to throw if any analyzer OR the driver throws, unless the test explicitly provides a delegate.
                    onAnalyzerException = FailFastOnAnalyzerException;
                }
            }

            Compilation newCompilation;
            var         driver    = AnalyzerDriver.CreateAndAttachToCompilation(c, analyzersArray, options, AnalyzerManager.Instance, onAnalyzerException, false, reportDiagnosticsWithSourceSuppressions, out newCompilation, CancellationToken.None);
            var         discarded = newCompilation.GetDiagnostics();

            diagnostics = driver.GetDiagnosticsAsync(newCompilation).Result.AddRange(exceptionDiagnostics);

            if (!reportDiagnosticsWithSourceSuppressions)
            {
                Assert.True(diagnostics.All(d => !d.IsSuppressed));
            }

            return((TCompilation)newCompilation); // note this is a new compilation
        }
        public static ImmutableArray <Diagnostic> GetAnalyzerDiagnostics <TCompilation>(
            this TCompilation c,
            DiagnosticAnalyzer[] analyzers,
            TestValidationMode validationMode,
            AnalyzerOptions options = null,
            Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null,
            bool logAnalyzerExceptionAsDiagnostics = true)
            where TCompilation : Compilation
        {
            ImmutableArray <DiagnosticAnalyzer> analyzersArray = analyzers.ToImmutableArray();

            var exceptionDiagnostics = new ConcurrentSet <Diagnostic>();

            if (onAnalyzerException == null)
            {
                if (logAnalyzerExceptionAsDiagnostics)
                {
                    onAnalyzerException = (ex, analyzer, diagnostic) =>
                    {
                        exceptionDiagnostics.Add(diagnostic);
                    };
                }
                else
                {
                    // We want unit tests to throw if any analyzer OR the driver throws, unless the test explicitly provides a delegate.
                    onAnalyzerException = FailFastOnAnalyzerException;
                }
            }

            Compilation    newCompilation;
            AnalyzerDriver driver = AnalyzerDriver.CreateAndAttachToCompilation(c, analyzersArray, options, AnalyzerManager.Instance, onAnalyzerException, null, false, out newCompilation, CancellationToken.None);

            ImmutableArray <Diagnostic> diagnostics = newCompilation.GetDiagnostics();

            if (validationMode != TestValidationMode.AllowCompileErrors)
            {
                ValidateNoCompileErrors(diagnostics);
            }

            return(driver.GetDiagnosticsAsync(newCompilation).Result.AddRange(exceptionDiagnostics));
        }
Exemplo n.º 5
0
        private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.IsScriptRunner);

            cancellationToken.ThrowIfCancellationRequested();

            if (Arguments.DisplayLogo)
            {
                PrintLogo(consoleOutput);
            }

            if (Arguments.DisplayHelp)
            {
                PrintHelp(consoleOutput);
                return(Succeeded);
            }

            if (ReportErrors(Arguments.Errors, consoleOutput, errorLogger))
            {
                return(Failed);
            }

            var touchedFilesLogger = (Arguments.TouchedFilesPath != null) ? new TouchedFileLogger() : null;

            Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger, errorLogger);

            if (compilation == null)
            {
                return(Failed);
            }

            var diagnostics = new List <DiagnosticInfo>();
            ImmutableArray <DiagnosticAnalyzer> analyzers;
            ImmutableArray <SourceGenerator>    sourceGenerators;

            ResolveAnalyzersAndGeneratorsFromArguments(diagnostics, MessageProvider, out analyzers, out sourceGenerators);
            var additionalTextFiles = ResolveAdditionalFilesFromArguments(diagnostics, MessageProvider, touchedFilesLogger);

            if (ReportErrors(diagnostics, consoleOutput, errorLogger))
            {
                return(Failed);
            }

            bool reportAnalyzer = false;
            CancellationTokenSource analyzerCts     = null;
            AnalyzerManager         analyzerManager = null;
            AnalyzerDriver          analyzerDriver  = null;

            try
            {
                // Print the diagnostics produced during the parsing stage and exit if there were any errors.
                if (ReportErrors(compilation.GetParseDiagnostics(), consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                if (!sourceGenerators.IsEmpty)
                {
                    var trees = compilation.GenerateSource(sourceGenerators, this.Arguments.OutputDirectory, writeToDisk: true, cancellationToken: cancellationToken);
                    if (!trees.IsEmpty)
                    {
                        compilation = compilation.AddSyntaxTrees(trees);
                        if (ReportErrors(compilation.GetParseDiagnostics(), consoleOutput, errorLogger))
                        {
                            return(Failed);
                        }
                    }
                }

                ConcurrentSet <Diagnostic> analyzerExceptionDiagnostics = null;

                if (!analyzers.IsEmpty)
                {
                    analyzerCts     = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    analyzerManager = new AnalyzerManager();
                    analyzerExceptionDiagnostics = new ConcurrentSet <Diagnostic>();
                    Action <Diagnostic> addExceptionDiagnostic = diagnostic => analyzerExceptionDiagnostics.Add(diagnostic);
                    var analyzerOptions = new AnalyzerOptions(ImmutableArray <AdditionalText> .CastUp(additionalTextFiles));

                    analyzerDriver = AnalyzerDriver.CreateAndAttachToCompilation(compilation, analyzers, analyzerOptions, analyzerManager, addExceptionDiagnostic, Arguments.ReportAnalyzer, out compilation, analyzerCts.Token);
                    reportAnalyzer = Arguments.ReportAnalyzer && !analyzers.IsEmpty;
                }

                if (ReportErrors(compilation.GetDeclarationDiagnostics(), consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                string outputName       = GetOutputFileName(compilation, cancellationToken);
                var    finalPeFilePath  = Path.Combine(Arguments.OutputDirectory, outputName);
                var    finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalPeFilePath, ".pdb");
                var    finalXmlFilePath = Arguments.DocumentationPath;

                var diagnosticBag = DiagnosticBag.GetInstance();

                try
                {
                    // NOTE: Unlike the PDB path, the XML doc path is not embedded in the assembly, so we don't need to pass it to emit.
                    var emitOptions = Arguments.EmitOptions.
                                      WithOutputNameOverride(outputName).
                                      WithPdbFilePath(finalPdbFilePath);

                    // The PDB path is emitted in it's entirety into the PE.  This makes it impossible to have deterministic
                    // builds that occur in different source directories.  To enable this we shave all path information from
                    // the PDB when specified by the user.
                    //
                    // This is a temporary work around to allow us to make progress with determinism.  The following issue
                    // tracks getting an official solution here.
                    //
                    // https://github.com/dotnet/roslyn/issues/9813
                    if (Arguments.ParseOptions.Features.ContainsKey("pdb-path-determinism") && !string.IsNullOrEmpty(emitOptions.PdbFilePath))
                    {
                        emitOptions = emitOptions.WithPdbFilePath(Path.GetFileName(emitOptions.PdbFilePath));
                    }

                    var moduleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder(
                        diagnosticBag,
                        Arguments.ManifestResources,
                        emitOptions,
                        debugEntryPoint: null,
                        testData: null,
                        cancellationToken: cancellationToken);

                    if (moduleBeingBuilt != null)
                    {
                        bool success;

                        try
                        {
                            success = compilation.CompileMethods(
                                moduleBeingBuilt,
                                Arguments.EmitPdb,
                                diagnosticBag,
                                filterOpt: null,
                                cancellationToken: cancellationToken);

                            if (success)
                            {
                                // NOTE: as native compiler does, we generate the documentation file
                                // NOTE: 'in place', replacing the contents of the file if it exists
                                Stream xmlStreamOpt = null;

                                if (finalXmlFilePath != null)
                                {
                                    xmlStreamOpt = OpenFile(finalXmlFilePath, consoleOutput, PortableShim.FileMode.OpenOrCreate, PortableShim.FileAccess.Write, PortableShim.FileShare.ReadWriteBitwiseOrDelete);
                                    if (xmlStreamOpt == null)
                                    {
                                        return(Failed);
                                    }

                                    xmlStreamOpt.SetLength(0);
                                }

                                using (xmlStreamOpt)
                                {
                                    IEnumerable <DiagnosticInfo> errors;
                                    using (var win32ResourceStreamOpt = GetWin32Resources(Arguments, compilation, out errors))
                                    {
                                        if (ReportErrors(errors, consoleOutput, errorLogger))
                                        {
                                            return(Failed);
                                        }

                                        success = compilation.GenerateResourcesAndDocumentationComments(
                                            moduleBeingBuilt,
                                            xmlStreamOpt,
                                            win32ResourceStreamOpt,
                                            diagnosticBag,
                                            cancellationToken);
                                    }

                                    // only report unused usings if we have success.
                                    if (success)
                                    {
                                        compilation.ReportUnusedImports(null, diagnosticBag, cancellationToken);
                                    }
                                }
                            }

                            compilation.CompleteTrees(null);

                            if (analyzerDriver != null)
                            {
                                // GetDiagnosticsAsync is called after ReportUnusedImports
                                // since that method calls EventQueue.TryComplete. Without
                                // TryComplete, we may miss diagnostics.
                                var hostDiagnostics = analyzerDriver.GetDiagnosticsAsync(compilation).Result;
                                diagnosticBag.AddRange(hostDiagnostics);
                                if (hostDiagnostics.Any(IsReportedError))
                                {
                                    success = false;
                                }
                            }
                        }
                        finally
                        {
                            moduleBeingBuilt.CompilationFinished();
                        }

                        if (success)
                        {
                            using (var peStreamProvider = new CompilerEmitStreamProvider(this, finalPeFilePath))
                                using (var pdbStreamProviderOpt = Arguments.EmitPdb ? new CompilerEmitStreamProvider(this, finalPdbFilePath) : null)
                                {
                                    success = compilation.SerializeToPeStream(
                                        moduleBeingBuilt,
                                        peStreamProvider,
                                        pdbStreamProviderOpt,
                                        testSymWriterFactory: null,
                                        diagnostics: diagnosticBag,
                                        metadataOnly: emitOptions.EmitMetadataOnly,
                                        cancellationToken: cancellationToken);

                                    if (success && touchedFilesLogger != null)
                                    {
                                        if (pdbStreamProviderOpt != null)
                                        {
                                            touchedFilesLogger.AddWritten(finalPdbFilePath);
                                        }
                                        touchedFilesLogger.AddWritten(finalPeFilePath);
                                    }
                                }
                        }
                    }

                    var compileAndEmitDiagnostics = diagnosticBag.ToReadOnly();
                    GenerateSqmData(Arguments.CompilationOptions, compileAndEmitDiagnostics);

                    if (ReportErrors(compileAndEmitDiagnostics, consoleOutput, errorLogger))
                    {
                        return(Failed);
                    }
                }
                finally
                {
                    diagnosticBag.Free();
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (analyzerExceptionDiagnostics != null && ReportErrors(analyzerExceptionDiagnostics, consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                bool errorsReadingAdditionalFiles = false;
                foreach (var additionalFile in additionalTextFiles)
                {
                    if (ReportErrors(additionalFile.Diagnostics, consoleOutput, errorLogger))
                    {
                        errorsReadingAdditionalFiles = true;
                    }
                }

                if (errorsReadingAdditionalFiles)
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (Arguments.TouchedFilesPath != null)
                {
                    Debug.Assert(touchedFilesLogger != null);

                    if (finalXmlFilePath != null)
                    {
                        touchedFilesLogger.AddWritten(finalXmlFilePath);
                    }

                    var readStream = OpenFile(Arguments.TouchedFilesPath + ".read", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate);
                    if (readStream == null)
                    {
                        return(Failed);
                    }

                    using (var writer = new StreamWriter(readStream))
                    {
                        touchedFilesLogger.WriteReadPaths(writer);
                    }

                    var writtenStream = OpenFile(Arguments.TouchedFilesPath + ".write", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate);
                    if (writtenStream == null)
                    {
                        return(Failed);
                    }

                    using (var writer = new StreamWriter(writtenStream))
                    {
                        touchedFilesLogger.WriteWrittenPaths(writer);
                    }
                }
            }
            finally
            {
                // At this point analyzers are already complete in which case this is a no-op.  Or they are
                // still running because the compilation failed before all of the compilation events were
                // raised.  In the latter case the driver, and all its associated state, will be waiting around
                // for events that are never coming.  Cancel now and let the clean up process begin.
                if (analyzerCts != null)
                {
                    analyzerCts.Cancel();

                    if (analyzerManager != null)
                    {
                        // Clear cached analyzer descriptors and unregister exception handlers hooked up to the LocalizableString fields of the associated descriptors.
                        analyzerManager.ClearAnalyzerState(analyzers);
                    }

                    if (reportAnalyzer)
                    {
                        ReportAnalyzerExecutionTime(consoleOutput, analyzerDriver, Culture, compilation.Options.ConcurrentBuild);
                    }
                }
            }

            return(Succeeded);
        }
Exemplo n.º 6
0
        private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.IsScriptRunner);

            cancellationToken.ThrowIfCancellationRequested();

            if (Arguments.DisplayLogo)
            {
                PrintLogo(consoleOutput);
            }

            if (Arguments.DisplayHelp)
            {
                PrintHelp(consoleOutput);
                return(Succeeded);
            }

            if (ReportErrors(Arguments.Errors, consoleOutput, errorLogger))
            {
                return(Failed);
            }

            var touchedFilesLogger = (Arguments.TouchedFilesPath != null) ? new TouchedFileLogger() : null;

            Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger, errorLogger);

            if (compilation == null)
            {
                return(Failed);
            }


            var diagnostics         = new List <DiagnosticInfo>();
            var analyzers           = ResolveAnalyzersFromArguments(diagnostics, MessageProvider, touchedFilesLogger);
            var additionalTextFiles = ResolveAdditionalFilesFromArguments(diagnostics, MessageProvider, touchedFilesLogger);

            if (ReportErrors(diagnostics, consoleOutput, errorLogger))
            {
                return(Failed);
            }

            cancellationToken.ThrowIfCancellationRequested();

            CancellationTokenSource analyzerCts     = null;
            AnalyzerManager         analyzerManager = null;
            AnalyzerDriver          analyzerDriver  = null;

            try
            {
                Func <ImmutableArray <Diagnostic> > getAnalyzerDiagnostics       = null;
                ConcurrentSet <Diagnostic>          analyzerExceptionDiagnostics = null;
                if (!analyzers.IsDefaultOrEmpty)
                {
                    analyzerCts     = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    analyzerManager = new AnalyzerManager();
                    analyzerExceptionDiagnostics = new ConcurrentSet <Diagnostic>();
                    Action <Diagnostic> addExceptionDiagnostic = diagnostic => analyzerExceptionDiagnostics.Add(diagnostic);
                    var analyzerOptions = new AnalyzerOptions(ImmutableArray <AdditionalText> .CastUp(additionalTextFiles));

                    analyzerDriver         = AnalyzerDriver.CreateAndAttachToCompilation(compilation, analyzers, analyzerOptions, analyzerManager, addExceptionDiagnostic, Arguments.ReportAnalyzer, out compilation, analyzerCts.Token);
                    getAnalyzerDiagnostics = () => analyzerDriver.GetDiagnosticsAsync(compilation).Result;
                }

                // Print the diagnostics produced during the parsing stage and exit if there were any errors.
                if (ReportErrors(compilation.GetParseDiagnostics(), consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                if (ReportErrors(compilation.GetDeclarationDiagnostics(), consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                EmitResult emitResult;

                // NOTE: as native compiler does, we generate the documentation file
                // NOTE: 'in place', replacing the contents of the file if it exists

                string finalPeFilePath;
                string finalPdbFilePath;
                string finalXmlFilePath;

                Stream xmlStreamOpt = null;

                cancellationToken.ThrowIfCancellationRequested();

                finalXmlFilePath = Arguments.DocumentationPath;
                if (finalXmlFilePath != null)
                {
                    xmlStreamOpt = OpenFile(finalXmlFilePath, consoleOutput, PortableShim.FileMode.OpenOrCreate, PortableShim.FileAccess.Write, PortableShim.FileShare.ReadWriteBitwiseOrDelete);
                    if (xmlStreamOpt == null)
                    {
                        return(Failed);
                    }

                    xmlStreamOpt.SetLength(0);
                }

                cancellationToken.ThrowIfCancellationRequested();

                IEnumerable <DiagnosticInfo> errors;
                using (var win32ResourceStreamOpt = GetWin32Resources(Arguments, compilation, out errors))
                    using (xmlStreamOpt)
                    {
                        if (ReportErrors(errors, consoleOutput, errorLogger))
                        {
                            return(Failed);
                        }

                        cancellationToken.ThrowIfCancellationRequested();

                        string outputName = GetOutputFileName(compilation, cancellationToken);

                        finalPeFilePath  = Path.Combine(Arguments.OutputDirectory, outputName);
                        finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalPeFilePath, ".pdb");

                        // NOTE: Unlike the PDB path, the XML doc path is not embedded in the assembly, so we don't need to pass it to emit.
                        var emitOptions = Arguments.EmitOptions.
                                          WithOutputNameOverride(outputName).
                                          WithPdbFilePath(finalPdbFilePath);

                        using (var peStreamProvider = new CompilerEmitStreamProvider(this, finalPeFilePath))
                            using (var pdbStreamProviderOpt = Arguments.EmitPdb ? new CompilerEmitStreamProvider(this, finalPdbFilePath) : null)
                            {
                                emitResult = compilation.Emit(
                                    peStreamProvider,
                                    pdbStreamProviderOpt,
                                    (xmlStreamOpt != null) ? new Compilation.SimpleEmitStreamProvider(xmlStreamOpt) : null,
                                    (win32ResourceStreamOpt != null) ? new Compilation.SimpleEmitStreamProvider(win32ResourceStreamOpt) : null,
                                    Arguments.ManifestResources,
                                    emitOptions,
                                    debugEntryPoint: null,
                                    getHostDiagnostics: getAnalyzerDiagnostics,
                                    cancellationToken: cancellationToken);

                                if (emitResult.Success && touchedFilesLogger != null)
                                {
                                    if (pdbStreamProviderOpt != null)
                                    {
                                        touchedFilesLogger.AddWritten(finalPdbFilePath);
                                    }

                                    touchedFilesLogger.AddWritten(finalPeFilePath);
                                }
                            }
                    }

                GenerateSqmData(Arguments.CompilationOptions, emitResult.Diagnostics);

                if (ReportErrors(emitResult.Diagnostics, consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (analyzerExceptionDiagnostics != null && ReportErrors(analyzerExceptionDiagnostics, consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                bool errorsReadingAdditionalFiles = false;
                foreach (var additionalFile in additionalTextFiles)
                {
                    if (ReportErrors(additionalFile.Diagnostics, consoleOutput, errorLogger))
                    {
                        errorsReadingAdditionalFiles = true;
                    }
                }

                if (errorsReadingAdditionalFiles)
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (Arguments.TouchedFilesPath != null)
                {
                    Debug.Assert(touchedFilesLogger != null);

                    if (finalXmlFilePath != null)
                    {
                        touchedFilesLogger.AddWritten(finalXmlFilePath);
                    }

                    var readStream = OpenFile(Arguments.TouchedFilesPath + ".read", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate);
                    if (readStream == null)
                    {
                        return(Failed);
                    }

                    using (var writer = new StreamWriter(readStream))
                    {
                        touchedFilesLogger.WriteReadPaths(writer);
                    }

                    var writtenStream = OpenFile(Arguments.TouchedFilesPath + ".write", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate);
                    if (writtenStream == null)
                    {
                        return(Failed);
                    }

                    using (var writer = new StreamWriter(writtenStream))
                    {
                        touchedFilesLogger.WriteWrittenPaths(writer);
                    }
                }
            }
            finally
            {
                // At this point analyzers are already complete in which case this is a no-op.  Or they are
                // still running because the compilation failed before all of the compilation events were
                // raised.  In the latter case the driver, and all its associated state, will be waiting around
                // for events that are never coming.  Cancel now and let the clean up process begin.
                if (analyzerCts != null)
                {
                    analyzerCts.Cancel();

                    if (analyzerManager != null)
                    {
                        // Clear cached analyzer descriptors and unregister exception handlers hooked up to the LocalizableString fields of the associated descriptors.
                        analyzerManager.ClearAnalyzerState(analyzers);
                    }

                    if (Arguments.ReportAnalyzer && analyzerDriver != null && compilation != null)
                    {
                        ReportAnalyzerExecutionTime(consoleOutput, analyzerDriver, Culture, compilation.Options.ConcurrentBuild);
                    }
                }
            }

            return(Succeeded);
        }