Skip to content

Commit ca43877

Browse files
committed
added engine based on new roslyn bits from the fork
1 parent 5ccbcb8 commit ca43877

11 files changed

+660
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
using System.Reflection;
2+
3+
[assembly: AssemblyTitle("ScriptCs.Engine.Roslyn")]
4+
[assembly: AssemblyDescription("ScriptCs.Engine.Roslyn provides a Roslyn-based script engine for scriptcs.")]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0"?>
2+
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
3+
<metadata>
4+
<id>ScriptCs.Engine.Roslyn</id>
5+
<version>$version$</version>
6+
<authors>Glenn Block, Filip Wojcieszyn, Justin Rusbatch, Kristian Hellang, Damian Schenkelman, Adam Ralph</authors>
7+
<owners>Glenn Block, Justin Rusbatch, Filip Wojcieszyn</owners>
8+
<licenseUrl>https://github.com/scriptcs/scriptcs/blob/master/LICENSE.md</licenseUrl>
9+
<projectUrl>http://scriptcs.net</projectUrl>
10+
<iconUrl>http://www.gravatar.com/avatar/5c754f646971d8bc800b9d4057931938.png?s=120</iconUrl>
11+
<description>ScriptCs.Engine.Roslyn provides a Roslyn-based script engine for scriptcs.</description>
12+
<tags>roslyn csx script scriptcs</tags>
13+
<frameworkAssemblies>
14+
<frameworkAssembly assemblyName="System.ComponentModel.Composition" targetFramework="net45" />
15+
</frameworkAssemblies>
16+
<dependencies>
17+
<dependency id="ScriptCs.Core" version="$version$" />
18+
</dependencies>
19+
</metadata>
20+
</package>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using ScriptCs.Contracts;
2+
3+
namespace ScriptCs.Engine.Roslyn
4+
{
5+
[Module("roslyn")]
6+
public class RoslynModule : IModule
7+
{
8+
public void Initialize(IModuleConfiguration config)
9+
{
10+
Guard.AgainstNullArgument("config", config);
11+
12+
//if (!config.Overrides.ContainsKey(typeof(IScriptEngine)))
13+
//{
14+
//var engineType = config.Cache ? typeof(RoslynScriptPersistentEngine) : typeof(RoslynScriptEngine);
15+
//engineType = config.Debug ? typeof(RoslynScriptInMemoryEngine) : engineType;
16+
var engineType = config.IsRepl ? typeof(RoslynReplEngine) : typeof(RoslynScriptEngine);
17+
config.Overrides[typeof(IScriptEngine)] = engineType;
18+
//}
19+
}
20+
}
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Common.Logging;
4+
using Microsoft.CodeAnalysis.Scripting;
5+
using ScriptCs.Contracts;
6+
7+
namespace ScriptCs.Engine.Roslyn
8+
{
9+
public class RoslynReplEngine : RoslynScriptEngine, IReplEngine
10+
{
11+
public RoslynReplEngine(IScriptHostFactory scriptHostFactory, ILog logger)
12+
: base(scriptHostFactory, logger)
13+
{
14+
}
15+
16+
public ICollection<string> GetLocalVariables(ScriptPackSession scriptPackSession)
17+
{
18+
if (scriptPackSession != null && scriptPackSession.State.ContainsKey(SessionKey))
19+
{
20+
var sessionState = (SessionState<ScriptState>) scriptPackSession.State[SessionKey];
21+
return sessionState.Session.Variables.Select(x => string.Format("{0} {1}", x.Type, x.Name)).ToArray();
22+
}
23+
24+
return new string[0];
25+
}
26+
27+
protected override ScriptResult Execute(string code, object globals, SessionState<ScriptState> sessionState)
28+
{
29+
return string.IsNullOrWhiteSpace(FileName) && !IsCompleteSubmission(code)
30+
? ScriptResult.Incomplete
31+
: base.Execute(code, globals, sessionState);
32+
}
33+
}
34+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Reflection;
5+
using Common.Logging;
6+
7+
using Roslyn.Scripting;
8+
using ScriptCs.Contracts;
9+
using ScriptCs.Exceptions;
10+
11+
namespace ScriptCs.Engine.Roslyn
12+
{
13+
public abstract class RoslynScriptCompilerEngine : RoslynScriptEngine
14+
{
15+
private const string CompiledScriptClass = "Submission#0";
16+
17+
private const string CompiledScriptMethod = "<Factory>";
18+
19+
protected RoslynScriptCompilerEngine(IScriptHostFactory scriptHostFactory, ILog logger)
20+
: base(scriptHostFactory, logger)
21+
{
22+
}
23+
24+
protected abstract bool ShouldCompile();
25+
26+
protected abstract Assembly LoadAssembly(byte[] exeBytes, byte[] pdbBytes);
27+
28+
protected abstract Assembly LoadAssemblyFromCache();
29+
30+
protected override ScriptResult Execute(string code, Session session)
31+
{
32+
Guard.AgainstNullArgument("session", session);
33+
34+
return ShouldCompile()
35+
? CompileAndExecute(code, session)
36+
: InvokeEntryPointMethod(session, LoadAssemblyFromCache());
37+
}
38+
39+
private ScriptResult CompileAndExecute(string code, Session session)
40+
{
41+
Logger.Debug("Compiling submission");
42+
try
43+
{
44+
var submission = session.CompileSubmission<object>(code);
45+
46+
using (var exeStream = new MemoryStream())
47+
using (var pdbStream = new MemoryStream())
48+
{
49+
var result = submission.Compilation.Emit(exeStream, pdbStream: pdbStream);
50+
51+
if (result.Success)
52+
{
53+
Logger.Debug("Compilation was successful.");
54+
55+
var assembly = LoadAssembly(exeStream.ToArray(), pdbStream.ToArray());
56+
57+
return InvokeEntryPointMethod(session, assembly);
58+
}
59+
60+
var errors = string.Join(Environment.NewLine, result.Diagnostics.Select(x => x.ToString()));
61+
62+
Logger.ErrorFormat("Error occurred when compiling: {0})", errors);
63+
64+
return new ScriptResult(compilationException: new ScriptCompilationException(errors));
65+
}
66+
}
67+
catch (Exception compileException)
68+
{
69+
//we catch Exception rather than CompilationErrorException because there might be issues with assembly loading too
70+
return new ScriptResult(compilationException: new ScriptCompilationException(compileException.Message, compileException));
71+
}
72+
}
73+
74+
private ScriptResult InvokeEntryPointMethod(Session session, Assembly assembly)
75+
{
76+
Logger.Debug("Retrieving compiled script class (reflection).");
77+
78+
// the following line can throw NullReferenceException, if that happens it's useful to notify that an error ocurred
79+
var type = assembly.GetType(CompiledScriptClass);
80+
Logger.Debug("Retrieving compiled script method (reflection).");
81+
var method = type.GetMethod(CompiledScriptMethod, BindingFlags.Static | BindingFlags.Public);
82+
83+
try
84+
{
85+
Logger.Debug("Invoking method.");
86+
87+
return new ScriptResult(returnValue: method.Invoke(null, new object[] { session }));
88+
}
89+
catch (Exception executeException)
90+
{
91+
Logger.Error("An error occurred when executing the scripts.");
92+
93+
var ex = executeException.InnerException ?? executeException;
94+
95+
return new ScriptResult(executionException: ex);
96+
}
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)