public void WriteResult(IFastJsonWriter writer, object result, IWorkSession session) { if (result == null) { writer.WriteValue((string)null); return; } var targetName = session.GetTargetName(); if (targetName == TargetNames.Ast) { var astTarget = _astTargets.GetValueOrDefault(session.LanguageName); astTarget.SerializeAst(result, writer, session); return; } if (targetName == TargetNames.Run) { _executor.Serialize((ExecutionResult)result, writer); return; } var decompiler = _decompilers[targetName]; using (var stream = (Stream)result) using (var stringWriter = writer.OpenString()) { decompiler.Decompile(stream, stringWriter); } }
public async Task <object> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken) { var targetName = session.GetTargetName(); if (targetName == TargetNames.Ast) { var astTarget = _astTargets.GetValueOrDefault(session.LanguageName); return(await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false)); } if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { return(null); } if (targetName == TargetNames.Verify) { return("✔️ Compilation completed."); } if (targetName != TargetNames.Run && !_decompilers.ContainsKey(targetName)) { throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch."); } MemoryStream assemblyStream = null; MemoryStream symbolStream = null; try { assemblyStream = _memoryStreamManager.GetStream(); if (targetName == TargetNames.Run) { symbolStream = _memoryStreamManager.GetStream(); } if (!await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false)) { assemblyStream.Dispose(); symbolStream?.Dispose(); return(null); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolStream?.Seek(0, SeekOrigin.Begin); if (targetName == TargetNames.Run) { return(_executor.Execute(assemblyStream, symbolStream, session)); } // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult() return(assemblyStream); } catch { assemblyStream?.Dispose(); symbolStream?.Dispose(); throw; } }
private string GetAndEnsureTargetName(IWorkSession session) { var targetName = session.GetTargetName(); if (targetName == null) { throw new InvalidOperationException("Target is not set on the session (timing issue?). Please try reloading."); } return(targetName); }
public void UpdateOutputKind(IWorkSession session, IList <Diagnostic>?diagnostics = null) { if (session.LanguageName != LanguageNames.CSharp) { return; } if (GlobalStatement == null) { return; // this branch does not support global statements } if (session.GetTargetName() == TargetNames.Run) { return; // must always use executable mode for Run } if (!session.Roslyn.Project.Documents.Single().TryGetSyntaxRoot(out var syntaxRoot)) { if (diagnostics != null) // we must update now, otherwise diagnostics will be incorrect { throw new InvalidOperationException("Syntax root was not cached."); } return; // will update later } // We can't always mark it as executable as it would require Main() to be present, // so we toggle conditionally. var shouldBeExecutable = syntaxRoot.ChildNodes().Any(n => n.IsKind(GlobalStatement.Value)); var isExecutable = session.Roslyn.Project.CompilationOptions?.OutputKind == ConsoleApplication; if (isExecutable == shouldBeExecutable) { return; } diagnostics?.RemoveWhere( d => shouldBeExecutable ? (d.Id == DiagnosticIds.TopLevelNotInExecutable || d.Id == DiagnosticIds.TopLevelNotInExecutableOld) : (d.Id == DiagnosticIds.NoStaticMain) ); var project = session.Roslyn.Project; session.Roslyn.Project = project.WithCompilationOptions( project.CompilationOptions !.WithOutputKind(shouldBeExecutable ? ConsoleApplication : DynamicallyLinkedLibrary) ); }
public void WriteResult(IFastJsonWriter writer, object result, IWorkSession session) { if (result == null) { writer.WriteValue((string?)null); return; } if (result is string s) { writer.WriteValue(s); return; } var targetName = session.GetTargetName(); if (targetName == TargetNames.Ast) { var astTarget = _astTargets[session.LanguageName]; astTarget.SerializeAst(result, writer, session); return; } if (targetName == TargetNames.Explain) { _explainer.Serialize((ExplanationResult)result, writer); return; } if (targetName == TargetNames.Run) { _executor.Serialize((ExecutionResult)result, writer); return; } var decompiler = _decompilers[targetName]; using (var streams = (CompilationStreamPair)result) using (var stringWriter = writer.OpenString()) { decompiler.Decompile(streams, stringWriter); } }
public async Task <object?> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken) { var targetName = session.GetTargetName(); if (targetName == TargetNames.Ast || targetName == TargetNames.Explain) { var astTarget = _astTargets[session.LanguageName]; var ast = await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false); if (targetName == TargetNames.Explain) { return(await _explainer.ExplainAsync(ast, session, cancellationToken).ConfigureAwait(false)); } return(ast); } if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { return(null); } if (targetName == LanguageNames.VisualBasic) { return(VisualBasicNotAvailable); } if (targetName != TargetNames.Run && targetName != TargetNames.Verify && !_decompilers.ContainsKey(targetName)) { throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch."); } MemoryStream?assemblyStream = null; MemoryStream?symbolStream = null; try { assemblyStream = _memoryStreamManager.GetStream(); if (targetName == TargetNames.Run || targetName == TargetNames.IL) { symbolStream = _memoryStreamManager.GetStream(); } var compiled = await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false); if (!compiled.assembly) { assemblyStream.Dispose(); symbolStream?.Dispose(); return(null); } if (targetName == TargetNames.Verify) { assemblyStream.Dispose(); symbolStream?.Dispose(); return("✔️ Compilation completed."); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolStream?.Seek(0, SeekOrigin.Begin); var streams = new CompilationStreamPair(assemblyStream, compiled.symbols ? symbolStream : null); if (targetName == TargetNames.Run) { return(_executor.Execute(streams, session)); } // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult() return(streams); } catch { assemblyStream?.Dispose(); symbolStream?.Dispose(); throw; } }