Skip to content

Commit

Permalink
adopt notebook cell output API change for insiders build (#1068)
Browse files Browse the repository at this point in the history
* adopt notebook cell output API change for insiders build

* don't set notebook languages on insiders
  • Loading branch information
brettfo authored Feb 15, 2021
1 parent cd8c864 commit a41fa7a
Show file tree
Hide file tree
Showing 26 changed files with 224 additions and 129 deletions.
76 changes: 45 additions & 31 deletions src/dotnet-interactive-vscode/build-deps.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Copyright (c) .NET Foundation and contributors. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.

Set-StrictMode -version 2.0
$ErrorActionPreference = "Stop"

function Get-Integrity([string] $filePath) {
$hash = (Get-FileHash $filePath -Algorithm SHA512).Hash
$bytes = (0..($hash.Length / 2)) | ForEach-Object { [System.Convert]::ToByte($hash.Substring($_, 2), 16) }
Expand All @@ -13,34 +19,42 @@ function Update-PackageSha([string] $projectJsonLockPath, [string] $packageName,
$packageJsonLockContents | ConvertTo-Json -depth 100 | Out-File $projectJsonLockPath
}

$interfacesTarball = "$PSScriptRoot/src/interfaces/vscode-interfaces-1.0.0.tgz"
$insidersTarball = "$PSScriptRoot/src/vscode/insiders/vscode-insiders-1.0.0.tgz"
$stableTarball = "$PSScriptRoot/src/vscode/stable/vscode-stable-1.0.0.tgz"

# Build-Interfaces
Push-Location "$PSScriptRoot/src/interfaces"
npm install
npm run compile
npm pack
Pop-Location

# Build insiders
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/src/vscode/insiders/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Push-Location "$PSScriptRoot/src/vscode/insiders"
npm install
npm run compile
npm pack
Pop-Location

# Build stable
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/src/vscode/stable/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Push-Location "$PSScriptRoot/src/vscode/stable"
npm install
npm run compile
npm pack
Pop-Location

# Root project
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-insiders" -packageTarball $insidersTarball
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-stable" -packageTarball $stableTarball
try {
$interfacesTarball = "$PSScriptRoot/src/interfaces/vscode-interfaces-1.0.0.tgz"
$insidersTarball = "$PSScriptRoot/src/vscode/insiders/vscode-insiders-1.0.0.tgz"
$stableTarball = "$PSScriptRoot/src/vscode/stable/vscode-stable-1.0.0.tgz"

# Build-Interfaces
Push-Location "$PSScriptRoot/src/interfaces"
npm install; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm run compile; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm pack; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Pop-Location

# Build insiders
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/src/vscode/insiders/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Push-Location "$PSScriptRoot/src/vscode/insiders"
npm install; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm run compile; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm pack; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Pop-Location

# Build stable
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/src/vscode/stable/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Push-Location "$PSScriptRoot/src/vscode/stable"
npm install; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm run compile; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm pack; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Pop-Location

# Root project
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-interfaces" -packageTarball $interfacesTarball
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-insiders" -packageTarball $insidersTarball
Update-PackageSha -projectJsonLockPath "$PSScriptRoot/package-lock.json" -packageName "vscode-stable" -packageTarball $stableTarball
}
catch {
Write-Host $_
Write-Host $_.Exception
Write-Host $_.ScriptStackTrace
exit 1
}
6 changes: 3 additions & 3 deletions src/dotnet-interactive-vscode/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/dotnet-interactive-vscode/src/clientMapper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { KernelTransport } from "./contracts";
import { KernelTransport } from 'vscode-interfaces/out/contracts';
import { InteractiveClient } from "./interactiveClient";
import { Uri } from "vscode-interfaces/out/notebook";

Expand Down
2 changes: 1 addition & 1 deletion src/dotnet-interactive-vscode/src/interactiveClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
SubmissionType,
SubmitCode,
SubmitCodeType,
} from './contracts';
} from 'vscode-interfaces/out/contracts';
import { Eol } from './interfaces';
import { debounce } from './utilities';

Expand Down
2 changes: 1 addition & 1 deletion src/dotnet-interactive-vscode/src/interactiveNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as path from 'path';
import { debounce } from './utilities';
import { CellKind, Document, NotebookDocumentBackup } from 'vscode-interfaces/out/notebook';
import { ClientMapper } from './clientMapper';
import { Diagnostic } from './contracts';
import { Diagnostic } from 'vscode-interfaces/out/contracts';

export const notebookCellLanguages: Array<string> = [
'dotnet-interactive.csharp',
Expand Down
25 changes: 25 additions & 0 deletions src/dotnet-interactive-vscode/src/interfaces/src/utilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import {
NotebookCellDisplayOutput,
NotebookCellErrorOutput,
NotebookCellTextOutput,
} from './contracts';

export function isErrorOutput(arg: any): arg is NotebookCellErrorOutput {
return arg
&& typeof arg.errorName === 'string'
&& typeof arg.errorValue === 'string'
&& Array.isArray(arg.stackTrace);
}

export function isDisplayOutput(arg: any): arg is NotebookCellDisplayOutput {
return arg
&& typeof arg.data === 'object';
}

export function isTextOutput(arg: any): arg is NotebookCellTextOutput {
return arg
&& typeof arg.text === 'string';
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { ClientMapper } from './../clientMapper';
import { CompletionsProduced } from './../contracts';
import { PositionLike } from './interfaces';
import { Document } from 'vscode-interfaces/out/notebook';

export async function provideCompletion(clientMapper: ClientMapper, language: string, document: Document, position: PositionLike, token?: string | undefined): Promise<CompletionsProduced> {
import * as contracts from 'vscode-interfaces/out/contracts';

export async function provideCompletion(clientMapper: ClientMapper, language: string, document: Document, position: PositionLike, token?: string | undefined): Promise<contracts.CompletionsProduced> {
let client = await clientMapper.getOrAddClient(document.uri);
let completion = await client.completion(language, document.getText(), position.line, position.character, token);
return completion;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { LinePositionSpan } from './../contracts';
import * as contracts from 'vscode-interfaces/out/contracts';

export interface HoverResult {
contents: string,
isMarkdown: boolean;
range: LinePositionSpan | undefined,
range: contracts.LinePositionSpan | undefined,
}

export interface PositionLike {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import { ClientMapper } from './../clientMapper';
import { PositionLike } from './interfaces';
import { Document } from 'vscode-interfaces/out/notebook';
import { SignatureHelpProduced } from '../contracts';

export async function provideSignatureHelp(clientMapper: ClientMapper, language: string, document: Document, position: PositionLike, token?: string | undefined): Promise<SignatureHelpProduced> {
import * as contracts from 'vscode-interfaces/out/contracts';

export async function provideSignatureHelp(clientMapper: ClientMapper, language: string, document: Document, position: PositionLike, token?: string | undefined): Promise<contracts.SignatureHelpProduced> {
let client = await clientMapper.getOrAddClient(document.uri);
let sigHelp = await client.signatureHelp(language, document.getText(), position.line, position.character, token);
return sigHelp;
Expand Down
5 changes: 2 additions & 3 deletions src/dotnet-interactive-vscode/src/stdioKernelTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import {
DiagnosticLogEntryProduced,
KernelReadyType,
KernelCommandEnvelopeObserver
} from "./contracts";
} from 'vscode-interfaces/out/contracts';
import { ProcessStart } from './interfaces';
import { ReportChannel, Uri } from 'vscode-interfaces/out/notebook';
import { LineReader } from './lineReader';
import { isNotNull, parse, stringify, wait } from './utilities';
import { isNotNull, parse, stringify } from './utilities';
import fetch from 'node-fetch';
import { extname } from "path";

export class StdioKernelTransport implements KernelTransport {
private childProcess: cp.ChildProcessWithoutNullStreams | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { expect } from 'chai';

import { ClientMapper } from '../../clientMapper';
import { TestKernelTransport } from './testKernelTransport';
import { CodeSubmissionReceivedType, CompleteCodeSubmissionReceivedType, CommandSucceededType, DisplayedValueProducedType, ReturnValueProducedType, DisplayedValueUpdatedType, CommandFailedType } from '../../contracts';
import { CodeSubmissionReceivedType, CompleteCodeSubmissionReceivedType, CommandSucceededType, DisplayedValueProducedType, ReturnValueProducedType, DisplayedValueUpdatedType, CommandFailedType } from 'vscode-interfaces/out/contracts';
import { debounce, wait } from '../../utilities';
import * as interfaces from 'vscode-interfaces/out/notebook';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TestKernelTransport } from './testKernelTransport';
import { provideCompletion } from './../../languageServices/completion';
import { provideHover } from './../../languageServices/hover';
import { provideSignatureHelp } from '../../languageServices/signatureHelp';
import { CommandSucceededType, CompletionsProducedType, HoverTextProducedType, SignatureHelpProducedType } from '../../contracts';
import { CommandSucceededType, CompletionsProducedType, HoverTextProducedType, SignatureHelpProducedType } from 'vscode-interfaces/out/contracts';

describe('LanguageProvider tests', () => {
it('CompletionProvider', async () => {
Expand Down
5 changes: 3 additions & 2 deletions src/dotnet-interactive-vscode/src/tests/unit/misc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { expect } from 'chai';
import { NotebookCellDisplayOutput, NotebookCellErrorOutput, NotebookCellTextOutput } from '../../contracts';
import { NotebookCellDisplayOutput, NotebookCellErrorOutput, NotebookCellTextOutput } from 'vscode-interfaces/out/contracts';
import { isDisplayOutput, isErrorOutput, isTextOutput } from 'vscode-interfaces/out/utilities';
import { requiredKernelspecData } from '../../ipynbUtilities';
import { debounce, isDisplayOutput, isDotNetKernelPreferred, isErrorOutput, isTextOutput, parse, processArguments, stringify } from '../../utilities';
import { debounce, isDotNetKernelPreferred, parse, processArguments, stringify } from '../../utilities';

describe('Miscellaneous tests', () => {
describe('preferred kernel selection', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
DisplayedValueUpdatedType,
ReturnValueProducedType,
StandardOutputValueProducedType,
} from '../../contracts';
} from 'vscode-interfaces/out/contracts';
import { withFakeGlobalStorageLocation } from './utilities';
import { backupNotebook, languageToCellKind } from '../../interactiveNotebook';
import * as interfaces from 'vscode-interfaces/out/notebook';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { KernelCommand, KernelCommandType, KernelEventType, KernelEventEnvelopeObserver, DisposableSubscription, KernelEvent, KernelCommandEnvelopeObserver, KernelEventEnvelope, KernelTransport } from "../../contracts";
import { KernelCommand, KernelCommandType, KernelEventType, KernelEventEnvelopeObserver, DisposableSubscription, KernelEvent, KernelCommandEnvelopeObserver, KernelEventEnvelope, KernelTransport } from 'vscode-interfaces/out/contracts';

// Replays all events given to it
export class TestKernelTransport implements KernelTransport {
Expand Down
18 changes: 0 additions & 18 deletions src/dotnet-interactive-vscode/src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import * as path from 'path';
import { NotebookCellDisplayOutput, NotebookCellErrorOutput, NotebookCellTextOutput } from "./contracts";
import { ProcessStart } from "./interfaces";
import { Uri } from 'vscode-interfaces/out/notebook';

Expand Down Expand Up @@ -142,20 +141,3 @@ export function isDotNetKernelPreferred(filename: string, fileMetadata: any): bo
return false;
}
}

export function isErrorOutput(arg: any): arg is NotebookCellErrorOutput {
return arg
&& typeof arg.errorName === 'string'
&& typeof arg.errorValue === 'string'
&& Array.isArray(arg.stackTrace);
}

export function isDisplayOutput(arg: any): arg is NotebookCellDisplayOutput {
return arg
&& typeof arg.data === 'object';
}

export function isTextOutput(arg: any): arg is NotebookCellTextOutput {
return arg
&& typeof arg.text === 'string';
}
6 changes: 4 additions & 2 deletions src/dotnet-interactive-vscode/src/vscode/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ async function updateCellLanguageInMetadata(languageChangeEvent: { cell: vscode.

async function updateDocumentMetadata(e: { document: vscode.NotebookDocument, kernel: vscode.NotebookKernel | undefined }, clientMapper: ClientMapper) {
if (e.kernel?.id === KernelId) {
// update document language
e.document.languages = notebookCellLanguages;
if (!isInsidersBuild()) {
// update document language (not supported on Insiders)
e.document.languages = notebookCellLanguages;
}

// update various metadata
await updateDocumentKernelspecMetadata(e.document);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 53 additions & 5 deletions src/dotnet-interactive-vscode/src/vscode/insiders/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,64 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import * as vscode from 'vscode';
import * as contracts from 'vscode-interfaces/out/contracts';
import * as interfaces from 'vscode-interfaces/out/notebook';
import * as utilities from 'vscode-interfaces/out/utilities';

// The current insiders build doesn't honor the error mime type, so we're temporarily reverting to `text/plain`.
// To ensure we can still detect error cells, we're also stuffing the original mime type into the output's metadata.
// https://github.com/dotnet/interactive/issues/1063
function generateVsCodeNotebookCellOutputItem(mimeType: string, value: unknown): vscode.NotebookCellOutputItem {
const metadata = { mimeType };
const newMimeType = mimeType === interfaces.ErrorOutputMimeType ? 'text/plain' : mimeType;
return new vscode.NotebookCellOutputItem(newMimeType, value, metadata);
}

export async function updateCellOutputs(document: vscode.NotebookDocument, cellIndex: number, outputs: Array<interfaces.NotebookCellOutput>) {
const edit = new vscode.WorkspaceEdit();
edit.replaceNotebookCellOutput(document.uri, cellIndex, outputs.map(o => {
return new vscode.NotebookCellOutput(o.outputs.map(oi => {
// the current insiders build doesn't honor the error mime type, so we're temporarily reverting to `text/plain`
// https://github.com/dotnet/interactive/issues/1063
return new vscode.NotebookCellOutputItem(oi.mime === interfaces.ErrorOutputMimeType ? 'text/plain' : oi.mime, oi.value);
}));
return new vscode.NotebookCellOutput(o.outputs.map(oi => generateVsCodeNotebookCellOutputItem(oi.mime, oi.value)));
}));
await vscode.workspace.applyEdit(edit);
}

export function vsCodeCellOutputToContractCellOutput(output: vscode.NotebookCellOutput): contracts.NotebookCellOutput {
const errorOutputItems = output.outputs.filter(oi => oi.mime === interfaces.ErrorOutputMimeType || oi.metadata?.mimeType === interfaces.ErrorOutputMimeType);
if (errorOutputItems.length > 0) {
// any error-like output takes precedence
const errorOutputItem = errorOutputItems[0];
const error: contracts.NotebookCellErrorOutput = {
errorName: 'Error',
errorValue: '' + errorOutputItem.value,
stackTrace: [],
};
return error;
} else {
//otherwise build the mime=>value dictionary
const data: { [key: string]: any } = {};
for (const outputItem of output.outputs) {
data[outputItem.mime] = outputItem.value;
}

const cellOutput: contracts.NotebookCellDisplayOutput = {
data,
};

return cellOutput;
}
}

export function contractCellOutputToVsCodeCellOutput(output: contracts.NotebookCellOutput): vscode.NotebookCellOutput {
const outputItems: Array<vscode.NotebookCellOutputItem> = [];
if (utilities.isDisplayOutput(output)) {
for (const mimeKey in output.data) {
outputItems.push(generateVsCodeNotebookCellOutputItem(mimeKey, output.data[mimeKey]));
}
} else if (utilities.isErrorOutput(output)) {
outputItems.push(generateVsCodeNotebookCellOutputItem(interfaces.ErrorOutputMimeType, output.errorValue));
} else if (utilities.isTextOutput(output)) {
outputItems.push(generateVsCodeNotebookCellOutputItem('text/plain', output.text));
}

return new vscode.NotebookCellOutput(outputItems);
}
Loading

0 comments on commit a41fa7a

Please sign in to comment.