CodeCellState InsertCodeCell(CodeCell newCell, Cell previousCell, bool isHidden = false) { if (newCell == null) { throw new ArgumentNullException(nameof(newCell)); } InsertCellInDocumentModel(newCell, previousCell); var previousCodeCell = newCell.GetPreviousCell <CodeCell> (); var nextCodeCell = newCell.GetNextCell <CodeCell> (); var codeCellState = new CodeCellState(newCell); if (isHidden) { // Set up editor, required as dictionary key codeCellState.Editor = new HiddenCodeCellEditor(); codeCellState.View = new HiddenCodeCellView { Editor = codeCellState.Editor }; newCell.View = codeCellState.View; } else { BindCodeCellToView(newCell, codeCellState); } if (ClientSession.CompilationWorkspace != null) { codeCellState.CompilationWorkspace = ClientSession.CompilationWorkspace; codeCellState.DocumentId = ClientSession.CompilationWorkspace.AddSubmission( newCell.CodeAnalysisBuffer.CurrentText, GetDocumentId(previousCodeCell), GetDocumentId(nextCodeCell)); } if (!isHidden) { InsertCellInViewModel(newCell, previousCell); } OutdateAllCodeCells(newCell); AppendCodeCell(codeCellState.Editor, codeCellState); return(codeCellState); }
static void RenderResult( CodeCellState codeCellState, Evaluation result, bool isResultAnExpression) { if (codeCellState == null) { throw new ArgumentNullException(nameof(codeCellState)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } var cultureInfo = CultureInfo.CurrentCulture; try { cultureInfo = CultureInfo.GetCultureInfo(result.CultureLCID); } catch (Exception e) when( e is CultureNotFoundException || e is ArgumentOutOfRangeException) { Log.Error(TAG, $"Invalid CultureInfo LCID: {result.CultureLCID}"); } codeCellState.View.EvaluationDuration = result.EvaluationDuration; if (result.Exception != null) { codeCellState.View.RenderResult( cultureInfo, FilterException(result.Exception), result.ResultHandling); } else if (!result.Interrupted && result.Result != null || isResultAnExpression) { codeCellState.View.RenderResult( cultureInfo, result.Result, result.ResultHandling); } }
async Task <EvaluationStatus> CoreEvaluateCodeCellAsync( CodeCellState codeCellState, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken = ClientSession.CancellationToken.LinkWith(cancellationToken); if (!ClientSession.Agent.IsConnected || ClientSession.CompilationWorkspace == null) { codeCellState.View.IsEvaluating = false; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new Diagnostic( DiagnosticSeverity.Error, "Cannot evaluate: not connected to agent.")); return(EvaluationStatus.Disconnected); } CodeAnalysis.Compilation compilation = null; IReadOnlyList <Diagnostic> diagnostics = null; ExceptionNode exception = null; bool agentTerminatedWhileEvaluating = false; try { compilation = await ClientSession.CompilationWorkspace.EmitCellCompilationAsync( codeCellState.CodeCellId, new EvaluationEnvironment (ClientSession.WorkingDirectory), cancellationToken); diagnostics = await ClientSession.CompilationWorkspace.GetCellDiagnosticsAsync( codeCellState.CodeCellId, cancellationToken); var integrationAssemblies = compilation .References .Where(ra => ra.HasIntegration) .ToArray(); if (integrationAssemblies.Length > 0) { await ClientSession.Agent.Api.EvaluationContextManager.LoadAssembliesAsync( TargetCompilationConfiguration.EvaluationContextId, integrationAssemblies); } } catch (Exception e) { exception = ExceptionNode.Create(e); } var hasErrorDiagnostics = codeCellState.View.HasErrorDiagnostics = diagnostics .Any(d => d.Severity == DiagnosticSeverity.Error); foreach (var diagnostic in diagnostics) { codeCellState.View.RenderDiagnostic(diagnostic); } try { if (compilation != null) { await ClientSession.Agent.Api.EvaluationContextManager.EvaluateAsync( TargetCompilationConfiguration.EvaluationContextId, compilation, cancellationToken); } } catch (XipErrorMessageException e) { exception = e.XipErrorMessage.Exception; } catch (Exception e) { Log.Error(TAG, "marking agent as terminated", e); agentTerminatedWhileEvaluating = true; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new Diagnostic( DiagnosticSeverity.Error, Catalog.GetString( "The application terminated during evaluation of this cell. " + "Run this cell manually to try again."))); } codeCellState.View.IsEvaluating = false; EvaluationStatus evaluationStatus; if (exception != null) { codeCellState.View.RenderResult( CultureInfo.CurrentCulture, exception, EvaluationResultHandling.Replace); evaluationStatus = EvaluationStatus.EvaluationException; } else if (hasErrorDiagnostics) { return(EvaluationStatus.ErrorDiagnostic); } else if (agentTerminatedWhileEvaluating) { evaluationStatus = EvaluationStatus.Disconnected; } else { evaluationStatus = EvaluationStatus.Success; } if (ClientSession.SessionKind != ClientSessionKind.Workbook) { codeCellState.Freeze(); } codeCellState.NotifyEvaluated(agentTerminatedWhileEvaluating); return(evaluationStatus); }
// Only call this from EvaluateCodeCellAsync, for CanEvaluate handling async Task DoEvaluateCodeCellAsync(CodeCellState codeCellState, bool evaluateAll = false) { await ClientSession.EnsureAgentConnectionAsync(); var codeCellsToEvaluate = ImmutableList <CodeCellState> .Empty; var originalCodeCellState = codeCellState; if (ClientSession.ViewControllers.ReplHistory != null) { ClientSession.ViewControllers.ReplHistory.UpdateLastAppended( codeCellState.Cell.Buffer.Value.Trim()); ClientSession.ViewControllers.ReplHistory.Save(); } var codeCell = originalCodeCellState.Cell; var isLastCell = codeCell.GetNextCell <CodeCell> () == null; var isFirstCell = codeCell.GetPreviousCell <CodeCell> () == null; if (isFirstCell && ClientSession.SessionKind == ClientSessionKind.Workbook) { await ClientSession.Agent.Api.EvaluationContextManager.ResetStateAsync( TargetCompilationConfiguration.EvaluationContextId); } while (codeCell != null) { if (CodeCells.TryGetValue(codeCell.View.Editor, out codeCellState)) { var evaluateCodeCell = codeCellState == originalCodeCellState || codeCellState.EvaluationCount == 0 || codeCellState.View.IsDirty || codeCellState.View.IsOutdated; if (await ClientSession.CompilationWorkspace.IsCellOutdatedAsync(codeCellState.CodeCellId)) { evaluateCodeCell = true; } if (evaluateCodeCell) { codeCellsToEvaluate = codeCellsToEvaluate.Insert(0, codeCellState); } } codeCell = codeCell.GetPreviousCell <CodeCell> (); } codeCell = originalCodeCellState.Cell; var skipRemainingCodeCells = false; while (true) { codeCell = codeCell.GetNextCell <CodeCell> (); if (codeCell == null) { break; } if (CodeCells.TryGetValue(codeCell.View.Editor, out codeCellState)) { if (skipRemainingCodeCells || codeCellState.AgentTerminatedWhileEvaluating) { skipRemainingCodeCells = true; } else if (evaluateAll || codeCellState.EvaluationCount > 0) { codeCellsToEvaluate = codeCellsToEvaluate.Add(codeCellState); } codeCellState.View.IsOutdated = true; } } foreach (var evaluatableCodeCell in codeCellsToEvaluate) { evaluatableCodeCell.View.Reset(); evaluatableCodeCell.View.IsEvaluating = true; switch (await CoreEvaluateCodeCellAsync(evaluatableCodeCell)) { case EvaluationStatus.ErrorDiagnostic: case EvaluationStatus.Disconnected: return; } } if (isLastCell && !evaluateAll) { StartNewCodeCell(); } // NOTE: I cannot remember why this has to be run after awaiting // CoreEvaluateCodeCellAsync but it does... so don't move it? -abock if (ClientSession.ViewControllers.ReplHistory != null) { ClientSession.ViewControllers.ReplHistory.CursorToEnd(); ClientSession.ViewControllers.ReplHistory.Append(null); } }
void AppendCodeCell(IEditor editor, CodeCellState codeCellState) => codeCells = codeCells.Add(editor, codeCellState);
protected abstract void BindCodeCellToView(CodeCell cell, CodeCellState codeCellState);
async Task <CodeCellEvaluationStatus> CoreEvaluateCodeCellAsync( CodeCellState codeCellState, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken = ClientSession.CancellationToken.LinkWith(cancellationToken); if (!ClientSession.Agent.IsConnected || ClientSession.CompilationWorkspace == null) { codeCellState.View.IsEvaluating = false; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new InteractiveDiagnostic( DiagnosticSeverity.Error, "Cannot evaluate: not connected to agent.")); return(CodeCellEvaluationStatus.Disconnected); } CodeAnalysis.Compilation compilation = null; ExceptionNode exception = null; bool agentTerminatedWhileEvaluating = false; try { compilation = await ClientSession.CompilationWorkspace.GetSubmissionCompilationAsync( codeCellState.DocumentId, new EvaluationEnvironment (ClientSession.WorkingDirectory), cancellationToken); var integrationAssemblies = compilation .References .Where(ra => ra.HasIntegration) .ToArray(); if (integrationAssemblies.Length > 0) { await ClientSession.Agent.Api.LoadAssembliesAsync( ClientSession.CompilationWorkspace.EvaluationContextId, integrationAssemblies); } foreach (var dependency in ClientSession.CompilationWorkspace.WebDependencies) { if (ClientSession.AddWebResource(dependency.Location, out var guid)) { await LoadWorkbookDependencyAsync(guid + dependency.Location.Extension); } } } catch (Exception e) { exception = ExceptionNode.Create(e); } var diagnostics = ClientSession.CompilationWorkspace.CurrentSubmissionDiagnostics.Filter(); codeCellState.View.HasErrorDiagnostics = diagnostics.HasErrors; foreach (var diagnostic in diagnostics) { codeCellState.View.RenderDiagnostic((InteractiveDiagnostic)diagnostic); } try { if (compilation != null) { codeCellState.LastEvaluationRequestId = compilation.MessageId; codeCellState.IsResultAnExpression = compilation.IsResultAnExpression; await ClientSession.Agent.Api.EvaluateAsync( compilation, cancellationToken); } } catch (XipErrorMessageException e) { exception = e.XipErrorMessage.Exception; } catch (Exception e) { Log.Error(TAG, "marking agent as terminated", e); agentTerminatedWhileEvaluating = true; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new InteractiveDiagnostic( DiagnosticSeverity.Error, Catalog.GetString( "The application terminated during evaluation of this cell. " + "Run this cell manually to try again."))); } codeCellState.View.IsEvaluating = false; CodeCellEvaluationStatus evaluationStatus; if (exception != null) { codeCellState.View.RenderResult( CultureInfo.CurrentCulture, FilterException(exception), EvaluationResultHandling.Replace); evaluationStatus = CodeCellEvaluationStatus.EvaluationException; } else if (diagnostics.HasErrors) { return(CodeCellEvaluationStatus.ErrorDiagnostic); } else if (agentTerminatedWhileEvaluating) { evaluationStatus = CodeCellEvaluationStatus.Disconnected; } else { evaluationStatus = CodeCellEvaluationStatus.Success; } if (ClientSession.SessionKind != ClientSessionKind.Workbook) { codeCellState.Freeze(); } codeCellState.NotifyEvaluated(agentTerminatedWhileEvaluating); return(evaluationStatus); }