Skip to content

Instantly share code, notes, and snippets.

@jessenich
Last active November 28, 2021 09:29
Show Gist options
  • Save jessenich/5fdce8a155edf207ce45f65634c771af to your computer and use it in GitHub Desktop.
Save jessenich/5fdce8a155edf207ce45f65634c771af to your computer and use it in GitHub Desktop.
Rebuild C# Syntax Tree
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