Example #1
0
        Assembly CompileCode(string scriptText, string scriptFile)
        {
            string tempScriptFile = null;

            try
            {
                if (this.IsDebug)
                {
                    // Excellent example of debugging support
                    // http://www.michalkomorowski.com/2016/10/roslyn-how-to-create-custom-debuggable_27.html

                    if (scriptFile == null)
                    {
                        tempScriptFile = CSScript.GetScriptTempFile();
                        File.WriteAllText(tempScriptFile, scriptText, Encoding.UTF8);
                    }

                    scriptText = $"#line 1 \"{scriptFile ?? tempScriptFile}\"{Environment.NewLine}" + scriptText;
                }

                var options = CompilerSettings;
                if (!IsDebug)
                {
                    // There is a Roslyn bug that prevents emitting debug symbols if file path is specified. And fails
                    // the whole compilation:
                    // It triggers "error CS8055: Cannot emit debug information for a source text without encoding."
                    // Thus disable setting the source path until Roslyn is fixed.
                    options = CompilerSettings.WithFilePath(scriptFile ?? tempScriptFile);
                }

                var compilation = CSharpScript.Create(scriptText, options)
                                  .GetCompilation();

                if (this.IsDebug)
                {
                    compilation = compilation.WithOptions(compilation.Options
                                                          .WithOptimizationLevel(OptimizationLevel.Debug)
                                                          .WithOutputKind(OutputKind.DynamicallyLinkedLibrary));
                }

                using (var pdb = new MemoryStream())
                    using (var asm = new MemoryStream())
                    {
                        var emitOptions = new EmitOptions(false, DebugInformationFormat.PortablePdb);

                        EmitResult result;
                        if (IsDebug)
                        {
                            result = compilation.Emit(asm, pdb, options: emitOptions);
                        }
                        else
                        {
                            result = compilation.Emit(asm);
                        }

                        if (!result.Success)
                        {
                            IEnumerable <Diagnostic> failures = result.Diagnostics.Where(d => d.IsWarningAsError ||
                                                                                         d.Severity == DiagnosticSeverity.Error);

                            var message = new StringBuilder();
                            foreach (Diagnostic diagnostic in failures)
                            {
                                string error_location = "";
                                if (diagnostic.Location.IsInSource)
                                {
                                    var error_pos = diagnostic.Location.GetLineSpan().StartLinePosition;

                                    int error_line   = error_pos.Line + 1;
                                    int error_column = error_pos.Character + 1;

                                    // the actual source contains an injected '#line' directive f compiled with debug symbols
                                    if (IsDebug)
                                    {
                                        error_line--;
                                    }

                                    error_location = $"{diagnostic.Location.SourceTree.FilePath}({error_line},{ error_column}): ";
                                }
                                message.AppendLine($"{error_location}error {diagnostic.Id}: {diagnostic.GetMessage()}");
                            }
                            var errors = message.ToString();
                            throw new CompilerException(errors);
                        }
                        else
                        {
                            asm.Seek(0, SeekOrigin.Begin);
                            if (IsDebug)
                            {
                                pdb.Seek(0, SeekOrigin.Begin);
                                return(AppDomain.CurrentDomain.Load(asm.GetBuffer(), pdb.GetBuffer()));
                            }
                            else
                            {
                                return(AppDomain.CurrentDomain.Load(asm.GetBuffer()));
                            }
                        }
                    }
            }
            finally
            {
                if (this.IsDebug)
                {
                    CSScript.NoteTempFile(tempScriptFile);
                }
                else
                {
                    Utils.FileDelete(tempScriptFile, false);
                }
            }
        }
Example #2
0
        Assembly CompileCode(string scriptText, string scriptFile)
        {
            string tempScriptFile = null;

            try
            {
                if (this.IsDebug)
                {
                    if (scriptFile == null)
                    {
                        tempScriptFile = CSScript.GetScriptTempFile();
                        File.WriteAllText(tempScriptFile, scriptText);
                    }

                    scriptText = $"#line 1 \"{scriptFile ?? tempScriptFile}\"{Environment.NewLine}" + scriptText;
                }

                var compilation = CSharpScript.Create(scriptText, CompilerSettings
                                                      .WithFilePath(scriptFile ?? tempScriptFile))
                                  .GetCompilation();

                if (this.IsDebug)
                {
                    compilation = compilation.WithOptions(compilation.Options
                                                          .WithOptimizationLevel(OptimizationLevel.Debug)
                                                          .WithOutputKind(OutputKind.DynamicallyLinkedLibrary));
                }

                using (var pdb = new MemoryStream())
                    using (var asm = new MemoryStream())
                    {
                        var emitOptions = new EmitOptions(false, DebugInformationFormat.PortablePdb);

                        EmitResult result;
                        if (IsDebug)
                        {
                            result = compilation.Emit(asm, pdb, options: emitOptions);
                        }
                        else
                        {
                            result = compilation.Emit(asm);
                        }

                        if (!result.Success)
                        {
                            IEnumerable <Diagnostic> failures = result.Diagnostics.Where(d => d.IsWarningAsError ||
                                                                                         d.Severity == DiagnosticSeverity.Error);

                            var message = new StringBuilder();
                            foreach (Diagnostic diagnostic in failures)
                            {
                                string error_location = "";
                                if (diagnostic.Location.IsInSource)
                                {
                                    var error_pos = diagnostic.Location.GetLineSpan().StartLinePosition;

                                    int error_line   = error_pos.Line + 1;
                                    int error_column = error_pos.Character + 1;

                                    // the actual source contains an injected '#line' directive f compiled with debug symbols
                                    if (IsDebug)
                                    {
                                        error_line--;
                                    }

                                    error_location = $"{diagnostic.Location.SourceTree.FilePath}({error_line},{ error_column}): ";
                                }
                                message.AppendLine($"{error_location}error {diagnostic.Id}: {diagnostic.GetMessage()}");
                            }
                            var errors = message.ToString();
                            throw new CompilerException(errors);
                        }
                        else
                        {
                            asm.Seek(0, SeekOrigin.Begin);
                            if (IsDebug)
                            {
                                pdb.Seek(0, SeekOrigin.Begin);
                                return(AppDomain.CurrentDomain.Load(asm.GetBuffer(), pdb.GetBuffer()));
                            }
                            else
                            {
                                return(AppDomain.CurrentDomain.Load(asm.GetBuffer()));
                            }
                        }
                    }
            }
            finally
            {
                if (this.IsDebug)
                {
                    CSScript.NoteTempFile(tempScriptFile);
                }
                else
                {
                    Utils.FileDelete(tempScriptFile, false);
                }
            }
        }