-
-
Notifications
You must be signed in to change notification settings - Fork 325
/
RoslynInterfaceBuilder.cs
88 lines (73 loc) · 2.58 KB
/
RoslynInterfaceBuilder.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
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Eto.Forms;
using Microsoft.CodeAnalysis;
namespace Eto.Designer.Builders
{
public abstract class RoslynInterfaceBuilder : BaseCompiledInterfaceBuilder
{
protected virtual IEnumerable<string> GetReferences()
{
string referenceDir = GetReferenceAssembliesFolder();
if (string.IsNullOrEmpty(referenceDir))
throw new InvalidOperationException("Cannot find reference assemblies folder");
yield return Path.Combine(referenceDir, "mscorlib.dll");
yield return Path.Combine(referenceDir, "System.dll");
yield return Path.Combine(referenceDir, "System.Core.dll");
//yield return typeof(Control).Assembly.Location;
//yield return typeof(System.Collections.Immutable.ImmutableList).Assembly.Location;
/* Needed for PCL version of Eto.dll
*/
var facadeDir = Path.Combine(referenceDir, "Facades");
if (Directory.Exists(facadeDir))
{
foreach (var file in Directory.GetFiles(facadeDir))
{
yield return file;
}
}
}
protected abstract SyntaxTree ParseText(string code);
protected override CompileResult Compile(string outputFile, IEnumerable<string> references, string code, out Assembly generatedAssembly)
{
var syntaxTree = ParseText(code);
string assemblyName = Path.GetRandomFileName();
var refMetadata = GetReferences().Select(r => MetadataReference.CreateFromFile(r)).ToList();
if (references != null)
{
foreach (var reference in references)
{
if (File.Exists(reference))
refMetadata.Add(MetadataReference.CreateFromFile(reference));
}
}
var compilation = CreateCompilation(syntaxTree, assemblyName, refMetadata);
using (var ms = new MemoryStream())
{
var result = compilation.Emit(ms);
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (var diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
generatedAssembly = null;
return new CompileResult { Success = false, Errors = failures.Select(r => r.GetMessage()).ToList() };
}
else
{
ms.Seek(0, SeekOrigin.Begin);
generatedAssembly = Assembly.Load(ms.ToArray());
return new CompileResult { Success = true };
}
}
}
protected abstract Compilation CreateCompilation(SyntaxTree syntaxTree, string assemblyName, IEnumerable<PortableExecutableReference> references);
}
}