diff --git a/CSharpRepl.Tests/CSharpRepl.Tests.csproj b/CSharpRepl.Tests/CSharpRepl.Tests.csproj index 9535a73..b70ef7b 100644 --- a/CSharpRepl.Tests/CSharpRepl.Tests.csproj +++ b/CSharpRepl.Tests/CSharpRepl.Tests.csproj @@ -3,7 +3,7 @@ true preview - net7.0 + net8.0 CSDiscordService.Tests @@ -11,11 +11,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers diff --git a/CSharpRepl.Tests/EvalTests.cs b/CSharpRepl.Tests/EvalTests.cs index 50bca2c..8cab99a 100644 --- a/CSharpRepl.Tests/EvalTests.cs +++ b/CSharpRepl.Tests/EvalTests.cs @@ -69,15 +69,21 @@ public EvalTests(ITestOutputHelper outputHelper) [InlineData(@"var a = ""thing""; return a;", "thing", "string")] [InlineData("Math.Pow(1,2)", 1D, "double")] [InlineData(@"Enumerable.Range(0,1).Select(a=>""@"");", null, null)] - [InlineData("typeof(int)", "System.Int32, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "RuntimeType")] + [InlineData("typeof(int)", "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "RuntimeType")] [InlineData("Assembly.GetExecutingAssembly()", true, "RuntimeAssembly")] [InlineData("TimeSpan.FromSeconds(2310293892)", "26739.12:18:12", "TimeSpan")] + [InlineData("float.PositiveInfinity", "Infinity", "float")] + [InlineData("List l = [1, 2, 3]; l", "[1,2,3]", "List")] public async Task Eval_WellFormattedCodeExecutes(string expr, object expected, string type) { var (result, statusCode) = await Execute(expr); var res = result.ReturnValue as JsonElement?; object convertedValue; - if (expected is string || expected is null) + if (res.Value.ValueKind == JsonValueKind.Array) + { + convertedValue = res.Value.GetRawText(); + } + else if (expected is string || expected is null) { convertedValue = res?.GetString(); } @@ -85,6 +91,11 @@ public async Task Eval_WellFormattedCodeExecutes(string expr, object expected, s { convertedValue = res.HasValue; } + else if (result.ReturnTypeName == "RuntimeAssembly") + { + // nothing to do here, value is random for this test + convertedValue = expected; + } else { var value = res.Value.GetRawText(); @@ -185,8 +196,8 @@ public async Task Eval_ConsoleOutputIsCaptured(string expr, string consoleOut, o [Fact] public async Task Eval_LoadDLLThatExposesTypeOfADependency() { - var expr = "#nuget CK.ActivityMonitor\nvar m = new ActivityMonitor();"; - var (_, statusCode) = await Execute(expr); + var expr = "#nuget CK.ActivityMonitor\nvar m = new CK.Core.ActivityMonitor();"; + var (result, statusCode) = await Execute(expr); Assert.Equal(HttpStatusCode.OK, statusCode); } diff --git a/CSharpRepl/CSharpRepl.csproj b/CSharpRepl/CSharpRepl.csproj index 724cecf..393ce44 100644 --- a/CSharpRepl/CSharpRepl.csproj +++ b/CSharpRepl/CSharpRepl.csproj @@ -3,7 +3,7 @@ true preview - net7.0 + net8.0 Exe 03629088-8bb9-4faf-8162-debf93066bc4 @@ -14,12 +14,10 @@ - - - - - - + + + + diff --git a/CSharpRepl/Eval/DisassemblyService.cs b/CSharpRepl/Eval/DisassemblyService.cs index 4ee8926..ea102c3 100644 --- a/CSharpRepl/Eval/DisassemblyService.cs +++ b/CSharpRepl/Eval/DisassemblyService.cs @@ -2,7 +2,6 @@ using ICSharpCode.Decompiler.Disassembler; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Mono.Cecil; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -15,6 +14,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; +using ICSharpCode.Decompiler.Metadata; namespace CSDiscordService.Eval { @@ -65,7 +65,7 @@ public string GetIl(string code) namespace Eval {{ - public class Code + public unsafe class Code {{ public object Main() {{ @@ -75,17 +75,22 @@ public object Main() }} "; - var opts = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview).WithKind(SourceCodeKind.Regular); + var opts = CSharpParseOptions.Default + .WithLanguageVersion(LanguageVersion.Preview) + .WithKind(SourceCodeKind.Regular); var scriptSyntaxTree = CSharpSyntaxTree.ParseText(toExecute, opts); - var compOpts = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithOptimizationLevel(OptimizationLevel.Debug).WithAllowUnsafe(true).WithPlatform(Platform.AnyCpu); + var compOpts = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + .WithOptimizationLevel(OptimizationLevel.Debug) + .WithAllowUnsafe(true) + .WithPlatform(Platform.AnyCpu); - var compilation = CSharpCompilation.Create(Guid.NewGuid().ToString(), options: compOpts, references: References).AddSyntaxTrees(scriptSyntaxTree); + var compilation = CSharpCompilation.Create(Guid.NewGuid().ToString(), options: compOpts, references: References) + .AddSyntaxTrees(scriptSyntaxTree); var sb = new StringBuilder(); - using var pdb = new MemoryStream(); using var dll = new MemoryStream(); - var result = compilation.Emit(dll, pdb); + var result = compilation.Emit(dll); if (!result.Success) { sb.AppendLine("Emit Failed"); @@ -94,19 +99,22 @@ public object Main() else { dll.Seek(0, SeekOrigin.Begin); - using var module = ModuleDefinition.ReadModule(dll); + using var file = new PEFile(compilation.AssemblyName!, dll); using var writer = new StringWriter(sb); - module.Name = compilation.AssemblyName; var plainOutput = new PlainTextOutput(writer); var rd = new ReflectionDisassembler(plainOutput, CancellationToken.None) { DetectControlStructure = true }; var ignoredMethods = new[] { ".ctor" }; - var methods = module.Types.SelectMany(a => a.Methods).Where(a => !ignoredMethods.Contains(a.Name)); + var methods = file.Metadata.MethodDefinitions.Where(a => + { + var methodName = file.Metadata.GetString(file.Metadata.GetMethodDefinition(a).Name); + return !ignoredMethods.Contains(methodName); + }); foreach (var method in methods) { - rd.DisassembleMethod(method); + rd.DisassembleMethod(file, method); plainOutput.WriteLine(); } } diff --git a/CSharpRepl/Eval/NugetDirectiveProcessor.cs b/CSharpRepl/Eval/NugetDirectiveProcessor.cs index 5bd73a5..117590b 100644 --- a/CSharpRepl/Eval/NugetDirectiveProcessor.cs +++ b/CSharpRepl/Eval/NugetDirectiveProcessor.cs @@ -32,7 +32,7 @@ public async Task PreProcess(string directive, ScriptExecutionContext context, A { var actionLogger = new NugetLogger(logger); var nugetDirective = NugetPreProcessorDirective.Parse(directive); - string frameworkName = Assembly.GetEntryAssembly()!.GetCustomAttributes(true) + string frameworkName = typeof(NugetDirectiveProcessor).Assembly.GetCustomAttributes(true) .OfType() .Select(x => x.FrameworkName) .FirstOrDefault()!; diff --git a/CSharpRepl/Eval/ResultModels/EvalResult.cs b/CSharpRepl/Eval/ResultModels/EvalResult.cs index 0a2b83e..28daabc 100644 --- a/CSharpRepl/Eval/ResultModels/EvalResult.cs +++ b/CSharpRepl/Eval/ResultModels/EvalResult.cs @@ -87,6 +87,7 @@ public override string ToString() IncludeFields = true, PropertyNameCaseInsensitive = true, ReferenceHandler = ReferenceHandler.IgnoreCycles, + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new TypeJsonConverter(), new TypeInfoJsonConverter(), new RuntimeTypeHandleJsonConverter(), new TypeJsonConverterFactory(), new AssemblyJsonConverter(), diff --git a/CSharpRepl/Infrastructure/JsonFormatters/TypeJsonConverter.cs b/CSharpRepl/Infrastructure/JsonFormatters/TypeJsonConverter.cs index 3e769b3..f741697 100644 --- a/CSharpRepl/Infrastructure/JsonFormatters/TypeJsonConverter.cs +++ b/CSharpRepl/Infrastructure/JsonFormatters/TypeJsonConverter.cs @@ -122,7 +122,7 @@ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializer public class AssemblyJsonConverterFactory : JsonConverterFactory { - public override bool CanConvert(Type typeToConvert) => typeToConvert == Type.GetType("System.RuntimeAssembly"); + public override bool CanConvert(Type typeToConvert) => typeToConvert == Type.GetType("System.Reflection.RuntimeAssembly"); public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { return new RuntimeAssemblyJsonConverter(); diff --git a/CSharpRepl/Startup.cs b/CSharpRepl/Startup.cs index aed7451..055ef0a 100644 --- a/CSharpRepl/Startup.cs +++ b/CSharpRepl/Startup.cs @@ -36,6 +36,7 @@ public void ConfigureServices(IServiceCollection services) IncludeFields = true, PropertyNameCaseInsensitive = true, ReferenceHandler = ReferenceHandler.IgnoreCycles, + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, Converters = { new TypeJsonConverter(), new TypeInfoJsonConverter(), new RuntimeTypeHandleJsonConverter(), new TypeJsonConverterFactory(), new AssemblyJsonConverter(), @@ -57,6 +58,7 @@ public void ConfigureServices(IServiceCollection services) o.JsonSerializerOptions.IncludeFields = true; o.JsonSerializerOptions.PropertyNameCaseInsensitive = true; o.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; + o.JsonSerializerOptions.NumberHandling |= JsonNumberHandling.AllowNamedFloatingPointLiterals; o.JsonSerializerOptions.Converters.Add(new TypeJsonConverter()); o.JsonSerializerOptions.Converters.Add(new TypeInfoJsonConverter()); o.JsonSerializerOptions.Converters.Add(new RuntimeTypeHandleJsonConverter()); diff --git a/Dockerfile b/Dockerfile index a199717..0da8f30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 as dotnet-build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 as dotnet-build ARG TARGETPLATFORM ARG BUILDPLATFORM WORKDIR /src @@ -10,7 +10,7 @@ RUN dotnet build --configuration Release --no-restore #RUN dotnet test --configuration Release CSharpRepl.Tests/CSharpRepl.Tests.csproj --no-build --no-restore RUN dotnet publish --configuration Release CSharpRepl/CSharpRepl.csproj --no-build --no-restore -o /app -FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0 +FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:8.0 ARG TARGETPLATFORM ARG BUILDPLATFORM WORKDIR /app