Merge from vscode b16b467d3e03e1a1ae05b5836e4e5a5af504e86d

This commit is contained in:
ADS Merger
2020-07-01 03:37:27 +00:00
parent 1e805a4156
commit f6b44865cc
51 changed files with 339 additions and 167 deletions

View File

@@ -3,7 +3,7 @@
"description": "Provides rich language support for JSON files.",
"json.schemas.desc": "Associate schemas to JSON files in the current project",
"json.schemas.url.desc": "A URL to a schema or a relative path to a schema in the current directory",
"json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas. `*` can be used as a wildcard. Exclusion patterns can also be defined and start with '!'. A file matches when there at least one matching pattern and the last matching pattern is not an exclusion pattern.",
"json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas. `*` can be used as a wildcard. Exclusion patterns can also be defined and start with '!'. A file matches when there is at least one matching pattern and the last matching pattern is not an exclusion pattern.",
"json.schemas.fileMatch.item.desc": "A file pattern that can contain '*' to match against when resolving JSON files to schemas.",
"json.schemas.schema.desc": "The schema definition for the given URL. The schema only needs to be provided to avoid accesses to the schema URL.",
"json.format.enable.desc": "Enable/disable default JSON formatter",

View File

@@ -63,10 +63,10 @@ The server supports the following settings:
- `format`
- `enable`: Whether the server should register the formatting support. This option is only applicable if the client supports *dynamicRegistration* for *rangeFormatting* and `initializationOptions.provideFormatter` is not defined.
- `schemas`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content.
- `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard. Exclusion patterns can also be defined and start with '!'. A file matches when there at least one matching pattern and the last matching pattern is not an exclusion pattern.
- `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard. Exclusion patterns can also be defined and start with '!'. A file matches when there is at least one matching pattern and the last matching pattern is not an exclusion pattern.
- `url`: The URL of the schema, optional when also a schema is provided.
- `schema`: The schema content.
- `resultLimit`: The max number foldig ranges and otline symbols to be computed (for performance reasons)
- `resultLimit`: The max number folding ranges and outline symbols to be computed (for performance reasons)
```json
{
@@ -160,7 +160,7 @@ Notification:
### Item Limit
If the setting `resultLimit` is set, the JSON language server will limit the number of folding ranges and document symbols computed.
When the limit is reached, a notification `json/resultLimitReached` is sent that can be shown that camn be shown to the user.
When the limit is reached, a notification `json/resultLimitReached` is sent that can be shown that can be shown to the user.
Notification:
- method: 'json/resultLimitReached'
@@ -180,7 +180,7 @@ For that, install the `json-language-server` npm module:
`npm install -g json-language-server`
Start the language server with the `json-language-server` command. Use a command line argument to specify the prefered communication channel:
Start the language server with the `json-language-server` command. Use a command line argument to specify the preferred communication channel:
```
json-language-server --node-ipc

View File

@@ -190,5 +190,11 @@
"foreground": "#C8C8C8"
}
}
]
],
"semanticTokenColors": {
"newOperator":"#C586C0",
"stringLiteral":"#ce9178",
"customLiteral": "#DCDCAA",
"numberLiteral": "#b5cea8",
}
}

View File

@@ -45,7 +45,6 @@
{
"scope": [
"constant.numeric",
"entity.name.operator.custom-literal.number",
"variable.other.enummember",
"keyword.operator.plus.exponent",
"keyword.operator.minus.exponent"
@@ -226,7 +225,6 @@
{
"scope": [
"string",
"entity.name.operator.custom-literal.string",
"meta.embedded.assembly"
],
"settings": {
@@ -364,5 +362,11 @@
"foreground": "#569cd6"
}
}
]
],
"semanticTokenColors": {
"newOperator": "#d4d4d4",
"stringLiteral": "#ce9178",
"customLiteral": "#D4D4D4",
"numberLiteral": "#b5cea8",
}
}

View File

@@ -190,5 +190,11 @@
"foreground": "#000000"
}
}
]
],
"semanticTokenColors": {
"newOperator": "#AF00DB",
"stringLiteral": "#a31515",
"customLiteral": "#795E26",
"numberLiteral": "#098658",
}
}

View File

@@ -45,7 +45,6 @@
{
"scope": [
"constant.numeric",
"entity.name.operator.custom-literal.number",
"variable.other.enummember",
"keyword.operator.plus.exponent",
"keyword.operator.minus.exponent"
@@ -218,7 +217,6 @@
{
"scope": [
"string",
"entity.name.operator.custom-literal.string",
"meta.embedded.assembly"
],
"settings": {
@@ -388,5 +386,11 @@
"foreground": "#0000ff"
}
}
]
],
"semanticTokenColors": {
"newOperator": "#0000ff",
"stringLiteral": "#a31515",
"customLiteral": "#000000",
"numberLiteral": "#098658",
}
}

View File

@@ -41,8 +41,8 @@ const defaultOpts = {
export class CheckboxActionViewItem extends BaseActionViewItem {
private checkbox: Checkbox | undefined;
private readonly disposables = new DisposableStore();
protected checkbox: Checkbox | undefined;
protected readonly disposables = new DisposableStore();
render(container: HTMLElement): void {
this.element = container;

View File

@@ -56,6 +56,7 @@ bootstrapWindow.load([
],
function (workbench, configuration) {
perf.mark('didLoadWorkbenchMain');
performance.mark('workbench-start');
return process['lazyEnv'].then(function () {
perf.mark('main/startup');

View File

@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionbar';
import { CheckboxActionViewItem } from 'vs/base/browser/ui/checkbox/checkbox';
import { IAction } from 'vs/base/common/actions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachCheckboxStyler } from 'vs/platform/theme/common/styler';
export class ThemableCheckboxActionViewItem extends CheckboxActionViewItem {
constructor(context: any, action: IAction, options: IBaseActionViewItemOptions | undefined, private readonly themeService: IThemeService) {
super(context, action, options);
}
render(container: HTMLElement): void {
super.render(container);
if (this.checkbox) {
this.disposables.add(attachCheckboxStyler(this.checkbox, this.themeService));
}
}
}

View File

@@ -151,7 +151,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts.") },
'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id[@version] | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts. The identifier of an extension is always `${publisher}.${name}`. To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.") },
'uninstall-extension': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") },

View File

@@ -53,7 +53,7 @@ export class MockContextKeyService implements IContextKeyService {
public get onDidChangeContext(): Event<IContextKeyChangeEvent> {
return Event.None;
}
public bufferChangeEvents() { }
public bufferChangeEvents(callback: () => void) { callback(); }
public getContextKeyValue(key: string) {
const value = this._keys.get(key);
if (value) {

View File

@@ -21,6 +21,7 @@ import { IRelativePattern } from 'vs/base/common/glob';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
export class MainThreadNotebookDocument extends Disposable {
private _textModel: NotebookTextModel;
@@ -36,12 +37,13 @@ export class MainThreadNotebookDocument extends Disposable {
public supportBackup: boolean,
public uri: URI,
@INotebookService readonly notebookService: INotebookService,
@IUndoRedoService readonly undoRedoService: IUndoRedoService
@IUndoRedoService readonly undoRedoService: IUndoRedoService,
@ITextModelService modelService: ITextModelService
) {
super();
this._textModel = new NotebookTextModel(handle, viewType, supportBackup, uri, undoRedoService);
this._textModel = new NotebookTextModel(handle, viewType, supportBackup, uri, undoRedoService, modelService);
this._register(this._textModel.onDidModelChangeProxy(e => {
this._proxy.$acceptModelChanged(this.uri, e);
this._proxy.$acceptEditorPropertiesChanged(uri, { selections: { selections: this._textModel.selections }, metadata: null });

View File

@@ -227,7 +227,7 @@ export class TreeViewDataProvider implements ITreeViewDataProvider {
const resolvable = new ResolvableTreeItem(element, hasResolve ? () => {
return this._proxy.$resolve(this.treeViewId, element.handle);
} : undefined);
this.itemsMap.set(element.handle, element);
this.itemsMap.set(element.handle, resolvable);
result.push(resolvable);
}
}

View File

@@ -210,7 +210,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.activeEditorContext.set(activeEditorPane.getId());
this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly());
const editors = activeEditorPane.input.resource ? this.editorService.getEditorOverrides(activeEditorPane.input.resource, undefined, activeGroup) : [];
const editors = activeEditorPane.input.resource ? this.editorService.getEditorOverrides(activeEditorPane.input.resource, undefined, activeGroup, undefined) : [];
this.activeEditorAvailableEditorIds.set(editors.map(([_, entry]) => entry.id).join(','));
} else {
this.activeEditorContext.reset();

View File

@@ -457,6 +457,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_RIGHT, title: nls.localize('splitRight', "Split Right") }, group: '5_split', order: 40 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: ReopenResourcesAction.ID, title: ReopenResourcesAction.LABEL }, group: '6_reopen', order: 20, when: ActiveEditorAvailableEditorIdsContext });
// Editor Title Menu
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.TOGGLE_DIFF_SIDE_BY_SIDE, title: nls.localize('toggleInlineView', "Toggle Inline View") }, group: '1_diff', order: 10, when: ContextKeyExpr.has('isInDiffEditor') });

View File

@@ -1836,7 +1836,7 @@ export class ToggleEditorTypeAction extends Action {
const options = activeEditorPane.options;
const group = activeEditorPane.group;
const overrides = getAllAvailableEditors(input.resource, options, group, this.editorService);
const overrides = getAllAvailableEditors(input.resource, undefined, options, group, this.editorService);
const firstNonActiveOverride = overrides.find(([_, entry]) => !entry.active);
if (!firstNonActiveOverride) {
return;

View File

@@ -50,10 +50,15 @@
outline-offset: -2px;
}
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.clicked:focus .action-label {
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.clicked:not(.checked):focus .action-label {
border-bottom-color: transparent !important; /* hides border on clicked state */
}
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked.clicked:focus .action-label,
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked.active:focus .action-label {
border-bottom-color: currentColor !important;
}
/** Panel Switcher */
.monaco-workbench .part.panel > .composite.title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.codicon-more {

View File

@@ -430,7 +430,8 @@ export class CustomMenubarControl extends MenubarControl {
primary: KeyCode.F10,
weight: KeybindingWeight.WorkbenchContrib,
when: IsWebContext
}
},
f1: true
});
}

View File

@@ -416,6 +416,10 @@ export class Workbench extends Layout {
// Telemetry: startup metrics
mark('didStartWorkbench');
// Perf reporting (devtools)
performance.mark('workbench-end');
performance.measure('perf: workbench create & restore', 'workbench-start', 'workbench-end');
}
}
}

View File

@@ -451,29 +451,45 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo
open: (editor, options, group) => {
return this.onEditorOpening(editor, options, group);
},
getEditorOverrides: (resource: URI, _options: IEditorOptions | undefined, group: IEditorGroup | undefined): IOpenEditorOverrideEntry[] => {
getEditorOverrides: (resource: URI, _options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): IOpenEditorOverrideEntry[] => {
const currentEditor = group?.editors.find(editor => isEqual(editor.resource, resource));
const defaultEditorOverride: IOpenEditorOverrideEntry = {
...defaultEditorOverrideEntry,
active: this._fileEditorInputFactory.isFileEditorInput(currentEditor),
};
const toOverride = (entry: CustomEditorInfo): IOpenEditorOverrideEntry => {
return {
id: entry.id,
active: currentEditor instanceof CustomEditorInput && currentEditor.viewType === entry.id,
label: entry.displayName,
detail: entry.providerDisplayName,
};
};
if (typeof id === 'string') {
// A specific override was requested. Only return it.
if (id === defaultEditorOverride.id) {
return [defaultEditorOverride];
}
const matchingEditor = this.customEditorService.getCustomEditor(id);
return matchingEditor ? [toOverride(matchingEditor)] : [];
}
// Otherwise, return all potential overrides.
const customEditors = this.customEditorService.getAllCustomEditors(resource);
if (!customEditors.length) {
return [];
}
return [
{
...defaultEditorOverrideEntry,
active: this._fileEditorInputFactory.isFileEditorInput(currentEditor),
},
defaultEditorOverride,
...customEditors.allEditors
.filter(entry => entry.id !== defaultCustomEditor.id)
.map(entry => {
return {
id: entry.id,
active: currentEditor instanceof CustomEditorInput && currentEditor.viewType === entry.id,
label: entry.displayName,
detail: entry.providerDisplayName,
};
})
.map(toOverride)
];
}
}));

View File

@@ -98,7 +98,10 @@ export class ConfigureAction extends AbstractDebugAction {
launch = launches[0];
} else {
const picks = launches.map(l => ({ label: l.name, launch: l }));
const picked = await this.quickInputService.pick<{ label: string, launch: ILaunch }>(picks, { activeItem: picks[0], placeHolder: nls.localize('selectWorkspaceFolder', "Select a workspace folder to create a launch.json file in or add it to the workspace config file") });
const picked = await this.quickInputService.pick<{ label: string, launch: ILaunch }>(picks, {
activeItem: picks[0],
placeHolder: nls.localize({ key: 'selectWorkspaceFolder', comment: ['User picks a workspace folder or a workspace configuration file here. Workspace configuration files can contain settings and thus a launch.json configuration can be written into one.'] }, "Select a workspace folder to create a launch.json file in or add it to the workspace config file")
});
if (picked) {
launch = picked.launch;
}

View File

@@ -247,7 +247,7 @@ class ShowDebugHoverAction extends EditorAction {
class StepIntoTargetsAction extends EditorAction {
public static readonly ID = 'editor.debug.action.stepIntoTargets';
public static readonly LABEL = nls.localize('stepIntoTargets', "Step Into Targets...");
public static readonly LABEL = nls.localize({ key: 'stepIntoTargets', comment: ['Step Into Targets lets the user step into an exact function he or she is interested in.'] }, "Step Into Targets...");
constructor() {
super({

View File

@@ -61,11 +61,11 @@ export class DebugService implements IDebugService {
private taskRunner: DebugTaskRunner;
private configurationManager: ConfigurationManager;
private toDispose: IDisposable[];
private debugType: IContextKey<string>;
private debugState: IContextKey<string>;
private inDebugMode: IContextKey<boolean>;
private debugUx: IContextKey<string>;
private breakpointsExist: IContextKey<boolean>;
private debugType!: IContextKey<string>;
private debugState!: IContextKey<string>;
private inDebugMode!: IContextKey<boolean>;
private debugUx!: IContextKey<string>;
private breakpointsExist!: IContextKey<boolean>;
private breakpointsToSendOnResourceSaved: Set<string>;
private initializing = false;
private previousState: State | undefined;
@@ -80,7 +80,7 @@ export class DebugService implements IDebugService {
@IDialogService private readonly dialogService: IDialogService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IExtensionService private readonly extensionService: IExtensionService,
@@ -101,17 +101,19 @@ export class DebugService implements IDebugService {
this.configurationManager = this.instantiationService.createInstance(ConfigurationManager);
this.toDispose.push(this.configurationManager);
this.debugType = CONTEXT_DEBUG_TYPE.bindTo(contextKeyService);
this.debugState = CONTEXT_DEBUG_STATE.bindTo(contextKeyService);
this.inDebugMode = CONTEXT_IN_DEBUG_MODE.bindTo(contextKeyService);
this.debugUx = CONTEXT_DEBUG_UX.bindTo(contextKeyService);
this.debugUx.set(!!this.configurationManager.selectedConfiguration.name ? 'default' : 'simple');
contextKeyService.bufferChangeEvents(() => {
this.debugType = CONTEXT_DEBUG_TYPE.bindTo(contextKeyService);
this.debugState = CONTEXT_DEBUG_STATE.bindTo(contextKeyService);
this.inDebugMode = CONTEXT_IN_DEBUG_MODE.bindTo(contextKeyService);
this.debugUx = CONTEXT_DEBUG_UX.bindTo(contextKeyService);
this.debugUx.set(!!this.configurationManager.selectedConfiguration.name ? 'default' : 'simple');
this.breakpointsExist = CONTEXT_BREAKPOINTS_EXIST.bindTo(contextKeyService);
});
this.debugStorage = this.instantiationService.createInstance(DebugStorage);
this.model = this.instantiationService.createInstance(DebugModel, this.debugStorage);
this.telemetry = this.instantiationService.createInstance(DebugTelemetry, this.model);
const setBreakpointsExistContext = () => this.breakpointsExist.set(!!(this.model.getBreakpoints().length || this.model.getDataBreakpoints().length || this.model.getFunctionBreakpoints().length));
this.breakpointsExist = CONTEXT_BREAKPOINTS_EXIST.bindTo(contextKeyService);
setBreakpointsExistContext();
this.viewModel = new ViewModel(contextKeyService);
@@ -229,10 +231,12 @@ export class DebugService implements IDebugService {
private onStateChange(): void {
const state = this.state;
if (this.previousState !== state) {
this.debugState.set(getStateLabel(state));
this.inDebugMode.set(state !== State.Inactive);
// Only show the simple ux if debug is not yet started and if no launch.json exists
this.debugUx.set(((state !== State.Inactive && state !== State.Initializing) || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
this.contextKeyService.bufferChangeEvents(() => {
this.debugState.set(getStateLabel(state));
this.inDebugMode.set(state !== State.Inactive);
// Only show the simple ux if debug is not yet started and if no launch.json exists
this.debugUx.set(((state !== State.Inactive && state !== State.Initializing) || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
});
this.previousState = state;
this._onDidChangeState.fire(state);
}

View File

@@ -78,7 +78,9 @@
}
/* Make icons and text the same color as the list foreground on focus selection */
.debug-pane .monaco-list:focus .monaco-list-row.selected .state > .label,
.debug-pane .monaco-list:focus .monaco-list-row.selected.focused .state > .label,
.debug-pane .monaco-list:focus .monaco-list-row.selected .codicon,
.debug-pane .monaco-list:focus .monaco-list-row.selected.focused .codicon {
color: inherit !important;
}

View File

@@ -362,10 +362,10 @@ export class ReplAccessibilityProvider implements IListAccessibilityProvider<IRe
return localize('replValueOutputAriaLabel', "{0}", element.value);
}
if (element instanceof RawObjectReplElement) {
return localize('replRawObjectAriaLabel', "Repl variable {0}, value {1}", element.name, element.value);
return localize('replRawObjectAriaLabel', "Debug console variable {0}, value {1}", element.name, element.value);
}
if (element instanceof ReplGroup) {
return localize('replGroup', "Repl group {0}, read eval print loop, debug", element.name);
return localize('replGroup', "Debug console group {0}, read eval print loop, debug", element.name);
}
return '';

View File

@@ -21,25 +21,27 @@ export class ViewModel implements IViewModel {
private readonly _onDidFocusStackFrame = new Emitter<{ stackFrame: IStackFrame | undefined, explicit: boolean }>();
private readonly _onDidSelectExpression = new Emitter<IExpression | undefined>();
private multiSessionView: boolean;
private expressionSelectedContextKey: IContextKey<boolean>;
private breakpointSelectedContextKey: IContextKey<boolean>;
private loadedScriptsSupportedContextKey: IContextKey<boolean>;
private stepBackSupportedContextKey: IContextKey<boolean>;
private focusedSessionIsAttach: IContextKey<boolean>;
private restartFrameSupportedContextKey: IContextKey<boolean>;
private stepIntoTargetsSupported: IContextKey<boolean>;
private jumpToCursorSupported: IContextKey<boolean>;
private expressionSelectedContextKey!: IContextKey<boolean>;
private breakpointSelectedContextKey!: IContextKey<boolean>;
private loadedScriptsSupportedContextKey!: IContextKey<boolean>;
private stepBackSupportedContextKey!: IContextKey<boolean>;
private focusedSessionIsAttach!: IContextKey<boolean>;
private restartFrameSupportedContextKey!: IContextKey<boolean>;
private stepIntoTargetsSupported!: IContextKey<boolean>;
private jumpToCursorSupported!: IContextKey<boolean>;
constructor(contextKeyService: IContextKeyService) {
constructor(private contextKeyService: IContextKeyService) {
this.multiSessionView = false;
this.expressionSelectedContextKey = CONTEXT_EXPRESSION_SELECTED.bindTo(contextKeyService);
this.breakpointSelectedContextKey = CONTEXT_BREAKPOINT_SELECTED.bindTo(contextKeyService);
this.loadedScriptsSupportedContextKey = CONTEXT_LOADED_SCRIPTS_SUPPORTED.bindTo(contextKeyService);
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService);
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
contextKeyService.bufferChangeEvents(() => {
this.expressionSelectedContextKey = CONTEXT_EXPRESSION_SELECTED.bindTo(contextKeyService);
this.breakpointSelectedContextKey = CONTEXT_BREAKPOINT_SELECTED.bindTo(contextKeyService);
this.loadedScriptsSupportedContextKey = CONTEXT_LOADED_SCRIPTS_SUPPORTED.bindTo(contextKeyService);
this.stepBackSupportedContextKey = CONTEXT_STEP_BACK_SUPPORTED.bindTo(contextKeyService);
this.focusedSessionIsAttach = CONTEXT_FOCUSED_SESSION_IS_ATTACH.bindTo(contextKeyService);
this.restartFrameSupportedContextKey = CONTEXT_RESTART_FRAME_SUPPORTED.bindTo(contextKeyService);
this.stepIntoTargetsSupported = CONTEXT_STEP_INTO_TARGETS_SUPPORTED.bindTo(contextKeyService);
this.jumpToCursorSupported = CONTEXT_JUMP_TO_CURSOR_SUPPORTED.bindTo(contextKeyService);
});
}
getId(): string {
@@ -66,13 +68,15 @@ export class ViewModel implements IViewModel {
this._focusedThread = thread;
this._focusedSession = session;
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
this.stepIntoTargetsSupported.set(session ? !!session.capabilities.supportsStepInTargetsRequest : false);
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
const attach = !!session && isSessionAttach(session);
this.focusedSessionIsAttach.set(attach);
this.contextKeyService.bufferChangeEvents(() => {
this.loadedScriptsSupportedContextKey.set(session ? !!session.capabilities.supportsLoadedSourcesRequest : false);
this.stepBackSupportedContextKey.set(session ? !!session.capabilities.supportsStepBack : false);
this.restartFrameSupportedContextKey.set(session ? !!session.capabilities.supportsRestartFrame : false);
this.stepIntoTargetsSupported.set(session ? !!session.capabilities.supportsStepInTargetsRequest : false);
this.jumpToCursorSupported.set(session ? !!session.capabilities.supportsGotoTargetsRequest : false);
const attach = !!session && isSessionAttach(session);
this.focusedSessionIsAttach.set(attach);
});
if (shouldEmitForSession) {
this._onDidFocusSession.fire(session);

View File

@@ -175,7 +175,7 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa
} else if (canHandlePermissionOrReadonlyErrors && isPermissionDenied) {
message = isWindows ? nls.localize('permissionDeniedSaveError', "Failed to save '{0}': Insufficient permissions. Select 'Retry as Admin' to retry as administrator.", basename(resource)) : nls.localize('permissionDeniedSaveErrorSudo', "Failed to save '{0}': Insufficient permissions. Select 'Retry as Sudo' to retry as superuser.", basename(resource));
} else {
message = nls.localize('genericSaveError', "Failed to save '{0}': {1}", basename(resource), toErrorMessage(error, false));
message = nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", basename(resource), toErrorMessage(error, false));
}
}

View File

@@ -410,7 +410,7 @@ async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentif
try {
await editorService.save(editors, options);
} catch (error) {
notificationService.error(nls.localize('genericSaveError', "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)));
notificationService.error(nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)));
}
}

View File

@@ -486,7 +486,7 @@ export class ExplorerView extends ViewPane {
this.rootContext.set(!stat || (stat && stat.isRoot));
if (resource) {
const overrides = resource ? this.editorService.getEditorOverrides(resource, undefined, undefined) : [];
const overrides = resource ? this.editorService.getEditorOverrides(resource, undefined, undefined, undefined) : [];
this.availableEditorIdsContext.set(overrides.map(([, entry]) => entry.id).join(','));
} else {
this.availableEditorIdsContext.reset();

View File

@@ -518,7 +518,8 @@ registerAction2(class extends InsertCellCommand {
MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {
command: {
id: INSERT_CODE_CELL_BELOW_COMMAND_ID,
title: localize('notebookActions.menu.insertCode', "$(add) Code")
title: localize('notebookActions.menu.insertCode', "$(add) Code"),
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
},
order: 0,
group: 'inline'
@@ -551,7 +552,8 @@ registerAction2(class extends InsertCellCommand {
MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {
command: {
id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,
title: localize('notebookActions.menu.insertMarkdown', "$(add) Markdown")
title: localize('notebookActions.menu.insertMarkdown', "$(add) Markdown"),
tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")
},
order: 1,
group: 'inline'

View File

@@ -17,6 +17,11 @@
white-space: initial;
}
.monaco-workbench .cell.markdown p.emptyMarkdownPlaceholder {
font-style: italic;
opacity: 0.6;
}
.monaco-workbench .notebookOverlay .simple-fr-find-part-wrapper.visible {
z-index: 100;
}
@@ -308,8 +313,8 @@
}
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .codicon {
margin: 0 0 0 2px; /* accounts for 2px indicator on left */
padding: 4px;
margin: 0;
padding: 0 4px;
}
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .actions-container {
@@ -324,14 +329,14 @@
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .execution-count-label {
position: absolute;
top: 2px;
top: -2px;
font-size: 10px;
font-family: var(--monaco-monospace-font);
visibility: visible;
white-space: pre;
width: 100%;
text-align: center;
padding-right: 2px;
padding-right: 8px;
box-sizing: border-box;
opacity: .6;
}

View File

@@ -57,6 +57,7 @@ import 'vs/workbench/contrib/notebook/browser/contrib/status/editorStatus';
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform';
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform';
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
/*--------------------------------------------------------------------------------------------- */
@@ -247,7 +248,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri
cellOptions = { resource: originalInput.resource, options };
}
if (id === undefined) {
if (id === undefined && originalInput instanceof ResourceEditorInput) {
const exitingNotebookEditor = <NotebookEditorInput | undefined>group.editors.find(editor => editor instanceof NotebookEditorInput && isEqual(editor.resource, notebookUri));
id = exitingNotebookEditor?.viewType;
}

View File

@@ -84,7 +84,13 @@ export class NotebookEditorInput extends EditorInput {
async save(group: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
if (this._textModel) {
await this._textModel.object.save();
if (this.isUntitled()) {
return this.saveAs(group, options);
} else {
await this._textModel.object.save();
}
return this;
}

View File

@@ -921,7 +921,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const insertIndex = cell ?
(direction === 'above' ? index : nextIndex) :
index;
const newCell = this._notebookViewModel!.createCell(insertIndex, initialText.split(/\r?\n/g), language, type, cell?.metadata, true);
const newCell = this._notebookViewModel!.createCell(insertIndex, initialText.split(/\r?\n/g), language, type, undefined, true);
return newCell as CellViewModel;
}

View File

@@ -666,9 +666,7 @@ export class CellDragAndDropController extends Disposable {
}
private async moveCell(draggedCell: ICellViewModel, ontoCell: ICellViewModel, direction: 'above' | 'below') {
const editState = draggedCell.editState;
await this.notebookEditor.moveCell(draggedCell, ontoCell, direction);
this.notebookEditor.focusNotebookCell(draggedCell, editState === CellEditState.Editing ? 'editor' : 'container');
}
private copyCell(draggedCell: ICellViewModel, ontoCell: ICellViewModel, direction: 'above' | 'below') {

View File

@@ -7,7 +7,6 @@ import { Emitter, Event } from 'vs/base/common/event';
import * as UUID from 'vs/base/common/uuid';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
import { BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_MARGIN, CELL_RUN_GUTTER, CELL_STATUSBAR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_MARGIN, EDITOR_TOP_PADDING, CELL_BOTTOM_MARGIN, CODE_CELL_LEFT_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -69,8 +68,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
readonly viewType: string,
readonly model: NotebookCellTextModel,
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
readonly eventDispatcher: NotebookEventDispatcher,
@ITextModelService private readonly _modelService: ITextModelService,
readonly eventDispatcher: NotebookEventDispatcher
) {
super(viewType, model, UUID.generateUuid());
this._register(this.model.onDidChangeOutputs((splices) => {
@@ -174,7 +172,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
*/
async resolveTextModel(): Promise<model.ITextModel> {
if (!this.textModel) {
const ref = await this._modelService.createModelReference(this.model.uri);
const ref = await this.model.resolveTextModelRef();
this.textModel = ref.object.textEditorModel;
this._register(ref);
this._register(this.textModel.onDidChangeContent(() => {
@@ -257,4 +255,8 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
matches
};
}
dispose() {
super.dispose();
}
}

View File

@@ -3,12 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Emitter, Event } from 'vs/base/common/event';
import * as UUID from 'vs/base/common/uuid';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_MARGIN, CELL_RUN_GUTTER, CELL_STATUSBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
import { BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_MARGIN, CELL_RUN_GUTTER, CELL_STATUSBAR_HEIGHT, EDITOR_TOP_MARGIN, CELL_BOTTOM_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellFindMatch, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer';
import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel';
@@ -45,7 +45,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
set editorHeight(newHeight: number) {
this._editorHeight = newHeight;
this.totalHeight = this._editorHeight + BOTTOM_CELL_TOOLBAR_HEIGHT + CELL_STATUSBAR_HEIGHT;
this.totalHeight = this._editorHeight + EDITOR_TOP_MARGIN + CELL_BOTTOM_MARGIN + BOTTOM_CELL_TOOLBAR_HEIGHT + CELL_STATUSBAR_HEIGHT;
}
get editorHeight() {
@@ -65,8 +65,8 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
readonly foldingDelegate: EditorFoldingStateDelegate,
readonly eventDispatcher: NotebookEventDispatcher,
private readonly _mdRenderer: MarkdownRenderer,
@ITextModelService private readonly _modelService: ITextModelService) {
private readonly _mdRenderer: MarkdownRenderer
) {
super(viewType, model, UUID.generateUuid());
this._layoutInfo = {
@@ -140,7 +140,17 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
return this._html;
}
let renderer = this.getMarkdownRenderer();
this._html = renderer.render({ value: this.getText(), isTrusted: true }).element;
const text = this.getText();
if (text.length === 0) {
const el = document.createElement('p');
el.className = 'emptyMarkdownPlaceholder';
el.innerText = nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit.");
this._html = el;
} else {
this._html = renderer.render({ value: this.getText(), isTrusted: true }).element;
}
return this._html;
}
return null;
@@ -148,7 +158,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
async resolveTextModel(): Promise<model.ITextModel> {
if (!this.textModel) {
const ref = await this._modelService.createModelReference(this.model.uri);
const ref = await this.model.resolveTextModelRef();
this.textModel = ref.object.textEditorModel;
this._register(ref);
this._register(this.textModel.onDidChangeContent(() => {

View File

@@ -10,6 +10,7 @@ import { URI } from 'vs/base/common/uri';
import * as model from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { Disposable } from 'vs/base/common/lifecycle';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
export class NotebookCellTextModel extends Disposable implements ICell {
private _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
@@ -86,7 +87,8 @@ export class NotebookCellTextModel extends Disposable implements ICell {
private _language: string,
public cellKind: CellKind,
outputs: IProcessedOutput[],
metadata: NotebookCellMetadata | undefined
metadata: NotebookCellMetadata | undefined,
private readonly _modelService: ITextModelService
) {
super();
this._outputs = outputs;
@@ -139,4 +141,17 @@ export class NotebookCellTextModel extends Disposable implements ICell {
}
};
}
async resolveTextModelRef() {
const ref = await this._modelService.createModelReference(this.uri);
ref.object.textEditorModel.onWillDispose(() => {
this.textModel = undefined;
});
return ref;
}
dispose() {
super.dispose();
}
}

View File

@@ -11,6 +11,7 @@ import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSpl
import { ITextSnapshot } from 'vs/editor/common/model';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
function compareRangesUsingEnds(a: [number, number], b: [number, number]): number {
if (a[1] === b[1]) {
@@ -115,7 +116,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
public viewType: string,
public supportBackup: boolean,
public uri: URI,
private _undoService: IUndoRedoService
private _undoService: IUndoRedoService,
private _modelService: ITextModelService
) {
super();
this.cells = [];
@@ -141,7 +143,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
) {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata);
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata, this._modelService);
}
initialize(cells: ICellDto2[]) {
@@ -151,7 +153,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const mainCells = cells.map(cell => {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
});
this._isUntitled = false;
@@ -215,7 +217,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const mainCells = insertEdit.cells.map(cell => {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
});
this.insertNewCell(insertEdit.index, mainCells, false);
break;
@@ -583,6 +585,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
dispose() {
this._onWillDispose.fire();
this._cellListeners.forEach(val => val.dispose());
this.cells.forEach(cell => cell.dispose());
super.dispose();
}
}

View File

@@ -148,6 +148,7 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
const notebook = await this._notebookService.createNotebookFromBackup(this.viewType!, this.resource, data.metadata, data.languages, data.cells, editorId);
this._notebook = notebook!;
this._register(this._notebook);
this._name = basename(this._notebook!.uri);
@@ -167,6 +168,7 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
private async loadFromProvider(forceReloadFromDisk: boolean, editorId: string | undefined, backupId: string | undefined) {
const notebook = await this._notebookService.resolveNotebook(this.viewType!, this.resource, forceReloadFromDisk, editorId, backupId);
this._notebook = notebook!;
this._register(this._notebook);
this._name = basename(this._notebook!.uri);
@@ -210,4 +212,8 @@ export class NotebookEditorModel extends EditorModel implements IWorkingCopy, IN
this._notebook.setDirty(false);
return true;
}
dispose() {
super.dispose();
}
}

View File

@@ -5,10 +5,14 @@
import * as assert from 'assert';
import { NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, CellKind, diff, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { TestCell } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { URI } from 'vs/base/common/uri';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
suite('NotebookCommon', () => {
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
test('sortMimeTypes default orders', function () {
const defaultDisplayOrder = NOTEBOOK_DISPLAY_ORDER;
@@ -265,7 +269,7 @@ suite('NotebookCommon', () => {
for (let i = 0; i < 5; i++) {
cells.push(
new TestCell('notebook', i, [`var a = ${i};`], 'javascript', CellKind.Code, [])
new TestCell('notebook', i, [`var a = ${i};`], 'javascript', CellKind.Code, [], textModelService)
);
}
@@ -291,8 +295,8 @@ suite('NotebookCommon', () => {
]
);
const cellA = new TestCell('notebook', 6, ['var a = 6;'], 'javascript', CellKind.Code, []);
const cellB = new TestCell('notebook', 7, ['var a = 7;'], 'javascript', CellKind.Code, []);
const cellA = new TestCell('notebook', 6, ['var a = 6;'], 'javascript', CellKind.Code, [], textModelService);
const cellB = new TestCell('notebook', 7, ['var a = 7;'], 'javascript', CellKind.Code, [], textModelService);
const modifiedCells = [
cells[0],

View File

@@ -4,14 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { CellKind, CellEditType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { withTestNotebook, TestCell } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { withTestNotebook, TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
suite('NotebookTextModel', () => {
const instantiationService = new TestInstantiationService();
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const blukEditService = instantiationService.get(IBulkEditService);
const undoRedoService = instantiationService.stub(IUndoRedoService, () => { });
instantiationService.spy(IUndoRedoService, 'pushElement');
@@ -29,8 +30,8 @@ suite('NotebookTextModel', () => {
],
(editor, viewModel, textModel) => {
textModel.$applyEdit(textModel.versionId, [
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 3, cells: [new TestCell(viewModel.viewType, 6, ['var f = 6;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Insert, index: 3, cells: [new TestCell(viewModel.viewType, 6, ['var f = 6;'], 'javascript', CellKind.Code, [], textModelService)] },
], true, true);
assert.equal(textModel.cells.length, 6);
@@ -54,8 +55,8 @@ suite('NotebookTextModel', () => {
],
(editor, viewModel, textModel) => {
textModel.$applyEdit(textModel.versionId, [
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 6, ['var f = 6;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 6, ['var f = 6;'], 'javascript', CellKind.Code, [], textModelService)] },
], true, true);
assert.equal(textModel.cells.length, 6);
@@ -103,7 +104,7 @@ suite('NotebookTextModel', () => {
(editor, viewModel, textModel) => {
textModel.$applyEdit(textModel.versionId, [
{ editType: CellEditType.Delete, index: 1, count: 1 },
{ editType: CellEditType.Insert, index: 3, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 3, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [], textModelService)] },
], true, true);
assert.equal(textModel.cells.length, 4);
@@ -128,7 +129,7 @@ suite('NotebookTextModel', () => {
(editor, viewModel, textModel) => {
textModel.$applyEdit(textModel.versionId, [
{ editType: CellEditType.Delete, index: 1, count: 1 },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [])] },
{ editType: CellEditType.Insert, index: 1, cells: [new TestCell(viewModel.viewType, 5, ['var e = 5;'], 'javascript', CellKind.Code, [], textModelService)] },
], true, true);
assert.equal(textModel.cells.length, 4);

View File

@@ -5,25 +5,25 @@
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, NotebookCellMetadata, diff } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { withTestNotebook, TestCell, NotebookEditorTestModel } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { withTestNotebook, TestCell, NotebookEditorTestModel, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { TrackedRangeStickiness } from 'vs/editor/common/model';
import { reduceCellRanges, ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
suite('NotebookViewModel', () => {
const instantiationService = new TestInstantiationService();
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const blukEditService = instantiationService.get(IBulkEditService);
const undoRedoService = instantiationService.stub(IUndoRedoService, () => { });
instantiationService.spy(IUndoRedoService, 'pushElement');
const undoRedoService = instantiationService.get(IUndoRedoService);
test('ctor', function () {
const notebook = new NotebookTextModel(0, 'notebook', false, URI.parse('test'), undoRedoService);
const notebook = new NotebookTextModel(0, 'notebook', false, URI.parse('test'), undoRedoService, textModelService);
const model = new NotebookEditorTestModel(notebook);
const eventDispatcher = new NotebookEventDispatcher();
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, blukEditService, undoRedoService);
@@ -43,7 +43,7 @@ suite('NotebookViewModel', () => {
assert.equal(viewModel.viewCells[0].metadata?.editable, true);
assert.equal(viewModel.viewCells[1].metadata?.editable, false);
const cell = viewModel.insertCell(1, new TestCell(viewModel.viewType, 0, ['var c = 3;'], 'javascript', CellKind.Code, []), true);
const cell = viewModel.insertCell(1, new TestCell(viewModel.viewType, 0, ['var c = 3;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.equal(viewModel.viewCells.length, 3);
assert.equal(viewModel.notebookDocument.cells.length, 3);
assert.equal(viewModel.getCellIndex(cell), 1);
@@ -126,13 +126,13 @@ suite('NotebookViewModel', () => {
const lastViewCell = viewModel.viewCells[viewModel.viewCells.length - 1];
const insertIndex = viewModel.getCellIndex(firstViewCell) + 1;
const cell = viewModel.insertCell(insertIndex, new TestCell(viewModel.viewType, 3, ['var c = 3;'], 'javascript', CellKind.Code, []), true);
const cell = viewModel.insertCell(insertIndex, new TestCell(viewModel.viewType, 3, ['var c = 3;'], 'javascript', CellKind.Code, [], textModelService), true);
const addedCellIndex = viewModel.getCellIndex(cell);
viewModel.deleteCell(addedCellIndex, true);
const secondInsertIndex = viewModel.getCellIndex(lastViewCell) + 1;
const cell2 = viewModel.insertCell(secondInsertIndex, new TestCell(viewModel.viewType, 4, ['var d = 4;'], 'javascript', CellKind.Code, []), true);
const cell2 = viewModel.insertCell(secondInsertIndex, new TestCell(viewModel.viewType, 4, ['var d = 4;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.equal(viewModel.viewCells.length, 3);
assert.equal(viewModel.notebookDocument.cells.length, 3);
@@ -258,10 +258,10 @@ function getVisibleCells<T>(cells: T[], hiddenRanges: ICellRange[]) {
}
suite('NotebookViewModel Decorations', () => {
const instantiationService = new TestInstantiationService();
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const blukEditService = instantiationService.get(IBulkEditService);
const undoRedoService = instantiationService.stub(IUndoRedoService, () => { });
instantiationService.spy(IUndoRedoService, 'pushElement');
const undoRedoService = instantiationService.get(IUndoRedoService);
test('tracking range', function () {
withTestNotebook(
@@ -283,7 +283,7 @@ suite('NotebookViewModel Decorations', () => {
end: 2,
});
viewModel.insertCell(0, new TestCell(viewModel.viewType, 5, ['var d = 6;'], 'javascript', CellKind.Code, []), true);
viewModel.insertCell(0, new TestCell(viewModel.viewType, 5, ['var d = 6;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.deepEqual(viewModel.getTrackedRange(trackedId!), {
start: 2,
@@ -297,7 +297,7 @@ suite('NotebookViewModel Decorations', () => {
end: 2
});
viewModel.insertCell(3, new TestCell(viewModel.viewType, 6, ['var d = 7;'], 'javascript', CellKind.Code, []), true);
viewModel.insertCell(3, new TestCell(viewModel.viewType, 6, ['var d = 7;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.deepEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,
@@ -343,14 +343,14 @@ suite('NotebookViewModel Decorations', () => {
end: 3
});
viewModel.insertCell(5, new TestCell(viewModel.viewType, 8, ['var d = 9;'], 'javascript', CellKind.Code, []), true);
viewModel.insertCell(5, new TestCell(viewModel.viewType, 8, ['var d = 9;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.deepEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,
end: 3
});
viewModel.insertCell(4, new TestCell(viewModel.viewType, 9, ['var d = 10;'], 'javascript', CellKind.Code, []), true);
viewModel.insertCell(4, new TestCell(viewModel.viewType, 9, ['var d = 10;'], 'javascript', CellKind.Code, [], textModelService), true);
assert.deepEqual(viewModel.getTrackedRange(trackedId!), {
start: 1,

View File

@@ -10,7 +10,6 @@ import { URI } from 'vs/base/common/uri';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { EditorModel } from 'vs/workbench/common/editor';
import { ICellRange, ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -24,6 +23,16 @@ import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { ICompositeCodeEditor, IEditor } from 'vs/editor/common/editorCommon';
import { NotImplementedError } from 'vs/base/common/errors';
import { Schemas } from 'vs/base/common/network';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
export class TestCell extends NotebookCellTextModel {
constructor(
@@ -32,9 +41,10 @@ export class TestCell extends NotebookCellTextModel {
public source: string[],
language: string,
cellKind: CellKind,
outputs: IProcessedOutput[]
outputs: IProcessedOutput[],
modelService: ITextModelService
) {
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined);
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, modelService);
}
}
@@ -317,12 +327,26 @@ export class NotebookEditorTestModel extends EditorModel implements INotebookEdi
}
}
export function withTestNotebook(instantiationService: IInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string[], string, CellKind, IProcessedOutput[], NotebookCellMetadata][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel, textModel: NotebookTextModel) => void) {
export function setupInstantiationService() {
const instantiationService = new TestInstantiationService();
instantiationService.stub(IUndoRedoService, instantiationService.createInstance(UndoRedoService));
instantiationService.stub(IConfigurationService, new TestConfigurationService());
instantiationService.stub(IThemeService, new TestThemeService());
instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
return instantiationService;
}
export function withTestNotebook(instantiationService: TestInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string[], string, CellKind, IProcessedOutput[], NotebookCellMetadata][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel, textModel: NotebookTextModel) => void) {
const textModelService = instantiationService.get(ITextModelService);
const viewType = 'notebook';
const editor = new TestNotebookEditor();
const notebook = new NotebookTextModel(0, viewType, false, URI.parse('test'), undoRedoService);
const notebook = new NotebookTextModel(0, viewType, false, URI.parse('test'), undoRedoService, textModelService);
notebook.cells = cells.map((cell, index) => {
return new NotebookCellTextModel(notebook.uri, index, cell[0], cell[1], cell[2], cell[3], cell[4]);
return new NotebookCellTextModel(notebook.uri, index, cell[0], cell[1], cell[2], cell[3], cell[4], textModelService);
});
const model = new NotebookEditorTestModel(notebook);
const eventDispatcher = new NotebookEventDispatcher();

View File

@@ -46,6 +46,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { preferencesEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets';
import { Color, RGBA } from 'vs/base/common/color';
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
import { ThemableCheckboxActionViewItem } from 'vs/platform/browser/checkbox';
const $ = DOM.$;
@@ -376,13 +377,17 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditorP
const actionBar = this._register(new ActionBar(this.actionsContainer, {
animated: false,
actionViewItemProvider: (action: IAction) => {
let checkboxViewItem: CheckboxActionViewItem | undefined;
if (action.id === this.sortByPrecedenceAction.id) {
return new CheckboxActionViewItem(null, action);
checkboxViewItem = new ThemableCheckboxActionViewItem(null, action, undefined, this.themeService);
}
if (action.id === this.recordKeysAction.id) {
return new CheckboxActionViewItem(null, action);
else if (action.id === this.recordKeysAction.id) {
checkboxViewItem = new ThemableCheckboxActionViewItem(null, action, undefined, this.themeService);
}
return undefined;
if (checkboxViewItem) {
}
return checkboxViewItem;
}
}));

View File

@@ -415,12 +415,12 @@ export class ClearTerminalAction extends Action {
}
}
export class TerminalLaunchTroubleshootAction extends Action {
export class TerminalLaunchHelpAction extends Action {
constructor(
@IOpenerService private readonly _openerService: IOpenerService
) {
super('workbench.action.terminal.launchHelp', localize('terminalLaunchTroubleshoot', "Troubleshoot"));
super('workbench.action.terminal.launchHelp', localize('terminalLaunchHelp', "Open Help"));
}
async run(): Promise<void> {

View File

@@ -42,7 +42,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IViewsService, IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
import { EnvironmentVariableInfoWidget } from 'vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget';
import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { TerminalLaunchTroubleshootAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
// How long in milliseconds should an average frame take to render for a notification to appear
// which suggests the fallback DOM-based renderer
@@ -997,21 +997,21 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
if (this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH) {
if (commandLine) {
exitCodeMessage = nls.localize('launchFailed.exitCodeAndCommandLine', "The terminal process \"{0}\" failed to launch (exit code: {1})", commandLine, this._exitCode);
exitCodeMessage = nls.localize('launchFailed.exitCodeAndCommandLine', "The terminal process \"{0}\" failed to launch (exit code: {1}).", commandLine, this._exitCode);
break;
}
exitCodeMessage = nls.localize('launchFailed.exitCodeOnly', "The terminal process failed to launch (exit code: {0})", this._exitCode);
exitCodeMessage = nls.localize('launchFailed.exitCodeOnly', "The terminal process failed to launch (exit code: {0}).", this._exitCode);
break;
}
if (commandLine) {
exitCodeMessage = nls.localize('terminated.exitCodeAndCommandLine', "The terminal process \"{0}\" terminated with exit code: {1}", commandLine, this._exitCode);
exitCodeMessage = nls.localize('terminated.exitCodeAndCommandLine', "The terminal process \"{0}\" terminated with exit code: {1}.", commandLine, this._exitCode);
break;
}
exitCodeMessage = nls.localize('terminated.exitCodeOnly', "The terminal process terminated with exit code: {0}", this._exitCode);
exitCodeMessage = nls.localize('terminated.exitCodeOnly', "The terminal process terminated with exit code: {0}.", this._exitCode);
break;
case 'object':
this._exitCode = exitCodeOrError.code;
exitCodeMessage = nls.localize('launchFailed.errorMessage', "The terminal process failed to launch: {0}", exitCodeOrError.message);
exitCodeMessage = nls.localize('launchFailed.errorMessage', "The terminal process failed to launch: {0}.", exitCodeOrError.message);
break;
}
@@ -1045,7 +1045,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._notificationService.notify({
message: exitCodeMessage,
severity: Severity.Error,
actions: { primary: [this._instantiationService.createInstance(TerminalLaunchTroubleshootAction)] }
actions: { primary: [this._instantiationService.createInstance(TerminalLaunchHelpAction)] }
});
} else {
// Log to help surface the error in case users report issues with showExitAlert

View File

@@ -490,10 +490,10 @@ export class EditorService extends Disposable implements EditorServiceImpl {
return toDisposable(() => remove());
}
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][] {
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][] {
const overrides = [];
for (const handler of this.openEditorHandlers) {
const handlers = handler.getEditorOverrides ? handler.getEditorOverrides(resource, options, group).map(val => [handler, val] as [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]) : [];
const handlers = handler.getEditorOverrides ? handler.getEditorOverrides(resource, options, group, id).map(val => [handler, val] as [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]) : [];
overrides.push(...handlers);
}
@@ -1347,7 +1347,7 @@ export class DelegatingEditorService implements IEditorService {
isOpen(editor: IEditorInput | IResourceEditorInput): boolean { return this.editorService.isOpen(editor as IResourceEditorInput /* TS fail */); }
overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable { return this.editorService.overrideOpenEditor(handler); }
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined) { return this.editorService.getEditorOverrides(resource, options, group); }
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined) { return this.editorService.getEditorOverrides(resource, options, group, id); }
invokeWithinEditorContext<T>(fn: (accessor: ServicesAccessor) => T): T { return this.editorService.invokeWithinEditorContext(fn); }

View File

@@ -42,7 +42,7 @@ export async function openEditorWith(
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
const allEditorOverrides = getAllAvailableEditors(resource, options, group, editorService);
const allEditorOverrides = getAllAvailableEditors(resource, id, options, group, editorService);
if (!allEditorOverrides.length) {
return undefined; // {{SQL CARBON EDIT}} strict-null-checks
}
@@ -128,12 +128,13 @@ export const defaultEditorOverrideEntry = Object.freeze({
*/
export function getAllAvailableEditors(
resource: URI,
id: string | undefined,
options: IEditorOptions | ITextEditorOptions | undefined,
group: IEditorGroup,
editorService: IEditorService
): Array<[IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]> {
const fileEditorInputFactory = Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).getFileEditorInputFactory();
const overrides = editorService.getEditorOverrides(resource, options, group);
const overrides = editorService.getEditorOverrides(resource, options, group, id);
if (!overrides.some(([_, entry]) => entry.id === DEFAULT_EDITOR_ID)) {
overrides.unshift([
{

View File

@@ -36,7 +36,7 @@ export interface IOpenEditorOverrideEntry {
export interface IOpenEditorOverrideHandler {
open(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup, context: OpenEditorContext): IOpenEditorOverride | undefined;
getEditorOverrides?(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): IOpenEditorOverrideEntry[];
getEditorOverrides?(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): IOpenEditorOverrideEntry[];
}
export interface IOpenEditorOverride {
@@ -236,7 +236,7 @@ export interface IEditorService {
/**
* Get all available editor overrides for the editor input.
*/
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][];
getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][];
/**
* Allows to override the opening of editors by installing a handler that will

View File

@@ -63,7 +63,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
return {
onSaveError(error: Error, model: ITextFileEditorModel): void {
notificationService.error(localize('genericSaveError', "Failed to save '{0}': {1}", model.name, toErrorMessage(error, false)));
notificationService.error(localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", model.name, toErrorMessage(error, false)));
}
};
})();