예제 #1
0
        private static string GetGeneratedOutput(string source)
        {
            var syntaxTree = CSharpSyntaxTree.ParseText(source);

            var references = new List <MetadataReference>();

            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                if (!assembly.IsDynamic)
                {
                    references.Add(MetadataReference.CreateFromFile(assembly.Location));
                }
            }

            var compilation = CSharpCompilation.Create("foo", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            System.Collections.Immutable.ImmutableArray <Diagnostic> diagnostics = compilation.GetDiagnostics();
            Assert.False(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + diagnostics.FirstOrDefault()?.GetMessage());

            var generator = new Generator();

            var output = generator.GetGeneratedSource(compilation);

            return(output);
        }
예제 #2
0
        public async Task EvaluateAsync(CommandContext ctx,
                                        [RemainingText, Description("Code to evaluate.")] string code)
        {
            if (string.IsNullOrWhiteSpace(code))
            {
                throw new InvalidCommandUsageException("Code missing.");
            }

            int cs1 = code.IndexOf("```") + 3;
            int cs2 = code.LastIndexOf("```");

            if (cs1 == -1 || cs2 == -1)
            {
                throw new InvalidCommandUsageException("You need to wrap the code into a code block.");
            }
            code = code.Substring(cs1, cs2 - cs1);

            var emb = new DiscordEmbedBuilder {
                Title = "Evaluating...",
                Color = this.ModuleColor
            };

            DiscordMessage msg = await ctx.RespondAsync(embed : emb.Build());

            var           globals = new EvaluationEnvironment(ctx);
            ScriptOptions sopts   = ScriptOptions.Default
                                    .WithImports("System", "System.Collections.Generic", "System.Linq", "System.Net.Http",
                                                 "System.Net.Http.Headers", "System.Reflection", "System.Text", "System.Text.RegularExpressions",
                                                 "System.Threading.Tasks", "DSharpPlus", "DSharpPlus.CommandsNext", "DSharpPlus.Entities",
                                                 "DSharpPlus.Interactivity")
                                    .WithReferences(AppDomain.CurrentDomain.GetAssemblies().Where(xa => !xa.IsDynamic && !string.IsNullOrWhiteSpace(xa.Location)));

            var             sw1     = Stopwatch.StartNew();
            Script <object> snippet = CSharpScript.Create(code, sopts, typeof(EvaluationEnvironment));

            System.Collections.Immutable.ImmutableArray <Diagnostic> diag = snippet.Compile();
            sw1.Stop();

            if (diag.Any(d => d.Severity == DiagnosticSeverity.Error))
            {
                emb = new DiscordEmbedBuilder {
                    Title       = "Compilation failed",
                    Description = $"Compilation failed after {sw1.ElapsedMilliseconds.ToString("#,##0")}ms with {diag.Length} errors.",
                    Color       = DiscordColor.Red
                };

                foreach (Diagnostic d in diag.Take(3))
                {
                    FileLinePositionSpan ls = d.Location.GetLineSpan();
                    emb.AddField($"Error at line: {ls.StartLinePosition.Line}, {ls.StartLinePosition.Character}", Formatter.InlineCode(d.GetMessage()));
                }

                if (diag.Length > 3)
                {
                    emb.AddField("Some errors were omitted", $"{diag.Length - 3} errors not displayed");
                }

                if (!(msg is null))
                {
                    msg = await msg.ModifyAsync(embed : emb.Build());
                }
                return;
            }

            Exception            exc = null;
            ScriptState <object> css = null;
            var sw2 = Stopwatch.StartNew();

            try {
                css = await snippet.RunAsync(globals);

                exc = css.Exception;
            } catch (Exception e) {
                exc = e;
            }
            sw2.Stop();

            if (!(exc is null))
            {
                emb = new DiscordEmbedBuilder {
                    Title       = "Execution failed",
                    Description = $"Execution failed after {sw2.ElapsedMilliseconds.ToString("#,##0")}ms with {Formatter.InlineCode($"{exc.GetType()} : {exc.Message}")}.",
                    Color       = this.ModuleColor
                };

                if (!(msg is null))
                {
                    msg = await msg.ModifyAsync(embed : emb.Build());
                }
                return;
            }

            emb = new DiscordEmbedBuilder {
                Title = "Evaluation successful",
                Color = DiscordColor.Aquamarine
            };

            emb.AddField("Result", css.ReturnValue is null ? "No value returned" : css.ReturnValue.ToString(), false);
            emb.AddField("Compilation time", string.Concat(sw1.ElapsedMilliseconds.ToString("#,##0"), "ms"), true);
            emb.AddField("Execution time", string.Concat(sw2.ElapsedMilliseconds.ToString("#,##0"), "ms"), true);

            if (!(css.ReturnValue is null))
            {
                emb.AddField("Return type", css.ReturnValue.GetType().ToString(), true);
            }

            if (!(msg is null))
            {
                await msg.ModifyAsync(embed : emb.Build());
            }