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
9 changes: 8 additions & 1 deletion src/client/datascience/interactive-common/interactiveBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { CancellationToken, ConfigurationTarget, Event, EventEmitter, Memento, P
import { Disposable } from 'vscode-jsonrpc';

import { ServerStatus } from '../../../datascience-ui/interactive-common/mainState';
import { CommonActionType } from '../../../datascience-ui/interactive-common/redux/reducers/types';
import { IApplicationShell, ICommandManager, IDocumentManager, ILiveShareApi, IWebPanelProvider, IWorkspaceService } from '../../common/application/types';
import { CancellationError } from '../../common/cancellation';
import { EXTENSION_ROOT_DIR, PYTHON_LANGUAGE } from '../../common/constants';
Expand Down Expand Up @@ -43,7 +44,7 @@ import { JupyterInstallError } from '../jupyter/jupyterInstallError';
import { JupyterSelfCertsError } from '../jupyter/jupyterSelfCertsError';
import { JupyterKernelPromiseFailedError } from '../jupyter/kernels/jupyterKernelPromiseFailedError';
import { LiveKernelModel } from '../jupyter/kernels/types';
import { CssMessages } from '../messages';
import { CssMessages, SharedMessages } from '../messages';
import { ProgressReporter } from '../progress/progressReporter';
import {
CellState,
Expand Down Expand Up @@ -72,6 +73,7 @@ import {
} from '../types';
import { WebViewHost } from '../webViewHost';
import { InteractiveWindowMessageListener } from './interactiveWindowMessageListener';
import { BaseReduxActionPayload } from './types';

@injectable()
export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapping> implements IInteractiveBase {
Expand Down Expand Up @@ -174,6 +176,11 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
// tslint:disable-next-line: no-any no-empty cyclomatic-complexity max-func-body-length
public onMessage(message: string, payload: any) {
switch (message) {
case InteractiveWindowMessages.Sync:
// tslint:disable-next-line: no-any
const syncPayload = payload as { type: InteractiveWindowMessages | SharedMessages | CommonActionType; payload: BaseReduxActionPayload<any> };
this.postMessageInternal(syncPayload.type, syncPayload.payload).ignoreErrors();
break;
case InteractiveWindowMessages.GotoCodeCell:
this.handleMessage(message, payload, this.gotoCode);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { InteractiveWindowMessages, InteractiveWindowRemoteMessages } from './in

// This class listens to messages that come from the local Python Interactive window
export class InteractiveWindowMessageListener implements IWebPanelMessageListener {
private static handlers = new Map<InteractiveWindowMessageListener, (message: string, payload: any) => void>();
private postOffice: PostOffice;
private disposedCallback: () => void;
private callback: (message: string, payload: any) => void;
Expand All @@ -40,6 +41,7 @@ export class InteractiveWindowMessageListener implements IWebPanelMessageListene
this.interactiveWindowMessages.forEach(m => {
this.postOffice.registerCallback(m, a => callback(m, a)).ignoreErrors();
});
InteractiveWindowMessageListener.handlers.set(this, callback);
}

public async dispose() {
Expand All @@ -48,6 +50,20 @@ export class InteractiveWindowMessageListener implements IWebPanelMessageListene
}

public onMessage(message: string, payload: any) {
if (message === InteractiveWindowMessages.Sync) {
// const syncPayload = payload as BaseReduxActionPayload;
Array.from(InteractiveWindowMessageListener.handlers.keys()).forEach(item => {
if (item === this) {
return;
}
// Temporarily disabled.
// const cb = InteractiveWindowMessageListener.handlers.get(item);
// if (cb) {
// cb(InteractiveWindowMessages.Sync, { type: message, payload: syncPayload });
// }
});
return;
}
// We received a message from the local webview. Broadcast it to everybody if it's a remote message
if (InteractiveWindowRemoteMessages.indexOf(message) >= 0) {
this.postOffice.postCommand(message, payload).ignoreErrors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
'use strict';
import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
import { IServerState } from '../../../datascience-ui/interactive-common/mainState';
import { IAddCellAction, ICellAction } from '../../../datascience-ui/interactive-common/redux/reducers/types';
import { CommonActionType, IAddCellAction, ICellAction } from '../../../datascience-ui/interactive-common/redux/reducers/types';
import { CssMessages, IGetCssRequest, IGetCssResponse, IGetMonacoThemeRequest, SharedMessages } from '../messages';
import { IGetMonacoThemeResponse } from '../monacoMessages';
import { ICell, IInteractiveWindowInfo, IJupyterVariable, IJupyterVariablesRequest, IJupyterVariablesResponse } from '../types';
import { BaseReduxActionPayload } from './types';

export enum InteractiveWindowMessages {
StartCell = 'start_cell',
Expand Down Expand Up @@ -58,6 +59,7 @@ export enum InteractiveWindowMessages {
EditCell = 'edit_cell',
RemoveCell = 'remove_cell',
SwapCells = 'swap_cells',
Sync = 'sync_message_used_to_broadcast_and_sync_editors',
InsertCell = 'insert_cell',
LoadOnigasmAssemblyRequest = 'load_onigasm_assembly_request',
LoadOnigasmAssemblyResponse = 'load_onigasm_assembly_response',
Expand Down Expand Up @@ -368,6 +370,8 @@ export class IInteractiveWindowMapping {
public [InteractiveWindowMessages.NotebookDirty]: never | undefined;
public [InteractiveWindowMessages.NotebookClean]: never | undefined;
public [InteractiveWindowMessages.SaveAll]: ISaveAll;
// tslint:disable-next-line: no-any
public [InteractiveWindowMessages.Sync]: { type: InteractiveWindowMessages | SharedMessages | CommonActionType; payload: BaseReduxActionPayload<any> };
public [InteractiveWindowMessages.NativeCommand]: INativeCommand;
public [InteractiveWindowMessages.VariablesComplete]: never | undefined;
public [InteractiveWindowMessages.NotebookRunAllCells]: never | undefined;
Expand Down
181 changes: 181 additions & 0 deletions src/client/datascience/interactive-common/synchronization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { CommonActionType, CommonActionTypeMapping } from '../../../datascience-ui/interactive-common/redux/reducers/types';
import { CssMessages, SharedMessages } from '../messages';
import { IInteractiveWindowMapping, InteractiveWindowMessages } from './interactiveWindowTypes';
import { BaseReduxActionPayload } from './types';

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

export enum MessageType {
other = 0,
/**
* Messages must be re-broadcasted across other editors of the same file in the same session.
*/
syncAcrossSameNotebooks = 1 << 0,
/**
* Messages must be re-broadcasted across all sessions.
*/
syncWithLiveShare = 1 << 1,
noIdea = 1 << 2
}

type MessageMapping<T> = {
[P in keyof T]: MessageType;
};

export type IInteractiveActionMapping = MessageMapping<IInteractiveWindowMapping>;

// Do not change to a dictionary or a record.
// The current structure ensures all new enums added will be categorized.
// This way, if a new message is added, we'll make the decision early on whether it needs to be synchronized and how.
// Rather than waiting for users to report issues related to new messages.
const messageWithMessageTypes: MessageMapping<IInteractiveWindowMapping> & MessageMapping<CommonActionTypeMapping> = {
[CommonActionType.ADD_NEW_CELL]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.ARROW_DOWN]: MessageType.syncWithLiveShare,
[CommonActionType.ARROW_UP]: MessageType.syncWithLiveShare,
[CommonActionType.CHANGE_CELL_TYPE]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.CLICK_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.CODE_CREATED]: MessageType.noIdea,
[CommonActionType.COPY_CELL_CODE]: MessageType.other,
[CommonActionType.EDITOR_LOADED]: MessageType.other,
[CommonActionType.EDIT_CELL]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.EXECUTE_ABOVE]: MessageType.other,
[CommonActionType.EXECUTE_ALL_CELLS]: MessageType.other,
[CommonActionType.EXECUTE_CELL]: MessageType.other,
[CommonActionType.EXECUTE_CELL_AND_BELOW]: MessageType.other,
[CommonActionType.EXPORT]: MessageType.other,
[CommonActionType.FOCUS_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.GATHER_CELL]: MessageType.other,
[CommonActionType.GET_VARIABLE_DATA]: MessageType.other,
[CommonActionType.GOTO_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.INSERT_ABOVE]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INSERT_ABOVE_FIRST]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INSERT_BELOW]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INTERRUPT_KERNEL]: MessageType.other,
[CommonActionType.LOADED_ALL_CELLS]: MessageType.other,
[CommonActionType.LINK_CLICK]: MessageType.other,
[CommonActionType.MOVE_CELL_DOWN]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.MOVE_CELL_UP]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.RESTART_KERNEL]: MessageType.other,
[CommonActionType.SAVE]: MessageType.other,
[CommonActionType.SCROLL]: MessageType.syncWithLiveShare,
[CommonActionType.SELECT_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.SELECT_SERVER]: MessageType.other,
[CommonActionType.SEND_COMMAND]: MessageType.other,
[CommonActionType.SHOW_DATA_VIEWER]: MessageType.other,
[CommonActionType.SUBMIT_INPUT]: MessageType.other,
[CommonActionType.TOGGLE_INPUT_BLOCK]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.TOGGLE_LINE_NUMBERS]: MessageType.syncWithLiveShare,
[CommonActionType.TOGGLE_OUTPUT]: MessageType.syncWithLiveShare,
[CommonActionType.TOGGLE_VARIABLE_EXPLORER]: MessageType.syncWithLiveShare,
[CommonActionType.UNFOCUS_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.UNMOUNT]: MessageType.other,

// Types from InteractiveWindowMessages
[InteractiveWindowMessages.Activate]: MessageType.other,
[InteractiveWindowMessages.AddCell]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.AddedSysInfo]: MessageType.other,
[InteractiveWindowMessages.CancelCompletionItemsRequest]: MessageType.other,
[InteractiveWindowMessages.CancelHoverRequest]: MessageType.other,
[InteractiveWindowMessages.CancelResolveCompletionItemRequest]: MessageType.other,
[InteractiveWindowMessages.CancelSignatureHelpRequest]: MessageType.other,
[InteractiveWindowMessages.ClearAllOutputs]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.CollapseAll]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.CopyCodeCell]: MessageType.other,
[InteractiveWindowMessages.DeleteAllCells]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.DeleteCell]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.DoSave]: MessageType.other,
[InteractiveWindowMessages.EditCell]: MessageType.other,
[InteractiveWindowMessages.ExecutionRendered]: MessageType.other,
[InteractiveWindowMessages.ExpandAll]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.Export]: MessageType.other,
[InteractiveWindowMessages.FinishCell]: MessageType.other,
[InteractiveWindowMessages.FocusedCellEditor]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.GatherCodeRequest]: MessageType.other,
[InteractiveWindowMessages.GetAllCells]: MessageType.other,
[InteractiveWindowMessages.GetVariablesRequest]: MessageType.other,
[InteractiveWindowMessages.GetVariablesResponse]: MessageType.other,
[InteractiveWindowMessages.GotoCodeCell]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.GotoCodeCell]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.InsertCell]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.Interrupt]: MessageType.other,
[InteractiveWindowMessages.LoadAllCells]: MessageType.other,
[InteractiveWindowMessages.LoadAllCellsComplete]: MessageType.other,
[InteractiveWindowMessages.LoadOnigasmAssemblyRequest]: MessageType.other,
[InteractiveWindowMessages.LoadOnigasmAssemblyResponse]: MessageType.other,
[InteractiveWindowMessages.LoadTmLanguageRequest]: MessageType.other,
[InteractiveWindowMessages.LoadTmLanguageResponse]: MessageType.other,
[InteractiveWindowMessages.MonacoReady]: MessageType.other,
[InteractiveWindowMessages.NativeCommand]: MessageType.other,
[InteractiveWindowMessages.NotebookAddCellBelow]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.NotebookClean]: MessageType.other,
[InteractiveWindowMessages.NotebookDirty]: MessageType.other,
[InteractiveWindowMessages.NotebookExecutionActivated]: MessageType.other,
[InteractiveWindowMessages.NotebookIdentity]: MessageType.other,
[InteractiveWindowMessages.NotebookRunAllCells]: MessageType.other,
[InteractiveWindowMessages.NotebookRunSelectedCell]: MessageType.other,
[InteractiveWindowMessages.OpenLink]: MessageType.other,
[InteractiveWindowMessages.ProvideCompletionItemsRequest]: MessageType.other,
[InteractiveWindowMessages.ProvideCompletionItemsResponse]: MessageType.other,
[InteractiveWindowMessages.ProvideHoverRequest]: MessageType.other,
[InteractiveWindowMessages.ProvideHoverResponse]: MessageType.other,
[InteractiveWindowMessages.ProvideSignatureHelpRequest]: MessageType.other,
[InteractiveWindowMessages.ProvideSignatureHelpResponse]: MessageType.other,
[InteractiveWindowMessages.ReExecuteCell]: MessageType.other,
[InteractiveWindowMessages.Redo]: MessageType.other,
[InteractiveWindowMessages.RemoteAddCode]: MessageType.other,
[InteractiveWindowMessages.RemoteReexecuteCode]: MessageType.other,
[InteractiveWindowMessages.RemoveCell]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.ResolveCompletionItemRequest]: MessageType.other,
[InteractiveWindowMessages.ResolveCompletionItemResponse]: MessageType.other,
[InteractiveWindowMessages.RestartKernel]: MessageType.other,
[InteractiveWindowMessages.ReturnAllCells]: MessageType.other,
[InteractiveWindowMessages.SaveAll]: MessageType.other,
[InteractiveWindowMessages.SavePng]: MessageType.other,
[InteractiveWindowMessages.ScrollToCell]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.SelectJupyterServer]: MessageType.other,
[InteractiveWindowMessages.SelectKernel]: MessageType.other,
[InteractiveWindowMessages.SendInfo]: MessageType.other,
[InteractiveWindowMessages.SettingsUpdated]: MessageType.other,
[InteractiveWindowMessages.ShowDataViewer]: MessageType.other,
[InteractiveWindowMessages.ShowPlot]: MessageType.other,
[InteractiveWindowMessages.StartCell]: MessageType.other,
[InteractiveWindowMessages.StartDebugging]: MessageType.other,
[InteractiveWindowMessages.StartProgress]: MessageType.other,
[InteractiveWindowMessages.Started]: MessageType.other,
[InteractiveWindowMessages.StopDebugging]: MessageType.other,
[InteractiveWindowMessages.StopProgress]: MessageType.other,
[InteractiveWindowMessages.SubmitNewCell]: MessageType.other,
[InteractiveWindowMessages.SwapCells]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[InteractiveWindowMessages.Sync]: MessageType.other,
[InteractiveWindowMessages.Undo]: MessageType.other,
[InteractiveWindowMessages.UnfocusedCellEditor]: MessageType.syncWithLiveShare,
[InteractiveWindowMessages.UpdateCell]: MessageType.other,
[InteractiveWindowMessages.UpdateKernel]: MessageType.other,
[InteractiveWindowMessages.VariableExplorerToggle]: MessageType.other,
[InteractiveWindowMessages.VariablesComplete]: MessageType.other,
// Types from CssMessages
[CssMessages.GetCssRequest]: MessageType.other,
[CssMessages.GetCssResponse]: MessageType.other,
[CssMessages.GetMonacoThemeRequest]: MessageType.other,
[CssMessages.GetMonacoThemeResponse]: MessageType.other,
// Types from Shared Messages
[SharedMessages.LocInit]: MessageType.other,
[SharedMessages.Started]: MessageType.other,
[SharedMessages.UpdateSettings]: MessageType.other
};

export function isActionPerformedByUser(action: BaseReduxActionPayload<{}> | BaseReduxActionPayload<never>) {
return action.messageType === undefined;
}

export function shouldRebroadcast(message: keyof IInteractiveWindowMapping): [boolean, MessageType] {
const messageType: MessageType | undefined = messageWithMessageTypes[message];
// Support for liveshare is turned off for now, we can enable that later.
// I.e. we only support synchronizing across editors in the same session.
if (messageType === undefined || (messageType & MessageType.syncAcrossSameNotebooks) !== MessageType.syncAcrossSameNotebooks) {
return [false, MessageType.other];
}

return [(messageType & MessageType.syncAcrossSameNotebooks) > 0 || (messageType & MessageType.syncWithLiveShare) > 0, messageType];
}
20 changes: 4 additions & 16 deletions src/client/datascience/interactive-common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@

'use strict';

import { MessageType } from './synchronization';

// Stuff common to React and Extensions.

type BaseData = {
/**
* If this property exists, then this is an action that has been dispatched for the solve purpose of:
* 1. Synchronizing states across different editors (pointing to the same file).
* 2. Synchronizing states across different editors (pointing to the same file) in different sessions.
*
* @type {('syncEditors' | 'syncSessions')}
*/
broadcastReason?: 'syncEditors' | 'syncSessions';
messageType?: MessageType;
/**
* Tells us whether this message is incoming for reducer use or
* whether this is a message that needs to be sent out to extension (from reducer).
Expand All @@ -22,14 +17,7 @@ type BaseData = {
};

type BaseDataWithPayload<T> = {
/**
* If this property exists, then this is an action that has been dispatched for the solve purpose of:
* 1. Synchronizing states across different editors (pointing to the same file).
* 2. Synchronizing states across different editors (pointing to the same file) in different sessions.
*
* @type {('syncEditors' | 'syncSessions')}
*/
broadcastReason?: 'syncEditors' | 'syncSessions';
messageType?: MessageType;
/**
* Tells us whether this message is incoming for reducer use or
* whether this is a message that needs to be sent out to extension (from reducer).
Expand Down
Loading