Last active
November 28, 2021 09:29
-
-
Save jessenich/5fdce8a155edf207ce45f65634c771af to your computer and use it in GitHub Desktop.
Rebuild C# Syntax Tree
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
public static class CodeInjector { | |
static void InjectCode(string appDir) { | |
if (string.IsNullOrWhiteSpace(appDir)) | |
throw new ArgumentNullException(nameof(appDir)); | |
if (!Directory.Exists(appDir)) | |
throw new IOException("Directory does not exist"); | |
var programFilePath = Path.Combine(appDir, "Program.cs".Normalize(NormalizationForm.FormC)); | |
if (!File.Exists(programFilePath)) | |
throw new IOException("File does not exist"); | |
var programTree = CSharpSyntaxTree.ParseText(File.ReadAllText(programFilePath)); | |
var newContent = string.Empty; | |
var mainMethod = programTree.GetRoot().DescendantNodes() | |
.OfType<MethodDeclarationSyntax>() | |
.FirstOrDefault(method => method.Identifier.ValueText == "Main"); | |
if (mainMethod is null) { | |
// Handles project templates that use top-level statements instead of a Main method | |
var nodes = programTree.GetRoot().ChildNodes(); | |
var usingDirectives = nodes.OfType<UsingDirectiveSyntax>(); | |
var otherNodes = nodes.Except(usingDirectives); | |
var builder = new StringBuilder(); | |
foreach (var usingDir in usingDirectives) | |
builder.Append(usingDir.ToFullString()); | |
builder.AppendLine("var response = await new System.Net.Http.HttpClient().GetAsync(\"https://www.google.com\");") | |
.AppendLine("response.EnsureSuccessStatusCode();"); | |
foreach (var syntaxNode in otherNodes) | |
builder.Append(syntaxNode.ToFullString()); | |
newContent = builder.ToString(); | |
} | |
else { | |
var testHttpsConnectivityStatement = SyntaxFactory.ParseStatement( | |
"var task = new System.Net.Http.HttpClient().GetAsync(\"https://www.microsoft.com\");" + | |
"task.Wait();" + | |
"task.Result.EnsureSuccessStatusCode();"); | |
var newMainMethod = mainMethod.InsertNodesBefore( | |
mainMethod.Body.ChildNodes().First(), | |
new SyntaxNode[] { testHttpsConnectivityStatement }); | |
var newRoot = programTree.GetRoot().ReplaceNode(mainMethod, newMainMethod); | |
newContent = newRoot.ToFullString(); | |
} | |
File.WriteAllText(programFilePath, newContent); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment