-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathDebugProgramTemplate.cs
115 lines (96 loc) · 3.67 KB
/
DebugProgramTemplate.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Cometary;
[CompilerGenerated]
internal static class DebugProgram
{
// This file will be modified by the DebuggingEditor and injected into target assemblies.
// Metadata, such as the assembly name and the references, will be set to the following fields,
// and used to reproduce a CSharpCompilation similar to the one used to generate the original compilation.
// Except this time, a debugger will be awaiting.
#region Logic
public const string AssemblyName = "";
public const string References = "";
public const string Files = "";
public const string ErrorFile = "";
public const bool Written = false;
public const bool BreakAtEnd = false;
public const bool BreakAtStart = false;
public static bool IsWrittenToDisk => Written;
public static bool ShouldBreakAtEnd => BreakAtEnd;
public static bool ShouldBreakAtStart => BreakAtStart;
public static int Main(string[] args)
{
try
{
DiagnosticAnalyzer analyzer = new CometaryAnalyzer();
CSharpParseOptions parseOptions = new CSharpParseOptions(preprocessorSymbols: new[] { "DEBUGGING" });
if (IsWrittenToDisk && ShouldBreakAtStart)
Debugger.Break();
CompilationWithAnalyzers compilation = CSharpCompilation.Create(
AssemblyName + "+Debugging",
Files.Split(';').Select(x => CSharpSyntaxTree.ParseText(File.ReadAllText(x), parseOptions)),
References.Split(';').Select(x => MetadataReference.CreateFromFile(x))
).WithAnalyzers(ImmutableArray.Create(analyzer));
ExecuteAsync(compilation).Wait();
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
Console.Error.WriteLine();
Console.Error.WriteLine(e.StackTrace);
Console.ReadKey();
return 1;
}
}
public static async Task ExecuteAsync(CompilationWithAnalyzers compilation)
{
await compilation.GetAllDiagnosticsAsync();
using (MemoryStream assemblyStream = new MemoryStream())
using (MemoryStream pdbStream = new MemoryStream())
{
var result = compilation.Compilation.Emit(assemblyStream, pdbStream);
if (!IsWrittenToDisk || !ShouldBreakAtEnd)
return;
Diagnostic[] diagnostics = result.Diagnostics.OrderByDescending(x => x.Severity).ToArray();
if (result.Success)
{
Success(diagnostics);
return;
}
string[] errors = diagnostics.TakeWhile(x => x.Severity == DiagnosticSeverity.Error).Select(x => x.ToString()).ToArray();
try
{
File.WriteAllLines(ErrorFile, errors);
}
finally
{
Failure(diagnostics, errors);
}
}
}
#endregion
public static void Success(Diagnostic[] diagnostics)
{
// If you got here, that means the compilation was a success!
//
Debugger.Break();
}
public static void Failure(Diagnostic[] diagnostics, string[] errors)
{
// If you got here, that means the compilation failed...
// You can inspect the errors via the debugger, or in the error file available at:
// %ERRORFILE%
//
Debugger.Break();
}
}