Ejemplo n.º 1
0
        /// <summary>
        /// Emits compiled assembly to temporary file
        /// </summary>
        /// <param name="compilation"></param>
        /// <param name="result"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public AssemblyWrapper EmitCompiledAssembly(Microsoft.CodeAnalysis.Compilation compilation, out EmitResult result, string filename)
        {
            var fi = new FileInfo(filename);

            fi.Directory?.Create();
            using (var fs = new FileStream(fi.FullName, FileMode.Create))
            {
                result = compilation.Emit(fs);
                if (!result.Success)
                {
                    return(null);
                }
            }
            var assembly = LoadByFullFilename(fi.FullName);

            return(assembly);
        }
Ejemplo n.º 2
0
        private CompilationResult EmitCompilation(
            string path,
            string assemblyName,
            string filePath,
            Microsoft.CodeAnalysis.Compilation compilation)
        {
            var result = compilation.Emit(path, manifestResources: _embeddedResourceCreator.GetManifestResources(assemblyName, filePath));

            return(new CompilationResult
            {
                IsSuccess = result.Success,
                Errors = result.Diagnostics
                         .Where(d => d.Severity == DiagnosticSeverity.Error)
                         .Select(d => new CompilationError {
                    Message = d.GetMessage(), Location = d.Location.ToString()
                })
                         .ToList()
            });
        }
Ejemplo n.º 3
0
        public Assembly Compile(Microsoft.CodeAnalysis.Compilation compilation, string outputPath)
        {
            var pdbPath    = Path.ChangeExtension(outputPath, "pdb");
            var xmlDocPath = Path.ChangeExtension(outputPath, "xml");

            using (MemoryStream dllStream = new MemoryStream(), pdbStream = new MemoryStream(), xmlStream = new MemoryStream())
            {
                using (var win32ResStream = compilation.CreateDefaultWin32Resources(
                           versionResource: true, // Important!
                           noManifest: false,
                           manifestContents: null,
                           iconInIcoFormat: null))
                {
                    var result = compilation.Emit(
                        peStream: dllStream,
                        pdbStream: pdbStream,
                        xmlDocumentationStream: xmlStream,
                        win32Resources: win32ResStream);

                    if (!result.Success)
                    {
                        var failures = result.Diagnostics.Where(diagnostic =>
                                                                diagnostic.IsWarningAsError ||
                                                                diagnostic.Severity == DiagnosticSeverity.Error);

                        foreach (var diagnostic in failures)
                        {
                            Logger.Error(diagnostic);
                        }

                        return(null);
                    }

                    _fileSystem.WriteAllBytes(outputPath, dllStream.ToArray());
                    _fileSystem.WriteAllBytes(pdbPath, pdbStream.ToArray());
                    _fileSystem.WriteAllBytes(xmlDocPath, xmlStream.ToArray());
                    return(_assemblyLoader.LoadFrom(outputPath));
                }
            }
        }
Ejemplo n.º 4
0
        public static CompilationResult GetAssemblyFromCompilation(
            ICodeGenAssemblyLoadContext loader,
            Microsoft.CodeAnalysis.Compilation compilation)
        {
            using (var ms = new MemoryStream())
            {
                var result = compilation.Emit(ms, pdbStream: null);

                if (!result.Success)
                {
                    var formatter     = new DiagnosticFormatter();
                    var errorMessages = result.Diagnostics
                                        .Where(IsError)
                                        .Select(d => formatter.Format(d));

                    return(CompilationResult.FromErrorMessages(errorMessages));
                }

                ms.Seek(0, SeekOrigin.Begin);

                try
                {
                    return(CompilationResult.FromAssembly(loader.LoadStream(ms, symbols: null)));
                }
                catch (Exception ex)
                {
                    var v = ex;
                    while (v.InnerException != null)
                    {
                        v = v.InnerException;
                    }

                    return(CompilationResult.FromErrorMessages(ex.GetAllErrorMessages()));
                }
            }
        }
Ejemplo n.º 5
0
        private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.IsInteractive);

            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.Create(compilation, analyzers, analyzerOptions, analyzerManager, addExceptionDiagnostic, Arguments.ReportAnalyzer, out compilation, analyzerCts.Token);
                    getAnalyzerDiagnostics = () => analyzerDriver.GetDiagnosticsAsync().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,
                                    getAnalyzerDiagnostics,
                                    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);
        }
        private int RunCore(TextWriter consoleOutput, ErrorLogger2 errorLogger, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.GetFieldOrProperty <bool>("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         = typeof(List <>).MakeGenericTypeFast(Refl.Type_DiagnosticInfo).InvokeFunction(".ctor");
            var analyzers           = ResolveAnalyzersAndGeneratorsFromArguments(diagnostics, MessageProvider, touchedFilesLogger);
            var additionalTextFiles = ResolveAdditionalFilesFromArguments(diagnostics, MessageProvider, touchedFilesLogger);

            if (ReportErrors((IEnumerable <DiagnosticInfo>)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.CreateRange(additionalTextFiles.Select(x => (AdditionalText)x)));

                    analyzerDriver = ReflAnalyzerDriver.CreateAndAttachToCompilation(
                        compilation,
                        analyzers,
                        analyzerOptions,
                        analyzerManager,
                        addExceptionDiagnostic,
                        Arguments.ReportAnalyzer,
                        out compilation,
                        analyzerCts.Token);
                    getAnalyzerDiagnostics = () => ((Task <ImmutableArray <Diagnostic> >)analyzerDriver.InvokeFunction("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);
                }
                consoleOutput.WriteLine("Rewriting LINQ to procedural code...");
                var originalCompilation = compilation;

                var rewrittenLinqInvocations = 0;
                var rewrittenMethods         = 0;
                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    var        rewriter = new LinqRewriter(originalCompilation.GetSemanticModel(syntaxTree));
                    var        root     = syntaxTree.GetRoot();
                    SyntaxNode rewritten;
                    try
                    {
                        rewritten = rewriter.Visit(root);
                    }
                    catch (Exception ex)
                    {
                        ReportErrors(new[] { rewriter.CreateDiagnosticForException(ex, syntaxTree.FilePath) }, consoleOutput, errorLogger);

                        var m = ex;
                        while (m != null)
                        {
                            Console.WriteLine(m);
                            Console.WriteLine(m.StackTrace);
                            m = m.InnerException;
                        }


                        return(Failed);
                    }

                    if (rewritten != root)
                    {
                        var originalOptions = (CSharp.CSharpParseOptions)root.SyntaxTree.Options;
                        var parseOptions    = ((CSharp.CSharpParseOptions)syntaxTree.Options).WithLanguageVersion(originalOptions.LanguageVersion);
                        var syntaxTree2     = syntaxTree.WithRootAndOptions(rewritten, parseOptions);

                        OriginalPaths[syntaxTree] = syntaxTree.FilePath;

                        //rewritten = rewritten.SyntaxTree.WithRootAndOptions
                        compilation = compilation.ReplaceSyntaxTree(syntaxTree, syntaxTree2);


                        rewrittenLinqInvocations += rewriter.RewrittenLinqQueries;
                        rewrittenMethods         += rewriter.RewrittenMethods;
                    }
                }

                var infoDescriptor = new DiagnosticDescriptor("REWRITE1001", "RoslynLinqRewrite statistics", "Rewritten {0} LINQ queries in {1} methods as procedural code.", "Compiler", DiagnosticSeverity.Info, true);
                var info           = Diagnostic.Create(infoDescriptor, Location.None, rewrittenLinqInvocations, rewrittenMethods);

                consoleOutput.WriteLine(DiagnosticFormatter.Format(info));

                var rewriteto = Environment.GetEnvironmentVariable("ROSLYN_LINQ_REWRITE_OUT_STATISTICS_TO");
                if (rewriteto != null)
                {
                    File.WriteAllText(rewriteto, string.Format("Rewritten {0} LINQ queries in {1} methods as procedural code.", rewrittenLinqInvocations, rewrittenMethods));
                }

                //consoleOutput.WriteLine(string.Format, rewrittenLinqInvocations, rewrittenMethods));

                var k = compilation.GetDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error).ToList();
                if (k.Count != 0)
                {
                    foreach (var err in k)
                    {
                        var errordescr = new DiagnosticDescriptor("REWRITE1002", "Could not compile rewritten method", "Could not compile rewritten method. Consider applying a [Shaman.Runtime.NoLinqRewrite] attribute. File: {0}. Code: {1}", "Compiler", DiagnosticSeverity.Error, true);
                        var m          = err.Location.SourceTree.GetRoot().FindNode(err.Location.SourceSpan);
                        var err2       = Diagnostic.Create(infoDescriptor, err.Location, err.Location.SourceTree.FilePath, m.ToString());

                        consoleOutput.WriteLine(DiagnosticFormatter.Format(info));

                        //System.Console.WriteLine("Could not compile rewritten method. Consider applying a [Shaman.Runtime.NoLinqRewrite] attribute.");

                        //System.Console.WriteLine(err.Location.SourceTree.FilePath);
                        //var z = m.FirstAncestorOrSelf<CSharp.Syntax.BaseMethodDeclarationSyntax>(x => x.Kind() == CSharp.SyntaxKind.MethodDeclaration);
                        //compilation.GetSemanticModel().GetEnclosingSymbol(err.Location.SourceSpan.Start)
                    }
                }
                if (ReportErrors(compilation.GetParseDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error), consoleOutput, errorLogger))
                {
                    return(Failed);
                }

                if (ReportErrors(compilation.GetDeclarationDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error), 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, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete);
                    if (xmlStreamOpt == null)
                    {
                        return(Failed);
                    }

                    xmlStreamOpt.SetLength(0);
                }

                cancellationToken.ThrowIfCancellationRequested();
                ImmutableArray <Diagnostic>  emitDiagnostics;
                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);

                        // 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 dummyCompiler = Refl.Type_Csc.InvokeFunction(".ctor", backup_responseFile, (object)null, backup_args, backup_analyzerLoader);

                        var constr             = Refl.Type_Csc.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).First();
                        var backup_buildPaths2 = Refl.Type_BuildPaths.InvokeFunction(".ctor", backup_buildPaths.ClientDirectory, backup_buildPaths.WorkingDirectory, backup_buildPaths.SdkDirectory, backup_buildPaths.TempDirectory);
                        var dummyCompiler      = constr.Invoke(new object[] { backup_responseFile, backup_buildPaths2, backup_args, backup_analyzerLoader });
                        //var dummyCompiler = Activator.CreateInstance(Refl.Type_Csc, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.CreateInstance|BindingFlags.Instance, null, new object[]{ backup_responseFile, (object)null, backup_args, backup_analyzerLoader}, null);
                        var peStreamProvider     = Refl.Type_CompilerEmitStreamProvider.InvokeFunction(".ctor", dummyCompiler, finalPeFilePath);
                        var pdbStreamProviderOpt = Arguments.EmitPdb ? Refl.Type_CompilerEmitStreamProvider.InvokeFunction(".ctor", dummyCompiler, finalPdbFilePath) : null;

                        /*
                         * internal EmitResult Emit(
                         *  Compilation.EmitStreamProvider peStreamProvider,
                         *  Compilation.EmitStreamProvider pdbStreamProvider,
                         *  Compilation.EmitStreamProvider xmlDocumentationStreamProvider,
                         *  Compilation.EmitStreamProvider win32ResourcesStreamProvider,
                         *  IEnumerable<ResourceDescription> manifestResources,
                         *  EmitOptions options,
                         *  IMethodSymbol debugEntryPoint,
                         *  CompilationTestData testData,
                         *  Func<ImmutableArray<Diagnostic>> getHostDiagnostics,
                         *  CancellationToken cancellationToken)
                         */
                        var diagnosticBag = Refl.Type_DiagnosticBag.InvokeFunction(".ctor");

                        emitResult = null;
                        try
                        {
                            var peStream  = ReflEmitStreamProvider.CreateStream(peStreamProvider, diagnosticBag);
                            var pdbStream = pdbStreamProviderOpt != null?ReflEmitStreamProvider.CreateStream(pdbStreamProviderOpt, diagnosticBag) : null;

                            emitResult = compilation.Emit(
                                peStream,
                                pdbStream,
                                xmlStreamOpt,
                                win32ResourceStreamOpt,
                                Arguments.ManifestResources,
                                emitOptions,
                                null,
                                cancellationToken);
                        }
                        catch
                        {
                            emitDiagnostics = GetEmitDiagnostic(diagnosticBag);
                            if (emitDiagnostics.Length == 0)
                            {
                                throw;
                            }
                        }
                        emitDiagnostics = GetEmitDiagnostic(diagnosticBag);

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

                            touchedFilesLogger.InvokeAction("AddWritten", finalPeFilePath);
                        }
                        peStreamProvider.InvokeAction("Close", diagnosticBag);
                        pdbStreamProviderOpt?.InvokeAction("Close", diagnosticBag);
                    }



                if (ReportErrors((emitResult != null ? emitResult.Diagnostics : Enumerable.Empty <Diagnostic>()).Union(emitDiagnostics), 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.GetFieldOrProperty <IEnumerable <Diagnostic> >("Diagnostics"), consoleOutput, errorLogger))
                    {
                        errorsReadingAdditionalFiles = true;
                    }
                }

                if (errorsReadingAdditionalFiles)
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

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

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

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

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

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

                    using (var writer = new StreamWriter(writtenStream))
                    {
                        touchedFilesLogger.InvokeAction("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.InvokeAction("ClearAnalyzerState", analyzers);
                    }

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

            return(Succeeded);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// csc.exe and vbc.exe entry point.
        /// </summary>
        public virtual int Run(TextWriter consoleOutput, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.IsInteractive);

            cancellationToken.ThrowIfCancellationRequested();

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

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

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

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

            Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger);

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

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

            if (PrintErrors(diagnostics, consoleOutput))
            {
                return(Failed);
            }

            cancellationToken.ThrowIfCancellationRequested();

            EmitResult emitResult;

            // EDMAURER: Don't yet know if there are method body errors. don't overwrite
            // any existing output files until the compilation is known to be successful.
            string tempExeFilename = null;
            string tempPdbFilename = null;

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

            try
            {
                tempExeFilename = CreateTempFile(consoleOutput);

                // Can happen when temp directory is "full"
                if (tempExeFilename == null)
                {
                    return(Failed);
                }

                FileStream output = OpenFile(tempExeFilename, consoleOutput);
                if (output == null)
                {
                    return(Failed);
                }

                string finalOutputPath;
                string finalPdbFilePath;
                string finalXmlFilePath;

                using (output)
                {
                    FileStream pdb = null;
                    FileStream xml = null;

                    cancellationToken.ThrowIfCancellationRequested();

                    if (Arguments.CompilationOptions.DebugInformationKind != DebugInformationKind.None)
                    {
                        tempPdbFilename = CreateTempFile(consoleOutput);

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

                        pdb = OpenFile(tempPdbFilename, consoleOutput);
                        if (pdb == null)
                        {
                            return(Failed);
                        }
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    finalXmlFilePath = Arguments.DocumentationPath;
                    if (finalXmlFilePath != null)
                    {
                        xml = OpenFile(finalXmlFilePath, consoleOutput, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete);
                        if (xml == null)
                        {
                            return(Failed);
                        }
                        xml.SetLength(0);
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    IEnumerable <DiagnosticInfo> errors;
                    using (var win32Res = GetWin32Resources(Arguments, compilation, out errors))
                        using (pdb)
                            using (xml)
                            {
                                if (PrintErrors(errors, consoleOutput))
                                {
                                    return(Failed);
                                }

                                cancellationToken.ThrowIfCancellationRequested();

                                string outputName = GetOutputFileName(compilation, cancellationToken);

                                finalOutputPath  = Path.Combine(Arguments.OutputDirectory, outputName);
                                finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalOutputPath, ".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.
                                emitResult = compilation.Emit(output, outputName, finalPdbFilePath, pdb, xml, cancellationToken, win32Res, Arguments.ManifestResources);
                            }
                }

                GenerateSqmData(Arguments.CompilationOptions, emitResult.Diagnostics);

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

                cancellationToken.ThrowIfCancellationRequested();

                var analyzerDiagnostics = AnalyzerDriver.GetDiagnostics(compilation, analyzers, default(CancellationToken));
                if (PrintErrors(analyzerDiagnostics, consoleOutput))
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (!TryDeleteFile(finalOutputPath, consoleOutput) || !TryMoveFile(tempExeFilename, finalOutputPath, consoleOutput))
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (tempPdbFilename != null)
                {
                    if (!TryDeleteFile(finalPdbFilePath, consoleOutput) || !TryMoveFile(tempPdbFilename, finalPdbFilePath, consoleOutput))
                    {
                        return(Failed);
                    }
                }

                cancellationToken.ThrowIfCancellationRequested();

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

                    touchedFilesLogger.AddWritten(tempExeFilename);
                    touchedFilesLogger.AddWritten(finalOutputPath);
                    if (tempPdbFilename != null)
                    {
                        touchedFilesLogger.AddWritten(tempPdbFilename);
                        touchedFilesLogger.AddWritten(finalPdbFilePath);
                    }
                    if (finalXmlFilePath != null)
                    {
                        touchedFilesLogger.AddWritten(finalXmlFilePath);
                    }


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

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

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

                    using (var writer = new StreamWriter(writtenStream))
                    {
                        touchedFilesLogger.WriteWrittenPaths(writer);
                    }
                }


                return(Succeeded);
            }
            finally
            {
                if (tempExeFilename != null)
                {
                    TryDeleteFile(tempExeFilename, consoleOutput: null);
                }

                if (tempPdbFilename != null)
                {
                    TryDeleteFile(tempPdbFilename, consoleOutput: null);
                }
            }
        }
Ejemplo n.º 8
0
        private int RunCore(TextWriter consoleOutput, CancellationToken cancellationToken)
        {
            Debug.Assert(!Arguments.IsInteractive);

            cancellationToken.ThrowIfCancellationRequested();

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

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

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

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

            Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger);

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

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

            if (PrintErrors(diagnostics, consoleOutput))
            {
                return(Failed);
            }

            cancellationToken.ThrowIfCancellationRequested();

            var analyzerOptions = new AnalyzerOptions(ImmutableArray.Create <AdditionalText, AdditionalTextFile>(additionalTextFiles));

            AnalyzerDriver analyzerDriver = null;

            if (!analyzers.IsDefaultOrEmpty)
            {
                analyzerDriver = AnalyzerDriver.Create(compilation, analyzers, analyzerOptions, out compilation, cancellationToken);
            }

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

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

            EmitResult emitResult;

            // EDMAURER: Don't yet know if there are method body errors. don't overwrite
            // any existing output files until the compilation is known to be successful.
            string tempExeFilename = null;
            string tempPdbFilename = null;

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

            try
            {
                FileStream output = CreateTempFile(consoleOutput, out tempExeFilename);

                // Can happen when temp directory is "full"
                if (output == null)
                {
                    return(Failed);
                }

                string finalOutputPath;
                string finalPdbFilePath;
                string finalXmlFilePath;

                using (output)
                {
                    FileStream pdb = null;
                    FileStream xml = null;

                    cancellationToken.ThrowIfCancellationRequested();

                    if (Arguments.EmitPdb)
                    {
                        pdb = CreateTempFile(consoleOutput, out tempPdbFilename);
                        if (pdb == null)
                        {
                            return(Failed);
                        }
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    finalXmlFilePath = Arguments.DocumentationPath;
                    if (finalXmlFilePath != null)
                    {
                        xml = OpenFile(finalXmlFilePath, consoleOutput, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete);
                        if (xml == null)
                        {
                            return(Failed);
                        }

                        xml.SetLength(0);
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    IEnumerable <DiagnosticInfo> errors;
                    using (var win32Res = GetWin32Resources(Arguments, compilation, out errors))
                        using (pdb)
                            using (xml)
                            {
                                if (PrintErrors(errors, consoleOutput))
                                {
                                    return(Failed);
                                }

                                cancellationToken.ThrowIfCancellationRequested();

                                string outputName = GetOutputFileName(compilation, cancellationToken);

                                finalOutputPath  = Path.Combine(Arguments.OutputDirectory, outputName);
                                finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalOutputPath, ".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);

                                emitResult = compilation.Emit(output, pdb, xml, win32Res, Arguments.ManifestResources, emitOptions, cancellationToken);
                            }
                }

                GenerateSqmData(Arguments.CompilationOptions, emitResult.Diagnostics);

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

                cancellationToken.ThrowIfCancellationRequested();

                if (analyzerDriver != null)
                {
                    var analyzerDiagnostics = analyzerDriver.GetDiagnosticsAsync().Result;
                    if (PrintErrors(analyzerDiagnostics, consoleOutput))
                    {
                        return(Failed);
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                }

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

                if (errorsReadingAdditionalFiles)
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (!TryDeleteFile(finalOutputPath, consoleOutput) || !TryMoveFile(tempExeFilename, finalOutputPath, consoleOutput))
                {
                    return(Failed);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (tempPdbFilename != null)
                {
                    if (!TryDeleteFile(finalPdbFilePath, consoleOutput) || !TryMoveFile(tempPdbFilename, finalPdbFilePath, consoleOutput))
                    {
                        return(Failed);
                    }
                }

                cancellationToken.ThrowIfCancellationRequested();

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

                    touchedFilesLogger.AddWritten(tempExeFilename);
                    touchedFilesLogger.AddWritten(finalOutputPath);
                    if (tempPdbFilename != null)
                    {
                        touchedFilesLogger.AddWritten(tempPdbFilename);
                        touchedFilesLogger.AddWritten(finalPdbFilePath);
                    }
                    if (finalXmlFilePath != null)
                    {
                        touchedFilesLogger.AddWritten(finalXmlFilePath);
                    }


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

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

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

                    using (var writer = new StreamWriter(writtenStream))
                    {
                        touchedFilesLogger.WriteWrittenPaths(writer);
                    }
                }


                return(Succeeded);
            }
            finally
            {
                if (tempExeFilename != null)
                {
                    TryDeleteFile(tempExeFilename, consoleOutput: null);
                }

                if (tempPdbFilename != null)
                {
                    TryDeleteFile(tempPdbFilename, consoleOutput: null);
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Emit the IL for the compilation into the specified stream.
        /// </summary>
        /// <param name="compilation">Compilation.</param>
        /// <param name="outputPath">Path of the file to which the compilation will be written.</param>
        /// <param name="pdbPath">Path of the file to which the compilation's debug info will be written.
        /// Also embedded in the output file.  Null to forego PDB generation.
        /// </param>
        /// <param name="xmlDocPath">Path of the file to which the compilation's XML documentation will be written.  Null to forego XML generation.</param>
        /// <param name="win32ResourcesPath">Path of the file from which the compilation's Win32 resources will be read (in RES format).
        /// Null to indicate that there are none.</param>
        /// <param name="manifestResources">List of the compilation's managed resources.  Null to indicate that there are none.</param>
        /// <param name="cancellationToken">To cancel the emit process.</param>
        /// <exception cref="ArgumentNullException">Compilation or path is null.</exception>
        /// <exception cref="ArgumentException">Path is empty or invalid.</exception>
        /// <exception cref="IOException">An error occurred while reading or writing a file.</exception>
        public static EmitResult Emit(
            this Compilation compilation,
            string outputPath,
            string?pdbPath            = null,
            string?xmlDocPath         = null,
            string?win32ResourcesPath = null,
            IEnumerable <ResourceDescription>?manifestResources = null,
            CancellationToken cancellationToken = default
            )
        {
            if (compilation == null)
            {
                throw new ArgumentNullException(nameof(compilation));
            }

            using (
                var outputStream = FileUtilities.CreateFileStreamChecked(
                    File.Create,
                    outputPath,
                    nameof(outputPath)
                    )
                )
                using (
                    var pdbStream = (
                        pdbPath == null
                        ? null
                        : FileUtilities.CreateFileStreamChecked(
                            File.Create,
                            pdbPath,
                            nameof(pdbPath)
                            )
                        )
                    )
                    using (
                        var xmlDocStream = (
                            xmlDocPath == null
                        ? null
                        : FileUtilities.CreateFileStreamChecked(
                                File.Create,
                                xmlDocPath,
                                nameof(xmlDocPath)
                                )
                            )
                        )
                        using (
                            var win32ResourcesStream = (
                                win32ResourcesPath == null
                        ? null
                        : FileUtilities.CreateFileStreamChecked(
                                    File.OpenRead,
                                    win32ResourcesPath,
                                    nameof(win32ResourcesPath)
                                    )
                                )
                            )
                        {
                            return(compilation.Emit(
                                       outputStream,
                                       pdbStream: pdbStream,
                                       xmlDocumentationStream: xmlDocStream,
                                       win32Resources: win32ResourcesStream,
                                       manifestResources: manifestResources,
                                       options: new EmitOptions(pdbFilePath: pdbPath),
                                       cancellationToken: cancellationToken
                                       ));
                        }
        }