Skip to content

Commit 19a772f

Browse files
committed
# Added support for compilation failures
1 parent df36878 commit 19a772f

9 files changed

Lines changed: 115 additions & 7 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Roslyn.Compilers.Common;
4+
5+
namespace ScriptCs
6+
{
7+
using System;
8+
9+
public class CompilationResult : ICompilationResult
10+
{
11+
public CompilationResult(CommonEmitResult emitResult)
12+
{
13+
this.Success = emitResult.Success;
14+
15+
this.ErrorMessage = this.RetrieveErrorMessage(emitResult.Diagnostics);
16+
}
17+
18+
public bool Success { get; private set; }
19+
20+
public string ErrorMessage { get; private set; }
21+
22+
private string RetrieveErrorMessage(IEnumerable<CommonDiagnostic> diagnostics)
23+
{
24+
return string.Join(Environment.NewLine, diagnostics.Select(d => d.ToString()));
25+
}
26+
}
27+
}

src/ScriptCs.Core/DebugScriptExecutor.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
using Roslyn.Compilers.Common;
77

8+
using ScriptCs.Exceptions;
9+
810
[Export(Constants.DebugContractName, typeof(IScriptExecutor))]
911
public class DebugScriptExecutor : ScriptExecutor
1012
{
@@ -30,13 +32,22 @@ protected override void Execute(string absolutePathToScript, ISession session, s
3032

3133
ISubmission<object> submission = session.CompileSubmission<object>(code);
3234

33-
CommonEmitResult result;
35+
ICompilationResult result;
3436

3537
using (Stream outputStream = _fileSystem.CreateFileStream(outputPath, FileMode.OpenOrCreate))
3638
using (Stream pdbStream = _fileSystem.CreateFileStream(pdbPath, FileMode.OpenOrCreate))
3739
{
3840
result = submission.Compilation.Emit(outputStream, pdbStream);
3941
}
42+
43+
if (result.Success)
44+
{
45+
46+
}
47+
else
48+
{
49+
throw new CompilationException(result.ErrorMessage);
50+
}
4051
}
4152
}
4253
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace ScriptCs.Exceptions
4+
{
5+
public class CompilationException : Exception
6+
{
7+
public CompilationException(string message) : base(message)
8+
{
9+
}
10+
}
11+
}

src/ScriptCs.Core/ICompilation.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
using System.IO;
2-
using Roslyn.Compilers.Common;
32

43
namespace ScriptCs
54
{
65
public interface ICompilation
76
{
8-
CommonEmitResult Emit(Stream outputStream, Stream pdbStream);
7+
ICompilationResult Emit(Stream outputStream, Stream pdbStream);
98
}
109
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace ScriptCs
2+
{
3+
public interface ICompilationResult
4+
{
5+
bool Success { get; }
6+
string ErrorMessage { get; }
7+
}
8+
}

src/ScriptCs.Core/ScriptCs.Core.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
<Reference Include="System.Xml" />
3232
</ItemGroup>
3333
<ItemGroup>
34+
<Compile Include="CompilationResult.cs" />
3435
<Compile Include="DebugFilePreProcessor.cs" />
3536
<Compile Include="DebugScriptExecutor.cs" />
37+
<Compile Include="Exceptions\CompilationException.cs" />
3638
<Compile Include="Exceptions\MissingAssemblyException.cs" />
3739
<Compile Include="..\..\common\CommonAssemblyInfo.cs">
3840
<Link>Properties\CommonAssemblyInfo.cs</Link>
@@ -43,6 +45,7 @@
4345
<Compile Include="FilePreProcessor.cs" />
4446
<Compile Include="FileSystem.cs" />
4547
<Compile Include="ICompilation.cs" />
48+
<Compile Include="ICompilationResult.cs" />
4649
<Compile Include="IFilePreProcessor.cs" />
4750
<Compile Include="IFileSystem.cs" />
4851
<Compile Include="IPackageAssemblyResolver.cs" />

src/ScriptCs.Core/Wrappers/CompilationWrapper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ public CompilationWrapper(CommonCompilation compilation)
1313
this._compilation = compilation;
1414
}
1515

16-
public CommonEmitResult Emit(Stream outputStream, Stream pdbStream)
16+
public ICompilationResult Emit(Stream outputStream, Stream pdbStream)
1717
{
18-
return this._compilation.Emit(outputStream, pdbStream: pdbStream);
18+
var emitResult = this._compilation.Emit(outputStream, pdbStream: pdbStream);
19+
return new CompilationResult(emitResult);
1920
}
2021
}
2122
}

test/ScriptCs.Core.Tests/DebugScriptExecutorTests.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
using System.Linq;
44
using Moq;
55
using ScriptCs.Contracts;
6+
using Should;
67
using Xunit;
78

89
namespace ScriptCs.Tests
910
{
11+
using ScriptCs.Exceptions;
1012

1113
public class DebugScriptExecutorTests
1214
{
@@ -59,10 +61,13 @@ public void ShouldCompileProcessedCode()
5961
var session = new Mock<ISession>();
6062
var submission = new Mock<ISubmission<object>>();
6163
var compilation = new Mock<ICompilation>();
64+
var compilationResult = new Mock<ICompilationResult>();
6265

6366
const string PathToScript = @"C:\script.csx";
6467
var code = Guid.NewGuid().ToString();
6568

69+
compilationResult.Setup(r => r.Success).Returns(true);
70+
6671
filePreProcessor.Setup(p => p.ProcessFile(PathToScript)).Returns(code);
6772

6873
scriptEngine.Setup(e => e.CreateSession(It.IsAny<ScriptHost>())).Returns(session.Object);
@@ -73,6 +78,8 @@ public void ShouldCompileProcessedCode()
7378

7479
submission.Setup(s => s.Compilation).Returns(compilation.Object);
7580

81+
compilation.Setup(c => c.Emit(It.IsAny<Stream>(), It.IsAny<Stream>())).Returns(compilationResult.Object).Verifiable();
82+
7683
var scriptExecutor = DebugScriptExecutorTests.CreateScriptExecutor(
7784
scriptEngine: scriptEngine,
7885
fileProcessor: filePreProcessor);
@@ -92,6 +99,7 @@ public void ShouldEmitCompilationProvidingPathsForDllAndPdbFiles()
9299
var session = new Mock<ISession>();
93100
var submission = new Mock<ISubmission<object>>();
94101
var compilation = new Mock<ICompilation>();
102+
var compilationResult = new Mock<ICompilationResult>();
95103

96104
var fileSystem = new Mock<IFileSystem>();
97105

@@ -105,6 +113,8 @@ public void ShouldEmitCompilationProvidingPathsForDllAndPdbFiles()
105113
var pdbStream = new MemoryStream();
106114
var dllStream = new MemoryStream();
107115

116+
compilationResult.Setup(r => r.Success).Returns(true);
117+
108118
scriptEngine.Setup(e => e.CreateSession(It.IsAny<ScriptHost>())).Returns(session.Object);
109119
scriptEngine.SetupProperty(e => e.BaseDirectory);
110120

@@ -117,7 +127,7 @@ public void ShouldEmitCompilationProvidingPathsForDllAndPdbFiles()
117127
fileSystem.Setup(fs => fs.CreateFileStream(pdbFullPath, FileMode.OpenOrCreate)).Returns(pdbStream).Verifiable();
118128
fileSystem.Setup(fs => fs.CreateFileStream(dllFullPath, FileMode.OpenOrCreate)).Returns(dllStream).Verifiable();
119129

120-
compilation.Setup(c => c.Emit(dllStream, pdbStream)).Verifiable();
130+
compilation.Setup(c => c.Emit(dllStream, pdbStream)).Returns(compilationResult.Object).Verifiable();
121131

122132
var scriptExecutor = DebugScriptExecutorTests.CreateScriptExecutor(fileSystem, scriptEngine: scriptEngine);
123133

@@ -127,6 +137,44 @@ public void ShouldEmitCompilationProvidingPathsForDllAndPdbFiles()
127137
// assert
128138
compilation.Verify(c => c.Emit(dllStream, pdbStream), Times.Once());
129139
}
140+
141+
[Fact]
142+
public void ShouldThrowCompilationExceptionIfCompilationFails()
143+
{
144+
// arrange
145+
var scriptEngine = new Mock<IScriptEngine>();
146+
var session = new Mock<ISession>();
147+
var submission = new Mock<ISubmission<object>>();
148+
var compilation = new Mock<ICompilation>();
149+
var compilationResult = new Mock<ICompilationResult>();
150+
151+
const string ErrorMessage = "Error message";
152+
compilationResult.Setup(r => r.Success).Returns(false).Verifiable();
153+
compilationResult.Setup(r => r.ErrorMessage).Returns(ErrorMessage).Verifiable();
154+
155+
const string PathToScript = @"C:\script.csx";
156+
157+
scriptEngine.Setup(e => e.CreateSession(It.IsAny<ScriptHost>())).Returns(session.Object);
158+
scriptEngine.SetupProperty(e => e.BaseDirectory);
159+
160+
session.Setup(s => s.CompileSubmission<object>(It.IsAny<string>())).Returns(submission.Object);
161+
session.Setup(s => s.Engine).Returns(scriptEngine.Object);
162+
163+
submission.Setup(s => s.Compilation).Returns(compilation.Object);
164+
165+
compilation.Setup(c => c.Emit(It.IsAny<Stream>(), It.IsAny<Stream>())).Returns(compilationResult.Object).Verifiable();
166+
167+
var scriptExecutor = DebugScriptExecutorTests.CreateScriptExecutor(scriptEngine: scriptEngine);
168+
169+
// act + assert
170+
var exception = Assert.Throws<CompilationException>(() =>
171+
scriptExecutor.Execute(PathToScript, Enumerable.Empty<string>(), Enumerable.Empty<IScriptPack>()));
172+
173+
exception.Message.ShouldEqual(ErrorMessage);
174+
175+
compilationResult.Verify(r => r.ErrorMessage, Times.Once());
176+
compilationResult.Verify(r => r.Success, Times.Once());
177+
}
130178
}
131179
}
132180
}

test/ScriptCs.Core.Tests/ScriptExecutorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public void ShouldAddReferenceToEachDestinationFile()
370370

371371
scriptEngine.Setup(e => e.CreateSession(It.IsAny<ScriptHost>())).Returns(session.Object);
372372

373-
var scriptExecutor = CreateScriptExecutor(fileSystem: fileSystem, scriptEngine: scriptEngine);
373+
var scriptExecutor = CreateScriptExecutor(fileSystem, scriptEngine: scriptEngine);
374374

375375
var currentDirectory = @"C:\";
376376
var sourceFilePath1 = Path.Combine(@"C:\fileDir", "fileName1.cs");

0 commit comments

Comments
 (0)