这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 3 additions & 21 deletions WorkspaceServer.Tests/Kernel/CSharpKernelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public async Task it_returns_diagnostics()
}

[Fact]
public async Task it_notifies_when_submission_is_complete()
public async Task it_cannot_execute_incomplete_submissions()
{
var kernel = CreateKernel();

Expand All @@ -122,27 +122,9 @@ public async Task it_notifies_when_submission_is_complete()

KernelEvents
.Should()
.Contain(e => e.Value is CodeSubmissionEvaluated);
}

[Fact]
public async Task it_notifies_when_submission_is_incomplete()
{
var kernel = CreateKernel();

await kernel.SendAsync(new SubmitCode("var a ="));

KernelEvents
.Should()
.NotContain(e => e.Value is ValueProduced);

KernelEvents
.ValuesOnly()
.Should()
.Contain(e => e is CodeSubmissionEvaluated)
.And
.Contain(e => e is IncompleteCodeSubmissionReceived);
.Contain(e => e.Value is CodeSubmissionEvaluationFailed);
}


[Fact]
public async Task expression_evaluated_to_null_has_result_with_null_value()
Expand Down
143 changes: 60 additions & 83 deletions WorkspaceServer/Kernel/CSharpKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Recommendations;
using Microsoft.CodeAnalysis.Scripting;
Expand All @@ -34,11 +33,7 @@ public class CSharpKernel : KernelBase
.GetMethod("HasReturnValue", BindingFlags.Instance | BindingFlags.NonPublic);

private ScriptState _scriptState;

protected CSharpParseOptions ParseOptions = new CSharpParseOptions(LanguageVersion.Default, kind: SourceCodeKind.Script);
protected ScriptOptions ScriptOptions;

private StringBuilder _inputBuffer = new StringBuilder();
private ImmutableArray<MetadataReference> _metadataReferences;
private WorkspaceFixture _fixture;

Expand All @@ -64,28 +59,12 @@ private void SetupScriptOptions()
typeof(Enumerable).Assembly,
typeof(IEnumerable<>).Assembly,
typeof(Task<>).Assembly,
typeof(IKernel).Assembly,
typeof(CSharpKernel).Assembly,
typeof(IKernel).Assembly,
typeof(CSharpKernel).Assembly,
typeof(PocketView).Assembly,
typeof(XPlot.Plotly.PlotlyChart).Assembly);
}

private (bool shouldExecute, string completeSubmission) IsBufferACompleteSubmission(string input)
{
_inputBuffer.AppendLine(input);

var code = _inputBuffer.ToString();
var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, ParseOptions);

if (!SyntaxFactory.IsCompleteSubmission(syntaxTree))
{
return (false, code);
}

_inputBuffer = new StringBuilder();
return (true, code);
}

protected override async Task HandleAsync(
IKernelCommand command,
KernelInvocationContext context)
Expand Down Expand Up @@ -115,83 +94,75 @@ private async Task HandleSubmitCode(
var codeSubmissionReceived = new CodeSubmissionReceived(
submitCode.Code,
submitCode);

context.OnNext(codeSubmissionReceived);

var (shouldExecute, code) = IsBufferACompleteSubmission(submitCode.Code);
var code = submitCode.Code;

if (shouldExecute)
{
context.OnNext(new CompleteCodeSubmissionReceived(submitCode));
Exception exception = null;
context.OnNext(new CompleteCodeSubmissionReceived(submitCode));
Exception exception = null;

using var console = await ConsoleOutput.Capture();
using var _ = console.SubscribeToStandardOutput(std => PublishOutput(std, context, submitCode));
using var console = await ConsoleOutput.Capture();
using var _ = console.SubscribeToStandardOutput(std => PublishOutput(std, context, submitCode));

try
try
{
if (_scriptState == null)
{
if (_scriptState == null)
{
_scriptState = await CSharpScript.RunAsync(
code,
ScriptOptions);
}
else
{
_scriptState = await _scriptState.ContinueWithAsync(
code,
ScriptOptions,
e =>
{
exception = e;
return true;
});
}
_scriptState = await CSharpScript.RunAsync(
code,
ScriptOptions);
}
catch (Exception e)
else
{
exception = e;
_scriptState = await _scriptState.ContinueWithAsync(
code,
ScriptOptions,
e =>
{
exception = e;
return true;
});
}
}
catch (Exception e)
{
exception = e;
}

if (exception != null)
{
var message = string.Join("\n", (_scriptState?.Script?.GetDiagnostics() ??
Enumerable.Empty<Diagnostic>()).Select(d => d.GetMessage()));
if (exception != null)
{
var message = string.Join("\n", (_scriptState?.Script?.GetDiagnostics() ??
Enumerable.Empty<Diagnostic>()).Select(d => d.GetMessage()));

context.OnNext(new CodeSubmissionEvaluationFailed(exception, message, submitCode));
context.OnError(exception);
}
else
context.OnNext(new CodeSubmissionEvaluationFailed(exception, message, submitCode));
context.OnError(exception);
}
else
{
if (HasReturnValue)
{
if (HasReturnValue)
{
var returnValueType = _scriptState.ReturnValue?.GetType();
var returnValueType = _scriptState.ReturnValue?.GetType();

var mimeType = MimeTypeFor(returnValueType);
var mimeType = MimeTypeFor(returnValueType);

var formatted = _scriptState.ReturnValue.ToDisplayString(mimeType);
var formatted = _scriptState.ReturnValue.ToDisplayString(mimeType);

var formattedValues = new List<FormattedValue>
var formattedValues = new List<FormattedValue>
{
new FormattedValue(mimeType, formatted)
};

context.OnNext(
new ValueProduced(
_scriptState.ReturnValue,
submitCode,
true,
formattedValues));
}

context.OnNext(new CodeSubmissionEvaluated(submitCode));

context.OnCompleted();
context.OnNext(
new ValueProduced(
_scriptState.ReturnValue,
submitCode,
true,
formattedValues));
}
}
else
{
context.OnNext(new IncompleteCodeSubmissionReceived(submitCode));

context.OnNext(new CodeSubmissionEvaluated(submitCode));

context.OnCompleted();
}
}
Expand All @@ -205,8 +176,8 @@ private static string MimeTypeFor(Type returnValueType)
}

private void PublishOutput(
string output,
KernelInvocationContext context,
string output,
KernelInvocationContext context,
IKernelCommand command)
{
var formattedValues = new List<FormattedValue>
Expand Down Expand Up @@ -251,14 +222,20 @@ private async Task<IEnumerable<CompletionItem>> GetCompletionList(string code, i
var forcedState = false;
if (scriptState == null)
{
scriptState = await CSharpScript.RunAsync("", ScriptOptions);
scriptState = await CSharpScript.RunAsync(string.Empty, ScriptOptions);
forcedState = true;
}

var compilation = scriptState.Script.GetCompilation();
metadataReferences = metadataReferences.AddRange(compilation.References);
var originalCode = forcedState ? string.Empty : scriptState.Script.Code ?? string.Empty;

var buffer = new StringBuilder(originalCode);
if (!string.IsNullOrWhiteSpace(originalCode) && !originalCode.EndsWith(Environment.NewLine))
{
buffer.AppendLine();
}

var buffer = new StringBuilder(forcedState ? string.Empty : scriptState.Script.Code ?? string.Empty);
buffer.AppendLine(code);
var fullScriptCode = buffer.ToString();
var offset = fullScriptCode.LastIndexOf(code, StringComparison.InvariantCulture);
Expand Down